From f881ee96f92d498f86271f785d28d09ecab0aee3 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Sat, 29 Jun 2013 18:23:59 -0700 Subject: [PATCH] Tidy up and activate the MSVC Debug Heap --- BeastConfig.h | 97 ++- Builds/VisualStudio2012/RippleD.props | 2 +- Builds/VisualStudio2012/RippleD.vcxproj | 2 +- .../VisualStudio2012/RippleD.vcxproj.filters | 6 +- .../beast/Builds/VisualStudio2012/Beast.props | 1 + .../Builds/VisualStudio2012/BeastConfig.h | 24 +- .../beast/modules/beast_basics/beast_basics.h | 56 -- .../beast_basics/memory/beast_FifoFreeStore.h | 2 +- .../threads/beast_ThreadWithCallQueue.h | 27 +- .../beast/modules/beast_core/beast_core.cpp | 40 +- .../beast/modules/beast_core/beast_core.h | 55 +- .../beast_core/diagnostic/beast_Debug.cpp | 37 +- .../beast_core/diagnostic/beast_Debug.h | 37 +- .../diagnostic/beast_LeakChecked.cpp | 2 +- .../beast_core/diagnostic/beast_Throw.h | 7 +- .../memory/beast_LeakedObjectDetector.h | 2 +- .../beast_core/native/beast_win32_Misc.cpp | 648 ++++++++++++++++++ .../beast_core/native/beast_win32_Threads.cpp | 2 + .../beast_core/system/beast_PlatformDefs.h | 321 ++++----- .../beast_core/system/beast_StandardHeader.h | 2 + .../beast_core/threads/beast_Process.h | 2 - TODO.txt | 6 + modules/ripple_app/ripple_app.cpp | 2 +- src/cpp/ripple/{main.cpp => ripple_Main.cpp} | 22 +- 24 files changed, 1094 insertions(+), 308 deletions(-) create mode 100644 Subtrees/beast/modules/beast_core/native/beast_win32_Misc.cpp rename src/cpp/ripple/{main.cpp => ripple_Main.cpp} (94%) diff --git a/BeastConfig.h b/BeastConfig.h index 6c63d43cdd..2581a865ff 100644 --- a/BeastConfig.h +++ b/BeastConfig.h @@ -20,30 +20,109 @@ #ifndef BEAST_BEASTCONFIG_H_INCLUDED #define BEAST_BEASTCONFIG_H_INCLUDED -// beast_core flags: +/** Configuration file for Beast. -#ifndef BEAST_FORCE_DEBUG - //#define BEAST_FORCE_DEBUG + This sets various configurable options for Beast. In order to compile you + must place a copy of this file in a location where your build environment + can find it, and then customize its contents to suit your needs. + + @file BeastConfig.h +*/ + +//------------------------------------------------------------------------------ + +/** Config: BEAST_FORCE_DEBUG + + Normally, BEAST_DEBUG is set to 1 or 0 based on compiler and project + settings, but if you define this value, you can override this to force it + to be true or false. +*/ +#ifndef BEAST_FORCE_DEBUG +//#define BEAST_FORCE_DEBUG 0 #endif -#ifndef BEAST_LOG_ASSERTIONS - //#define BEAST_LOG_ASSERTIONS 1 +//------------------------------------------------------------------------------ + +/** Config: BEAST_LOG_ASSERTIONS + + If this flag is enabled, the the bassert and bassertfalse macros will always + use Logger::writeToLog() to write a message when an assertion happens. + + Enabling it will also leave this turned on in release builds. When it's + disabled, however, the bassert and bassertfalse macros will not be compiled + in a release build. + + @see bassert, bassertfalse, Logger +*/ +#ifndef BEAST_LOG_ASSERTIONS +//#define BEAST_LOG_ASSERTIONS 0 #endif +//------------------------------------------------------------------------------ + +/** Config: BEAST_CHECK_MEMORY_LEAKS + + Enables a memory-leak check for certain objects when the app terminates. + See the LeakedObjectDetector and LeakChecked classes, and the + BEAST_LEAK_DETECTOR macro for more details about enabling leak checking for + specific classes. +*/ #ifndef BEAST_CHECK_MEMORY_LEAKS #define BEAST_CHECK_MEMORY_LEAKS 1 #endif -#ifndef BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES - //#define BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES +//------------------------------------------------------------------------------ + +/** Config: BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES + + In a Visual C++ build, this can be used to stop the required system libs + being automatically added to the link stage. +*/ +#ifndef BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES +//#define BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES 1 #endif -// beast_basics flags +//------------------------------------------------------------------------------ +/** Config: BEAST_INCLUDE_ZLIB_CODE + + This can be used to disable Beast's embedded 3rd-party zlib code. + You might need to tweak this if you're linking to an external zlib library in your app, + but for normal apps, this option should be left alone. + + If you disable this, you might also want to set a value for BEAST_ZLIB_INCLUDE_PATH, to + specify the path where your zlib headers live. +*/ +#ifndef BEAST_INCLUDE_ZLIB_CODE +//#define BEAST_INCLUDE_ZLIB_CODE 0 +#endif + +#ifndef BEAST_ZLIB_INCLUDE_PATH +#define BEAST_ZLIB_INCLUDE_PATH +#endif + +//------------------------------------------------------------------------------ + +/** Config: BEAST_BOOST_IS_AVAILABLE + + This activates boost specific features and improvements. +*/ +#ifndef BEAST_BOOST_IS_AVAILABLE #define BEAST_BOOST_IS_AVAILABLE 1 +#endif + +/** Bind source configuration. + + Set one of these to manually force a particular implementation of bind(). + If nothing is chosen then beast will use whatever is appropriate for your + environment based on what is available. +*/ +//#define BEAST_BIND_USES_STD 1 +//#define BEAST_BIND_USES_TR1 1 +//#define BEAST_BIND_USES_BOOST 1 #ifndef BEAST_USE_LEAKCHECKED -#define BEAST_USE_LEAKCHECKED BEAST_CHECK_MEMORY_LEAKS +#define BEAST_USE_LEAKCHECKED 1 #endif #endif diff --git a/Builds/VisualStudio2012/RippleD.props b/Builds/VisualStudio2012/RippleD.props index 6a999d5fdb..e3faaffc1e 100644 --- a/Builds/VisualStudio2012/RippleD.props +++ b/Builds/VisualStudio2012/RippleD.props @@ -12,7 +12,7 @@ - _VARIADIC_MAX=10;_WIN32_WINNT=0x0600;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions) + _CRTDBG_MAP_ALLOC;_VARIADIC_MAX=10;_WIN32_WINNT=0x0600;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions) true Level3 $(RepoDir);$(RepoDir)\src\cpp\protobuf\src;$(RepoDir)\src\cpp\protobuf\vsprojects;$(RepoDir)\build\proto;$(RepoDir)\Subtrees;$(RepoDir)\Subtrees\leveldb;$(RepoDir)\Subtrees\leveldb\include;$(RepoDir)\Subtrees\beast;%(AdditionalIncludeDirectories) diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj index 05afef861e..e80c8cd698 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj +++ b/Builds/VisualStudio2012/RippleD.vcxproj @@ -1200,7 +1200,7 @@ true true - + true true true diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters index 0d268090ba..b315793009 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters @@ -582,9 +582,6 @@ 1. Modules\ripple_app\_unfactored - - 1. Modules\ripple_app\_unfactored - 1. Modules\ripple_basics\utility @@ -948,6 +945,9 @@ 1. Modules\ripple_data\protocol + + 1. Modules\ripple_app\_unfactored + diff --git a/Subtrees/beast/Builds/VisualStudio2012/Beast.props b/Subtrees/beast/Builds/VisualStudio2012/Beast.props index ce63ed7590..4e9ca3e391 100644 --- a/Subtrees/beast/Builds/VisualStudio2012/Beast.props +++ b/Subtrees/beast/Builds/VisualStudio2012/Beast.props @@ -6,6 +6,7 @@ Level4 + _CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) diff --git a/Subtrees/beast/Builds/VisualStudio2012/BeastConfig.h b/Subtrees/beast/Builds/VisualStudio2012/BeastConfig.h index 42cf4e65c5..3a86bf5537 100644 --- a/Subtrees/beast/Builds/VisualStudio2012/BeastConfig.h +++ b/Subtrees/beast/Builds/VisualStudio2012/BeastConfig.h @@ -20,6 +20,15 @@ #ifndef BEAST_BEASTCONFIG_H_INCLUDED #define BEAST_BEASTCONFIG_H_INCLUDED +/** Configuration file for Beast. + + This sets various configurable options for Beast. In order to compile you + must place a copy of this file in a location where your build environment + can find it, and then customize its contents to suit your needs. + + @file BeastConfig.h +*/ + //------------------------------------------------------------------------------ /** Config: BEAST_FORCE_DEBUG @@ -94,15 +103,22 @@ //------------------------------------------------------------------------------ -// beast_basics flags +/** Config: BEAST_BOOST_IS_AVAILABLE + This activates boost specific features and improvements. +*/ #ifndef BEAST_BOOST_IS_AVAILABLE #define BEAST_BOOST_IS_AVAILABLE 0 #endif -// Choose one to override default for platform -//#define BEAST_BIND_USES_STD 1 -//#define BEAST_BIND_USES_TR1 1 +/** Bind source configuration. + + Set one of these to manually force a particular implementation of bind(). + If nothing is chosen then beast will use whatever is appropriate for your + environment based on what is available. +*/ +//#define BEAST_BIND_USES_STD 1 +//#define BEAST_BIND_USES_TR1 1 //#define BEAST_BIND_USES_BOOST 1 #ifndef BEAST_USE_LEAKCHECKED diff --git a/Subtrees/beast/modules/beast_basics/beast_basics.h b/Subtrees/beast/modules/beast_basics/beast_basics.h index 5ab2fb0b82..cfbfdfaa28 100644 --- a/Subtrees/beast/modules/beast_basics/beast_basics.h +++ b/Subtrees/beast/modules/beast_basics/beast_basics.h @@ -234,64 +234,8 @@ Some files contain portions of these external projects, licensed separately: #include #endif -#ifdef _CRTDBG_MAP_ALLOC -#error "MSVC C Runtime Debug Macros not supported" -#endif - -// If the MSVC debug heap headers were included, disable -// the macros during the juce include since they conflict. -#ifdef _CRTDBG_MAP_ALLOC -#include -#include -#include - -#pragma push_macro("calloc") -#pragma push_macro("free") -#pragma push_macro("malloc") -#pragma push_macro("realloc") -#pragma push_macro("_recalloc") -#pragma push_macro("_aligned_free") -#pragma push_macro("_aligned_malloc") -#pragma push_macro("_aligned_offset_malloc") -#pragma push_macro("_aligned_realloc") -#pragma push_macro("_aligned_recalloc") -#pragma push_macro("_aligned_offset_realloc") -#pragma push_macro("_aligned_offset_recalloc") -#pragma push_macro("_aligned_msize") - -#undef calloc -#undef free -#undef malloc -#undef realloc -#undef _recalloc -#undef _aligned_free -#undef _aligned_malloc -#undef _aligned_offset_malloc -#undef _aligned_realloc -#undef _aligned_recalloc -#undef _aligned_offset_realloc -#undef _aligned_offset_recalloc -#undef _aligned_msize -#endif - #include "../beast_core/beast_core.h" -#ifdef _CRTDBG_MAP_ALLOC -#pragma pop_macro("_aligned_msize") -#pragma pop_macro("_aligned_offset_recalloc") -#pragma pop_macro("_aligned_offset_realloc") -#pragma pop_macro("_aligned_recalloc") -#pragma pop_macro("_aligned_realloc") -#pragma pop_macro("_aligned_offset_malloc") -#pragma pop_macro("_aligned_malloc") -#pragma pop_macro("_aligned_free") -#pragma pop_macro("_recalloc") -#pragma pop_macro("realloc") -#pragma pop_macro("malloc") -#pragma pop_macro("free") -#pragma pop_macro("calloc") -#endif - /** The Beast namespace. This namespace contains all Beast symbols. diff --git a/Subtrees/beast/modules/beast_basics/memory/beast_FifoFreeStore.h b/Subtrees/beast/modules/beast_basics/memory/beast_FifoFreeStore.h index fafa2eeb26..92c7cbe795 100644 --- a/Subtrees/beast/modules/beast_basics/memory/beast_FifoFreeStore.h +++ b/Subtrees/beast/modules/beast_basics/memory/beast_FifoFreeStore.h @@ -24,7 +24,7 @@ @ingroup beast_concurrent */ -#if BEAST_BOOST_IS_AVAILABLE +#if 0//BEAST_BOOST_IS_AVAILABLE typedef FifoFreeStoreWithTLS FifoFreeStoreType; #else typedef FifoFreeStoreWithoutTLS FifoFreeStoreType; diff --git a/Subtrees/beast/modules/beast_basics/threads/beast_ThreadWithCallQueue.h b/Subtrees/beast/modules/beast_basics/threads/beast_ThreadWithCallQueue.h index c5fb1f6219..ef6f153b6b 100644 --- a/Subtrees/beast/modules/beast_basics/threads/beast_ThreadWithCallQueue.h +++ b/Subtrees/beast/modules/beast_basics/threads/beast_ThreadWithCallQueue.h @@ -20,29 +20,28 @@ #ifndef BEAST_THREADWITHCALLQUEUE_BEASTHEADER #define BEAST_THREADWITHCALLQUEUE_BEASTHEADER -/*============================================================================*/ -/** - An InterruptibleThread with a CallQueue. +/** An InterruptibleThread with a CallQueue. - This combines an InterruptibleThread with a CallQueue, allowing functors to - be queued for asynchronous execution on the thread. + This combines an InterruptibleThread with a CallQueue, allowing functors to + be queued for asynchronous execution on the thread. - The thread runs an optional user-defined idle function, which must regularly - check for an interruption using the InterruptibleThread interface. When an - interruption is signaled, the idle function returns and the CallQueue is - synchronized. Then, the idle function is resumed. + The thread runs an optional user-defined idle function, which must regularly + check for an interruption using the InterruptibleThread interface. When an + interruption is signaled, the idle function returns and the CallQueue is + synchronized. Then, the idle function is resumed. - When the ThreadWithCallQueue first starts up, an optional user-defined - initialization function is executed on the thread. When the thread exits, - a user-defined exit function may be executed on the thread. + When the ThreadWithCallQueue first starts up, an optional user-defined + initialization function is executed on the thread. When the thread exits, + a user-defined exit function may be executed on the thread. - @see CallQueue + @see CallQueue - @ingroup beast_concurrent + @ingroup beast_concurrent */ class BEAST_API ThreadWithCallQueue : public CallQueue , private InterruptibleThread::EntryPoint + , LeakChecked { public: /** Entry points for a ThreadWithCallQueue. diff --git a/Subtrees/beast/modules/beast_core/beast_core.cpp b/Subtrees/beast/modules/beast_core/beast_core.cpp index f06429c246..be3907d179 100644 --- a/Subtrees/beast/modules/beast_core/beast_core.cpp +++ b/Subtrees/beast/modules/beast_core/beast_core.cpp @@ -102,8 +102,39 @@ #include #endif +//------------------------------------------------------------------------------ + +// If the MSVC debug heap headers were included, disable +// the macros during the juce include since they conflict. +#ifdef _CRTDBG_MAP_ALLOC +#pragma push_macro("calloc") +#pragma push_macro("free") +#pragma push_macro("malloc") +#pragma push_macro("realloc") +#pragma push_macro("_recalloc") +#pragma push_macro("_aligned_free") +#pragma push_macro("_aligned_malloc") +#pragma push_macro("_aligned_offset_malloc") +#pragma push_macro("_aligned_realloc") +#pragma push_macro("_aligned_recalloc") +#pragma push_macro("_aligned_offset_realloc") +#pragma push_macro("_aligned_offset_recalloc") +#pragma push_macro("_aligned_msize") +#undef calloc +#undef free +#undef malloc +#undef realloc +#undef _recalloc +#undef _aligned_free +#undef _aligned_malloc +#undef _aligned_offset_malloc +#undef _aligned_realloc +#undef _aligned_recalloc +#undef _aligned_offset_realloc +#undef _aligned_offset_recalloc +#undef _aligned_msize +#endif -//============================================================================== namespace beast { @@ -184,7 +215,6 @@ namespace beast #include "zip/beast_GZIPCompressorOutputStream.cpp" #include "zip/beast_ZipFile.cpp" -//============================================================================== #if BEAST_MAC || BEAST_IOS #include "native/beast_osx_ObjCHelpers.h" #endif @@ -198,7 +228,6 @@ namespace beast #include "native/beast_posix_NamedPipe.cpp" #endif -//============================================================================== #if BEAST_MAC || BEAST_IOS #include "native/beast_mac_Files.mm" #include "native/beast_mac_Network.mm" @@ -206,7 +235,6 @@ namespace beast #include "native/beast_mac_SystemStats.mm" #include "native/beast_mac_Threads.mm" -//============================================================================== #elif BEAST_WINDOWS #include "native/beast_win32_ComSmartPtr.h" #include "native/beast_win32_Files.cpp" @@ -215,21 +243,18 @@ namespace beast #include "native/beast_win32_SystemStats.cpp" #include "native/beast_win32_Threads.cpp" -//============================================================================== #elif BEAST_LINUX #include "native/beast_linux_Files.cpp" #include "native/beast_linux_Network.cpp" #include "native/beast_linux_SystemStats.cpp" #include "native/beast_linux_Threads.cpp" -//============================================================================== #elif BEAST_BSD #include "native/beast_bsd_Files.cpp" #include "native/beast_bsd_Network.cpp" #include "native/beast_bsd_SystemStats.cpp" #include "native/beast_bsd_Threads.cpp" -//============================================================================== #elif BEAST_ANDROID #include "native/beast_android_Files.cpp" #include "native/beast_android_Misc.cpp" @@ -260,4 +285,3 @@ boost::arg<9> _9; } } #endif - diff --git a/Subtrees/beast/modules/beast_core/beast_core.h b/Subtrees/beast/modules/beast_core/beast_core.h index 258bc116da..0d1d6e1575 100644 --- a/Subtrees/beast/modules/beast_core/beast_core.h +++ b/Subtrees/beast/modules/beast_core/beast_core.h @@ -150,6 +150,8 @@ using namespace placeholders; //------------------------------------------------------------------------------ +#include "system/beast_StandardHeader.h" + #if BEAST_MSVC # pragma warning (disable: 4251) // (DLL build warning, must be disabled before pushing the warning state) # pragma warning (push) @@ -159,7 +161,36 @@ using namespace placeholders; # endif #endif -#include "system/beast_StandardHeader.h" +// If the MSVC debug heap headers were included, disable +// the macros during the juce include since they conflict. +#ifdef _CRTDBG_MAP_ALLOC +#pragma push_macro("calloc") +#pragma push_macro("free") +#pragma push_macro("malloc") +#pragma push_macro("realloc") +#pragma push_macro("_recalloc") +#pragma push_macro("_aligned_free") +#pragma push_macro("_aligned_malloc") +#pragma push_macro("_aligned_offset_malloc") +#pragma push_macro("_aligned_realloc") +#pragma push_macro("_aligned_recalloc") +#pragma push_macro("_aligned_offset_realloc") +#pragma push_macro("_aligned_offset_recalloc") +#pragma push_macro("_aligned_msize") +#undef calloc +#undef free +#undef malloc +#undef realloc +#undef _recalloc +#undef _aligned_free +#undef _aligned_malloc +#undef _aligned_offset_malloc +#undef _aligned_realloc +#undef _aligned_recalloc +#undef _aligned_offset_realloc +#undef _aligned_offset_recalloc +#undef _aligned_msize +#endif namespace beast { @@ -291,8 +322,26 @@ namespace beast } -#if BEAST_MSVC -# pragma warning (pop) +#ifdef _CRTDBG_MAP_ALLOC +#pragma pop_macro("_aligned_msize") +#pragma pop_macro("_aligned_offset_recalloc") +#pragma pop_macro("_aligned_offset_realloc") +#pragma pop_macro("_aligned_recalloc") +#pragma pop_macro("_aligned_realloc") +#pragma pop_macro("_aligned_offset_malloc") +#pragma pop_macro("_aligned_malloc") +#pragma pop_macro("_aligned_free") +#pragma pop_macro("_recalloc") +#pragma pop_macro("realloc") +#pragma pop_macro("malloc") +#pragma pop_macro("free") +#pragma pop_macro("calloc") #endif +#if BEAST_MSVC +#pragma warning (pop) +#endif + +//------------------------------------------------------------------------------ + #endif diff --git a/Subtrees/beast/modules/beast_core/diagnostic/beast_Debug.cpp b/Subtrees/beast/modules/beast_core/diagnostic/beast_Debug.cpp index 9cf37f37b1..d8e1245d43 100644 --- a/Subtrees/beast/modules/beast_core/diagnostic/beast_Debug.cpp +++ b/Subtrees/beast/modules/beast_core/diagnostic/beast_Debug.cpp @@ -20,35 +20,23 @@ namespace Debug { -//------------------------------------------------------------------------------ - -bool isDebuggerAttached () -{ - return beast_isRunningUnderDebugger (); -} - -//------------------------------------------------------------------------------ - -#if BEAST_DEBUG && defined (beast_breakDebugger) void breakPoint () { - if (isDebuggerAttached ()) +#if BEAST_DEBUG + if (beast_isRunningUnderDebugger ()) beast_breakDebugger; -} #else -void breakPoint () -{ - bassertfalse -} + bassertfalse; #endif +} -//---------------------------------------------------------------------------- +//------------------------------------------------------------------------------ #if BEAST_MSVC && defined (_DEBUG) -void setHeapAlwaysCheck (bool bAlwaysCheck) +void setAlwaysCheckHeap (bool bAlwaysCheck) { int flags = _CrtSetDbgFlag (_CRTDBG_REPORT_FLAG); @@ -78,14 +66,21 @@ void setHeapReportLeaks (bool bReportLeaks) _CrtSetDbgFlag (flags); } +void reportLeaks () +{ + _CrtDumpMemoryLeaks (); +} + void checkHeap () { _CrtCheckMemory (); } +//------------------------------------------------------------------------------ + #else -void setHeapAlwaysCheck (bool) +void setAlwaysCheckHeap (bool) { } @@ -97,6 +92,10 @@ void setHeapReportLeaks (bool) { } +void reportLeaks () +{ +} + void checkHeap () { } diff --git a/Subtrees/beast/modules/beast_core/diagnostic/beast_Debug.h b/Subtrees/beast/modules/beast_core/diagnostic/beast_Debug.h index 5382e37e34..c6013d46c5 100644 --- a/Subtrees/beast/modules/beast_core/diagnostic/beast_Debug.h +++ b/Subtrees/beast/modules/beast_core/diagnostic/beast_Debug.h @@ -17,18 +17,18 @@ */ //============================================================================== -#ifndef BEAST_DEBUG_BEASTHEADER -#define BEAST_DEBUG_BEASTHEADER +#ifndef BEAST_DEBUG_H_INCLUDED +#define BEAST_DEBUG_H_INCLUDED // Auxiliary outines for debugging namespace Debug { -// Returns true if a debugger is attached, for any build. -extern bool isDebuggerAttached (); +/** Break to debugger if a debugger is attached to a debug build. -// Breaks to the debugger if a debugger is attached. + Does nothing if no debugger is attached, or the build is not a debug build. +*/ extern void breakPoint (); // VFALCO NOTE IS THIS REALLY THE RIGHT PLACE FOR THESE?? @@ -46,9 +46,34 @@ String stringToCommandLine (const String& s); // that can contain newlines and double quotes. String commandLineToString (const String& commandLine); -extern void setHeapAlwaysCheck (bool bAlwaysCheck); +// +// These control the MSVC C Runtime Debug heap. +// +// The calls currently do nothing on other platforms. +// + +/** Calls checkHeap() at every allocation and deallocation. +*/ +extern void setAlwaysCheckHeap (bool bAlwaysCheck); + +/** Keep freed memory blocks in the heap's linked list, assign them the + _FREE_BLOCK type, and fill them with the byte value 0xDD. +*/ extern void setHeapDelayedFree (bool bDelayedFree); + +/** Perform automatic leak checking at program exit through a call to + dumpMemoryLeaks() and generate an error report if the application + failed to free all the memory it allocated. +*/ extern void setHeapReportLeaks (bool bReportLeaks); + +/** Report all memory blocks which have not been freed. +*/ +extern void reportLeaks (); + +/** Confirms the integrity of the memory blocks allocated in the + debug heap (debug version only. +*/ extern void checkHeap (); } diff --git a/Subtrees/beast/modules/beast_core/diagnostic/beast_LeakChecked.cpp b/Subtrees/beast/modules/beast_core/diagnostic/beast_LeakChecked.cpp index 0cf686ec78..0688c3cd28 100644 --- a/Subtrees/beast/modules/beast_core/diagnostic/beast_LeakChecked.cpp +++ b/Subtrees/beast/modules/beast_core/diagnostic/beast_LeakChecked.cpp @@ -76,7 +76,7 @@ void LeakCheckedBase::CounterBase::detectLeaks () if (count > 0) { - bassertfalse; + //bassertfalse; DBG ("[LEAK] " << count << " of " << getClassName ()); } } diff --git a/Subtrees/beast/modules/beast_core/diagnostic/beast_Throw.h b/Subtrees/beast/modules/beast_core/diagnostic/beast_Throw.h index e5b3f94579..a488193fef 100644 --- a/Subtrees/beast/modules/beast_core/diagnostic/beast_Throw.h +++ b/Subtrees/beast/modules/beast_core/diagnostic/beast_Throw.h @@ -17,10 +17,8 @@ */ //============================================================================== -#ifndef BEAST_THROW_BEASTHEADER -#define BEAST_THROW_BEASTHEADER - -#include "beast_Debug.h" +#ifndef BEAST_THROW_H_INCLUDED +#define BEAST_THROW_H_INCLUDED /** Throw an exception, with a debugger hook. @@ -30,7 +28,6 @@ template inline void Throw (Exception const& e) { - // VFALCO TODO Replace with straight JUCE equivalent Debug::breakPoint (); throw e; diff --git a/Subtrees/beast/modules/beast_core/memory/beast_LeakedObjectDetector.h b/Subtrees/beast/modules/beast_core/memory/beast_LeakedObjectDetector.h index eaa01b15df..cc45e61dc7 100644 --- a/Subtrees/beast/modules/beast_core/memory/beast_LeakedObjectDetector.h +++ b/Subtrees/beast/modules/beast_core/memory/beast_LeakedObjectDetector.h @@ -90,7 +90,7 @@ private: your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays, ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs! */ - bassertfalse; + //bassertfalse; } } diff --git a/Subtrees/beast/modules/beast_core/native/beast_win32_Misc.cpp b/Subtrees/beast/modules/beast_core/native/beast_win32_Misc.cpp new file mode 100644 index 0000000000..4a2f785a22 --- /dev/null +++ b/Subtrees/beast/modules/beast_core/native/beast_win32_Misc.cpp @@ -0,0 +1,648 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Portions of this file are from JUCE. + Copyright (c) 2013 - Raw Material Software Ltd. + Please visit http://www.juce.com + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +HWND beast_messageWindowHandle = 0; // (this is used by other parts of the codebase) + +//============================================================================== +#if ! BEAST_USE_INTRINSICS +// In newer compilers, the inline versions of these are used (in beast_Atomic.h), but in +// older ones we have to actually call the ops as win32 functions.. +long beast_InterlockedExchange (volatile long* a, long b) noexcept { return InterlockedExchange (a, b); } +long beast_InterlockedIncrement (volatile long* a) noexcept { return InterlockedIncrement (a); } +long beast_InterlockedDecrement (volatile long* a) noexcept { return InterlockedDecrement (a); } +long beast_InterlockedExchangeAdd (volatile long* a, long b) noexcept { return InterlockedExchangeAdd (a, b); } +long beast_InterlockedCompareExchange (volatile long* a, long b, long c) noexcept { return InterlockedCompareExchange (a, b, c); } + +__int64 beast_InterlockedCompareExchange64 (volatile __int64* value, __int64 newValue, __int64 valueToCompare) noexcept +{ + bassertfalse; // This operation isn't available in old MS compiler versions! + + __int64 oldValue = *value; + if (oldValue == valueToCompare) + *value = newValue; + + return oldValue; +} + +#endif + +//============================================================================== +CriticalSection::CriticalSection() noexcept +{ + // (just to check the MS haven't changed this structure and broken things...) + #if BEAST_VC7_OR_EARLIER + static_bassert (sizeof (CRITICAL_SECTION) <= 24); + #else + static_bassert (sizeof (CRITICAL_SECTION) <= sizeof (internal)); + #endif + + InitializeCriticalSection ((CRITICAL_SECTION*) internal); +} + +CriticalSection::~CriticalSection() noexcept +{ + DeleteCriticalSection ((CRITICAL_SECTION*) internal); +} + +void CriticalSection::enter() const noexcept +{ + EnterCriticalSection ((CRITICAL_SECTION*) internal); +} + +bool CriticalSection::tryEnter() const noexcept +{ + return TryEnterCriticalSection ((CRITICAL_SECTION*) internal) != FALSE; +} + +void CriticalSection::exit() const noexcept +{ + LeaveCriticalSection ((CRITICAL_SECTION*) internal); +} + +//============================================================================== +WaitableEvent::WaitableEvent (const bool manualReset) noexcept + : internal (CreateEvent (0, manualReset ? TRUE : FALSE, FALSE, 0)) +{ +} + +WaitableEvent::~WaitableEvent() noexcept +{ + CloseHandle (internal); +} + +bool WaitableEvent::wait (const int timeOutMillisecs) const noexcept +{ + return WaitForSingleObject (internal, (DWORD) timeOutMillisecs) == WAIT_OBJECT_0; +} + +void WaitableEvent::signal() const noexcept +{ + SetEvent (internal); +} + +void WaitableEvent::reset() const noexcept +{ + ResetEvent (internal); +} + +//============================================================================== +void BEAST_API beast_threadEntryPoint (void*); + +static unsigned int __stdcall threadEntryProc (void* userData) +{ + if (beast_messageWindowHandle != 0) + AttachThreadInput (GetWindowThreadProcessId (beast_messageWindowHandle, 0), + GetCurrentThreadId(), TRUE); + + beast_threadEntryPoint (userData); + + _endthreadex (0); + return 0; +} + +void Thread::launchThread() +{ + unsigned int newThreadId; + threadHandle = (void*) _beginthreadex (0, 0, &threadEntryProc, this, 0, &newThreadId); + threadId = (ThreadID) newThreadId; +} + +void Thread::closeThreadHandle() +{ + CloseHandle ((HANDLE) threadHandle); + threadId = 0; + threadHandle = 0; +} + +void Thread::killThread() +{ + if (threadHandle != 0) + { + #if BEAST_DEBUG + OutputDebugStringA ("** Warning - Forced thread termination **\n"); + #endif + TerminateThread (threadHandle, 0); + } +} + +void Thread::setCurrentThreadName (const String& name) +{ + #if BEAST_DEBUG && BEAST_MSVC + struct + { + DWORD dwType; + LPCSTR szName; + DWORD dwThreadID; + DWORD dwFlags; + } info; + + info.dwType = 0x1000; + info.szName = name.toUTF8(); + info.dwThreadID = GetCurrentThreadId(); + info.dwFlags = 0; + + __try + { + RaiseException (0x406d1388 /*MS_VC_EXCEPTION*/, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info); + } + __except (EXCEPTION_CONTINUE_EXECUTION) + {} + #else + (void) name; + #endif +} + +Thread::ThreadID Thread::getCurrentThreadId() +{ + return (ThreadID) (pointer_sized_int) GetCurrentThreadId(); +} + +bool Thread::setThreadPriority (void* handle, int priority) +{ + int pri = THREAD_PRIORITY_TIME_CRITICAL; + + if (priority < 1) pri = THREAD_PRIORITY_IDLE; + else if (priority < 2) pri = THREAD_PRIORITY_LOWEST; + else if (priority < 5) pri = THREAD_PRIORITY_BELOW_NORMAL; + else if (priority < 7) pri = THREAD_PRIORITY_NORMAL; + else if (priority < 9) pri = THREAD_PRIORITY_ABOVE_NORMAL; + else if (priority < 10) pri = THREAD_PRIORITY_HIGHEST; + + if (handle == 0) + handle = GetCurrentThread(); + + return SetThreadPriority (handle, pri) != FALSE; +} + +void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) +{ + SetThreadAffinityMask (GetCurrentThread(), affinityMask); +} + +//============================================================================== +struct SleepEvent +{ + SleepEvent() noexcept + : handle (CreateEvent (nullptr, FALSE, FALSE, + #if BEAST_DEBUG + _T("BEAST Sleep Event"))) + #else + nullptr)) + #endif + {} + + ~SleepEvent() noexcept + { + CloseHandle (handle); + handle = 0; + } + + HANDLE handle; +}; + +static SleepEvent sleepEvent; + +void BEAST_CALLTYPE Thread::sleep (const int millisecs) +{ + if (millisecs >= 10 || sleepEvent.handle == 0) + { + Sleep ((DWORD) millisecs); + } + else + { + // unlike Sleep() this is guaranteed to return to the current thread after + // the time expires, so we'll use this for short waits, which are more likely + // to need to be accurate + WaitForSingleObject (sleepEvent.handle, (DWORD) millisecs); + } +} + +void Thread::yield() +{ + Sleep (0); +} + +//============================================================================== +static int lastProcessPriority = -1; + +// called by WindowDriver because Windows does weird things to process priority +// when you swap apps, and this forces an update when the app is brought to the front. +void beast_repeatLastProcessPriority() +{ + if (lastProcessPriority >= 0) // (avoid changing this if it's not been explicitly set by the app..) + { + DWORD p; + + switch (lastProcessPriority) + { + case Process::LowPriority: p = IDLE_PRIORITY_CLASS; break; + case Process::NormalPriority: p = NORMAL_PRIORITY_CLASS; break; + case Process::HighPriority: p = HIGH_PRIORITY_CLASS; break; + case Process::RealtimePriority: p = REALTIME_PRIORITY_CLASS; break; + default: bassertfalse; return; // bad priority value + } + + SetPriorityClass (GetCurrentProcess(), p); + } +} + +void Process::setPriority (ProcessPriority prior) +{ + if (lastProcessPriority != (int) prior) + { + lastProcessPriority = (int) prior; + beast_repeatLastProcessPriority(); + } +} + +BEAST_API bool BEAST_CALLTYPE beast_isRunningUnderDebugger() +{ + return IsDebuggerPresent() != FALSE; +} + +bool BEAST_CALLTYPE Process::isRunningUnderDebugger() +{ + return beast_isRunningUnderDebugger(); +} + +BEAST_API void BEAST_CALLTYPE Process::breakPoint () +{ +#if BEAST_DEBUG + if (beast_isRunningUnderDebugger ()) + beast_breakDebugger; + +#else + bassertfalse; + +#endif +} + +//------------------------------------------------------------------------------ + +static void* currentModuleHandle = nullptr; + +void* Process::getCurrentModuleInstanceHandle() noexcept +{ + if (currentModuleHandle == nullptr) + currentModuleHandle = GetModuleHandleA (nullptr); + + return currentModuleHandle; +} + +void Process::setCurrentModuleInstanceHandle (void* const newHandle) noexcept +{ + currentModuleHandle = newHandle; +} + +void Process::raisePrivilege() +{ + bassertfalse; // xxx not implemented +} + +void Process::lowerPrivilege() +{ + bassertfalse; // xxx not implemented +} + +void Process::terminate() +{ + #if BEAST_MSVC && BEAST_CHECK_MEMORY_LEAKS + _CrtDumpMemoryLeaks(); + #endif + + // bullet in the head in case there's a problem shutting down.. + ExitProcess (0); +} + +bool beast_isRunningInWine() +{ + HMODULE ntdll = GetModuleHandleA ("ntdll"); + return ntdll != 0 && GetProcAddress (ntdll, "wine_get_version") != nullptr; +} + +//============================================================================== +bool DynamicLibrary::open (const String& name) +{ + close(); + + BEAST_TRY + { + handle = LoadLibrary (name.toWideCharPointer()); + } + BEAST_CATCH_ALL + + return handle != nullptr; +} + +void DynamicLibrary::close() +{ + BEAST_TRY + { + if (handle != nullptr) + { + FreeLibrary ((HMODULE) handle); + handle = nullptr; + } + } + BEAST_CATCH_ALL +} + +void* DynamicLibrary::getFunction (const String& functionName) noexcept +{ + return handle != nullptr ? (void*) GetProcAddress ((HMODULE) handle, functionName.toUTF8()) // (void* cast is required for mingw) + : nullptr; +} + + +//============================================================================== +class InterProcessLock::Pimpl +{ +public: + Pimpl (String name, const int timeOutMillisecs) + : handle (0), refCount (1) + { + name = name.replaceCharacter ('\\', '/'); + handle = CreateMutexW (0, TRUE, ("Global\\" + name).toWideCharPointer()); + + // Not 100% sure why a global mutex sometimes can't be allocated, but if it fails, fall back to + // a local one. (A local one also sometimes fails on other machines so neither type appears to be + // universally reliable) + if (handle == 0) + handle = CreateMutexW (0, TRUE, ("Local\\" + name).toWideCharPointer()); + + if (handle != 0 && GetLastError() == ERROR_ALREADY_EXISTS) + { + if (timeOutMillisecs == 0) + { + close(); + return; + } + + switch (WaitForSingleObject (handle, timeOutMillisecs < 0 ? INFINITE : timeOutMillisecs)) + { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + break; + + case WAIT_TIMEOUT: + default: + close(); + break; + } + } + } + + ~Pimpl() + { + close(); + } + + void close() + { + if (handle != 0) + { + ReleaseMutex (handle); + CloseHandle (handle); + handle = 0; + } + } + + HANDLE handle; + int refCount; +}; + +InterProcessLock::InterProcessLock (const String& name_) + : name (name_) +{ +} + +InterProcessLock::~InterProcessLock() +{ +} + +bool InterProcessLock::enter (const int timeOutMillisecs) +{ + const ScopedLock sl (lock); + + if (pimpl == nullptr) + { + pimpl = new Pimpl (name, timeOutMillisecs); + + if (pimpl->handle == 0) + pimpl = nullptr; + } + else + { + pimpl->refCount++; + } + + return pimpl != nullptr; +} + +void InterProcessLock::exit() +{ + const ScopedLock sl (lock); + + // Trying to release the lock too many times! + bassert (pimpl != nullptr); + + if (pimpl != nullptr && --(pimpl->refCount) == 0) + pimpl = nullptr; +} + +//============================================================================== +class ChildProcess::ActiveProcess +{ +public: + ActiveProcess (const String& command) + : ok (false), readPipe (0), writePipe (0) + { + SECURITY_ATTRIBUTES securityAtts = { 0 }; + securityAtts.nLength = sizeof (securityAtts); + securityAtts.bInheritHandle = TRUE; + + if (CreatePipe (&readPipe, &writePipe, &securityAtts, 0) + && SetHandleInformation (readPipe, HANDLE_FLAG_INHERIT, 0)) + { + STARTUPINFOW startupInfo = { 0 }; + startupInfo.cb = sizeof (startupInfo); + startupInfo.hStdError = writePipe; + startupInfo.hStdOutput = writePipe; + startupInfo.dwFlags = STARTF_USESTDHANDLES; + + ok = CreateProcess (nullptr, const_cast (command.toWideCharPointer()), + nullptr, nullptr, TRUE, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, + nullptr, nullptr, &startupInfo, &processInfo) != FALSE; + } + } + + ~ActiveProcess() + { + if (ok) + { + CloseHandle (processInfo.hThread); + CloseHandle (processInfo.hProcess); + } + + if (readPipe != 0) + CloseHandle (readPipe); + + if (writePipe != 0) + CloseHandle (writePipe); + } + + bool isRunning() const + { + return WaitForSingleObject (processInfo.hProcess, 0) != WAIT_OBJECT_0; + } + + int read (void* dest, int numNeeded) const + { + int total = 0; + + while (ok && numNeeded > 0) + { + DWORD available = 0; + + if (! PeekNamedPipe ((HANDLE) readPipe, nullptr, 0, nullptr, &available, nullptr)) + break; + + const int numToDo = bmin ((int) available, numNeeded); + + if (available == 0) + { + if (! isRunning()) + break; + + Thread::yield(); + } + else + { + DWORD numRead = 0; + if (! ReadFile ((HANDLE) readPipe, dest, numToDo, &numRead, nullptr)) + break; + + total += numRead; + dest = addBytesToPointer (dest, numRead); + numNeeded -= numRead; + } + } + + return total; + } + + bool killProcess() const + { + return TerminateProcess (processInfo.hProcess, 0) != FALSE; + } + + bool ok; + +private: + HANDLE readPipe, writePipe; + PROCESS_INFORMATION processInfo; + + BEAST_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ActiveProcess) +}; + +bool ChildProcess::start (const String& command) +{ + activeProcess = new ActiveProcess (command); + + if (! activeProcess->ok) + activeProcess = nullptr; + + return activeProcess != nullptr; +} + +bool ChildProcess::start (const StringArray& args) +{ + return start (args.joinIntoString (" ")); +} + +bool ChildProcess::isRunning() const +{ + return activeProcess != nullptr && activeProcess->isRunning(); +} + +int ChildProcess::readProcessOutput (void* dest, int numBytes) +{ + return activeProcess != nullptr ? activeProcess->read (dest, numBytes) : 0; +} + +bool ChildProcess::kill() +{ + return activeProcess == nullptr || activeProcess->killProcess(); +} + +//============================================================================== +struct HighResolutionTimer::Pimpl +{ + Pimpl (HighResolutionTimer& t) noexcept : owner (t), periodMs (0) + { + } + + ~Pimpl() + { + bassert (periodMs == 0); + } + + void start (int newPeriod) + { + if (newPeriod != periodMs) + { + stop(); + periodMs = newPeriod; + + TIMECAPS tc; + if (timeGetDevCaps (&tc, sizeof (tc)) == TIMERR_NOERROR) + { + const int actualPeriod = blimit ((int) tc.wPeriodMin, (int) tc.wPeriodMax, newPeriod); + + timerID = timeSetEvent (actualPeriod, tc.wPeriodMin, callbackFunction, (DWORD_PTR) this, + TIME_PERIODIC | TIME_CALLBACK_FUNCTION | 0x100 /*TIME_KILL_SYNCHRONOUS*/); + } + } + } + + void stop() + { + periodMs = 0; + timeKillEvent (timerID); + } + + HighResolutionTimer& owner; + int periodMs; + +private: + unsigned int timerID; + + static void __stdcall callbackFunction (UINT, UINT, DWORD_PTR userInfo, DWORD_PTR, DWORD_PTR) + { + if (Pimpl* const timer = reinterpret_cast (userInfo)) + if (timer->periodMs != 0) + timer->owner.hiResTimerCallback(); + } + + BEAST_DECLARE_NON_COPYABLE (Pimpl) +}; diff --git a/Subtrees/beast/modules/beast_core/native/beast_win32_Threads.cpp b/Subtrees/beast/modules/beast_core/native/beast_win32_Threads.cpp index 2274bec659..937069576a 100644 --- a/Subtrees/beast/modules/beast_core/native/beast_win32_Threads.cpp +++ b/Subtrees/beast/modules/beast_core/native/beast_win32_Threads.cpp @@ -285,6 +285,8 @@ bool BEAST_CALLTYPE Process::isRunningUnderDebugger() return beast_isRunningUnderDebugger(); } +//------------------------------------------------------------------------------ + static void* currentModuleHandle = nullptr; void* Process::getCurrentModuleInstanceHandle() noexcept diff --git a/Subtrees/beast/modules/beast_core/system/beast_PlatformDefs.h b/Subtrees/beast/modules/beast_core/system/beast_PlatformDefs.h index 59b93ba3c0..63323de40e 100644 --- a/Subtrees/beast/modules/beast_core/system/beast_PlatformDefs.h +++ b/Subtrees/beast/modules/beast_core/system/beast_PlatformDefs.h @@ -24,118 +24,113 @@ #ifndef BEAST_PLATFORMDEFS_BEASTHEADER #define BEAST_PLATFORMDEFS_BEASTHEADER -//============================================================================== -/* This file defines miscellaneous macros for debugging, assertions, etc. -*/ +// This file defines miscellaneous macros for debugging, assertions, etc. -//============================================================================== #ifdef BEAST_FORCE_DEBUG - #undef BEAST_DEBUG - - #if BEAST_FORCE_DEBUG - #define BEAST_DEBUG 1 - #endif +# undef BEAST_DEBUG +# if BEAST_FORCE_DEBUG +# define BEAST_DEBUG 1 +# endif #endif -/** This macro defines the C calling convention used as the standard for Beast calls. */ +/** This macro defines the C calling convention used as the standard for Beast calls. +*/ #if BEAST_MSVC - #define BEAST_CALLTYPE __stdcall - #define BEAST_CDECL __cdecl +# define BEAST_CALLTYPE __stdcall +# define BEAST_CDECL __cdecl #else - #define BEAST_CALLTYPE - #define BEAST_CDECL +# define BEAST_CALLTYPE +# define BEAST_CDECL #endif -//============================================================================== // Debugging and assertion macros #if BEAST_LOG_ASSERTIONS || BEAST_DEBUG - #define beast_LogCurrentAssertion beast::logAssertion (__FILE__, __LINE__); +#define beast_LogCurrentAssertion beast::logAssertion (__FILE__, __LINE__); #else - #define beast_LogCurrentAssertion +#define beast_LogCurrentAssertion #endif -//============================================================================== #if BEAST_IOS || BEAST_LINUX || BEAST_ANDROID || BEAST_PPC - /** This will try to break into the debugger if the app is currently being debugged. - If called by an app that's not being debugged, the behaiour isn't defined - it may crash or not, depending - on the platform. - @see bassert() - */ - #define beast_breakDebugger { ::kill (0, SIGTRAP); } +/** This will try to break into the debugger if the app is currently being debugged. + If called by an app that's not being debugged, the behaiour isn't defined - it may crash or not, depending + on the platform. + @see bassert() +*/ +# define beast_breakDebugger { ::kill (0, SIGTRAP); } #elif BEAST_USE_INTRINSICS - #ifndef __INTEL_COMPILER - #pragma intrinsic (__debugbreak) - #endif - #define beast_breakDebugger { __debugbreak(); } +# ifndef __INTEL_COMPILER +# pragma intrinsic (__debugbreak) +# endif +# define beast_breakDebugger { __debugbreak(); } #elif BEAST_GCC || BEAST_MAC - #if BEAST_NO_INLINE_ASM - #define beast_breakDebugger { } - #else - #define beast_breakDebugger { asm ("int $3"); } - #endif +# if BEAST_NO_INLINE_ASM +# define beast_breakDebugger { } +# else +# define beast_breakDebugger { asm ("int $3"); } +# endif #else - #define beast_breakDebugger { __asm int 3 } +# define beast_breakDebugger { __asm int 3 } #endif #if BEAST_CLANG && defined (__has_feature) && ! defined (BEAST_ANALYZER_NORETURN) - #if __has_feature (attribute_analyzer_noreturn) - inline void __attribute__((analyzer_noreturn)) beast_assert_noreturn() {} - #define BEAST_ANALYZER_NORETURN beast_assert_noreturn(); - #endif +# if __has_feature (attribute_analyzer_noreturn) + inline void __attribute__((analyzer_noreturn)) beast_assert_noreturn() {} +# define BEAST_ANALYZER_NORETURN beast_assert_noreturn(); +# endif #endif #ifndef BEAST_ANALYZER_NORETURN - #define BEAST_ANALYZER_NORETURN +#define BEAST_ANALYZER_NORETURN #endif +//------------------------------------------------------------------------------ -//============================================================================== #if BEAST_DEBUG || DOXYGEN - /** Writes a string to the standard error stream. - This is only compiled in a debug build. - @see Logger::outputDebugString - */ - #define DBG(dbgtext) { beast::String tempDbgBuf; tempDbgBuf << dbgtext; beast::Logger::outputDebugString (tempDbgBuf); } - //============================================================================== - /** This will always cause an assertion failure. - It is only compiled in a debug build, (unless BEAST_LOG_ASSERTIONS is enabled for your build). - @see bassert - */ - #define bassertfalse { beast_LogCurrentAssertion; if (beast::beast_isRunningUnderDebugger()) beast_breakDebugger; BEAST_ANALYZER_NORETURN } +/** Writes a string to the standard error stream. + This is only compiled in a debug build. + @see Logger::outputDebugString +*/ +#define DBG(dbgtext) { beast::String tempDbgBuf; tempDbgBuf << dbgtext; beast::Logger::outputDebugString (tempDbgBuf); } - //============================================================================== - /** Platform-independent assertion macro. +/** This will always cause an assertion failure. + It is only compiled in a debug build, (unless BEAST_LOG_ASSERTIONS is enabled for your build). + @see bassert +*/ +#define bassertfalse { beast_LogCurrentAssertion; if (beast::beast_isRunningUnderDebugger()) beast_breakDebugger; BEAST_ANALYZER_NORETURN } - This macro gets turned into a no-op when you're building with debugging turned off, so be - careful that the expression you pass to it doesn't perform any actions that are vital for the - correct behaviour of your program! - @see bassertfalse +/** Platform-independent assertion macro. + + This macro gets turned into a no-op when you're building with debugging turned off, so be + careful that the expression you pass to it doesn't perform any actions that are vital for the + correct behaviour of your program! + @see bassertfalse */ - #define bassert(expression) { if (! (expression)) bassertfalse; } +#define bassert(expression) { if (! (expression)) bassertfalse; } #else - //============================================================================== - // If debugging is disabled, these dummy debug and assertion macros are used.. - #define DBG(dbgtext) - #define bassertfalse { beast_LogCurrentAssertion } +// If debugging is disabled, these dummy debug and assertion macros are used.. - #if BEAST_LOG_ASSERTIONS - #define bassert(expression) { if (! (expression)) bassertfalse; } - #else - #define bassert(a) {} - #endif +#define DBG(dbgtext) +#define bassertfalse { beast_LogCurrentAssertion } + +# if BEAST_LOG_ASSERTIONS +# define bassert(expression) { if (! (expression)) bassertfalse; } +# else +# define bassert(a) {} +# endif #endif -//============================================================================== +//------------------------------------------------------------------------------ + #ifndef DOXYGEN namespace beast { - template struct BeastStaticAssert; - template <> struct BeastStaticAssert { static void dummy() {} }; +template struct BeastStaticAssert; +template <> struct BeastStaticAssert { static void dummy() {} }; } #endif @@ -189,8 +184,8 @@ namespace beast static void* operator new (size_t); \ static void operator delete (void*); +//------------------------------------------------------------------------------ -//============================================================================== #if ! DOXYGEN #define BEAST_JOIN_MACRO_HELPER(a, b) a ## b #define BEAST_STRINGIFY_MACRO_HELPER(a) #a @@ -206,158 +201,140 @@ namespace beast */ #define BEAST_STRINGIFY(item) BEAST_STRINGIFY_MACRO_HELPER (item) +//------------------------------------------------------------------------------ -//============================================================================== #if BEAST_CATCH_UNHANDLED_EXCEPTIONS - - #define BEAST_TRY try - - #define BEAST_CATCH_ALL catch (...) {} - #define BEAST_CATCH_ALL_ASSERT catch (...) { bassertfalse; } - - #if ! BEAST_MODULE_AVAILABLE_beast_gui_basics - #define BEAST_CATCH_EXCEPTION BEAST_CATCH_ALL - #else - /** Used in try-catch blocks, this macro will send exceptions to the BEASTApplication - object so they can be logged by the application if it wants to. - */ - #define BEAST_CATCH_EXCEPTION \ - catch (const std::exception& e) \ - { \ - beast::BEASTApplication::sendUnhandledException (&e, __FILE__, __LINE__); \ - } \ - catch (...) \ - { \ - beast::BEASTApplication::sendUnhandledException (nullptr, __FILE__, __LINE__); \ - } - #endif +# define BEAST_TRY try +# define BEAST_CATCH_ALL catch (...) {} +# define BEAST_CATCH_ALL_ASSERT catch (...) { bassertfalse; } +# define BEAST_CATCH_EXCEPTION BEAST_CATCH_ALL #else - - #define BEAST_TRY - #define BEAST_CATCH_EXCEPTION - #define BEAST_CATCH_ALL - #define BEAST_CATCH_ALL_ASSERT +# define BEAST_TRY +# define BEAST_CATCH_EXCEPTION +# define BEAST_CATCH_ALL +# define BEAST_CATCH_ALL_ASSERT #endif -//============================================================================== +//------------------------------------------------------------------------------ + #if BEAST_DEBUG || DOXYGEN - /** A platform-independent way of forcing an inline function. - Use the syntax: @code - forcedinline void myfunction (int x) - @endcode - */ - #define forcedinline inline +/** A platform-independent way of forcing an inline function. + Use the syntax: @code + forcedinline void myfunction (int x) + @endcode +*/ +# define forcedinline inline +#elif BEAST_MSVC +# define forcedinline __forceinline #else - #if BEAST_MSVC - #define forcedinline __forceinline - #else - #define forcedinline inline __attribute__((always_inline)) - #endif +# define forcedinline inline __attribute__((always_inline)) #endif #if BEAST_MSVC || DOXYGEN - /** This can be placed before a stack or member variable declaration to tell the compiler - to align it to the specified number of bytes. */ - #define BEAST_ALIGN(bytes) __declspec (align (bytes)) +/** This can be placed before a stack or member variable declaration to tell + the compiler to align it to the specified number of bytes. +*/ +#define BEAST_ALIGN(bytes) __declspec (align (bytes)) #else - #define BEAST_ALIGN(bytes) __attribute__ ((aligned (bytes))) +#define BEAST_ALIGN(bytes) __attribute__ ((aligned (bytes))) #endif -//============================================================================== +//------------------------------------------------------------------------------ + // Cross-compiler deprecation macros.. #if DOXYGEN || (BEAST_MSVC && ! BEAST_NO_DEPRECATION_WARNINGS) - /** This can be used to wrap a function which has been deprecated. */ - #define BEAST_DEPRECATED(functionDef) __declspec(deprecated) functionDef +/** This can be used to wrap a function which has been deprecated. */ +# define BEAST_DEPRECATED(functionDef) __declspec(deprecated) functionDef #elif BEAST_GCC && ! BEAST_NO_DEPRECATION_WARNINGS - #define BEAST_DEPRECATED(functionDef) functionDef __attribute__ ((deprecated)) +# define BEAST_DEPRECATED(functionDef) functionDef __attribute__ ((deprecated)) #else - #define BEAST_DEPRECATED(functionDef) functionDef +# define BEAST_DEPRECATED(functionDef) functionDef #endif -//============================================================================== +//------------------------------------------------------------------------------ + #if BEAST_ANDROID && ! DOXYGEN - #define BEAST_MODAL_LOOPS_PERMITTED 0 +# define BEAST_MODAL_LOOPS_PERMITTED 0 #elif ! defined (BEAST_MODAL_LOOPS_PERMITTED) - /** Some operating environments don't provide a modal loop mechanism, so this flag can be - used to disable any functions that try to run a modal loop. */ + /** Some operating environments don't provide a modal loop mechanism, so this + flag can be used to disable any functions that try to run a modal loop. + */ #define BEAST_MODAL_LOOPS_PERMITTED 1 #endif -//============================================================================== +//------------------------------------------------------------------------------ + #if BEAST_GCC - #define BEAST_PACKED __attribute__((packed)) +# define BEAST_PACKED __attribute__((packed)) #elif ! DOXYGEN - #define BEAST_PACKED +# define BEAST_PACKED #endif -//============================================================================== +//------------------------------------------------------------------------------ + // Here, we'll check for C++11 compiler support, and if it's not available, define // a few workarounds, so that we can still use some of the newer language features. #if defined (__GXX_EXPERIMENTAL_CXX0X__) && defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 - #define BEAST_COMPILER_SUPPORTS_NOEXCEPT 1 - #define BEAST_COMPILER_SUPPORTS_NULLPTR 1 - #define BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 - - #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && ! defined (BEAST_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL) - #define BEAST_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 - #endif +# define BEAST_COMPILER_SUPPORTS_NOEXCEPT 1 +# define BEAST_COMPILER_SUPPORTS_NULLPTR 1 +# define BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && ! defined (BEAST_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL) +# define BEAST_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 +# endif #endif #if BEAST_CLANG && defined (__has_feature) - #if __has_feature (cxx_nullptr) - #define BEAST_COMPILER_SUPPORTS_NULLPTR 1 - #endif - - #if __has_feature (cxx_noexcept) - #define BEAST_COMPILER_SUPPORTS_NOEXCEPT 1 - #endif - - #if __has_feature (cxx_rvalue_references) - #define BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 - #endif - - #ifndef BEAST_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL - #define BEAST_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 - #endif - - #ifndef BEAST_COMPILER_SUPPORTS_ARC - #define BEAST_COMPILER_SUPPORTS_ARC 1 - #endif +# if __has_feature (cxx_nullptr) +# define BEAST_COMPILER_SUPPORTS_NULLPTR 1 +# endif +# if __has_feature (cxx_noexcept) +# define BEAST_COMPILER_SUPPORTS_NOEXCEPT 1 +# endif +# if __has_feature (cxx_rvalue_references) +# define BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 +# endif +# ifndef BEAST_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL +# define BEAST_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 +# endif +# ifndef BEAST_COMPILER_SUPPORTS_ARC +# define BEAST_COMPILER_SUPPORTS_ARC 1 +# endif #endif #if defined (_MSC_VER) && _MSC_VER >= 1600 - #define BEAST_COMPILER_SUPPORTS_NULLPTR 1 - #define BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 +# define BEAST_COMPILER_SUPPORTS_NULLPTR 1 +# define BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 #endif #if defined (_MSC_VER) && _MSC_VER >= 1700 - #define BEAST_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 +# define BEAST_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 #endif -//============================================================================== +//------------------------------------------------------------------------------ + // Declare some fake versions of nullptr and noexcept, for older compilers: #if ! (DOXYGEN || BEAST_COMPILER_SUPPORTS_NOEXCEPT) - #ifdef noexcept - #undef noexcept - #endif - #define noexcept throw() - #if defined (_MSC_VER) && _MSC_VER > 1600 - #define _ALLOW_KEYWORD_MACROS 1 // (to stop VC2012 complaining) - #endif +# ifdef noexcept +# undef noexcept +# endif +# define noexcept throw() +# if defined (_MSC_VER) && _MSC_VER > 1600 +# define _ALLOW_KEYWORD_MACROS 1 // (to stop VC2012 complaining) +# endif #endif #if ! (DOXYGEN || BEAST_COMPILER_SUPPORTS_NULLPTR) - #ifdef nullptr - #undef nullptr - #endif - #define nullptr (0) +#ifdef nullptr +#undef nullptr +#endif +#define nullptr (0) #endif #if ! (DOXYGEN || BEAST_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL) - #undef override - #define override +#undef override +#define override #endif -#endif // BEAST_PLATFORMDEFS_BEASTHEADER +#endif diff --git a/Subtrees/beast/modules/beast_core/system/beast_StandardHeader.h b/Subtrees/beast/modules/beast_core/system/beast_StandardHeader.h index a3b81c3b15..f2ee59a2ea 100644 --- a/Subtrees/beast/modules/beast_core/system/beast_StandardHeader.h +++ b/Subtrees/beast/modules/beast_core/system/beast_StandardHeader.h @@ -114,6 +114,8 @@ #if BEAST_MSVC && BEAST_DEBUG # include +# include +# include #endif #if BEAST_MSVC diff --git a/Subtrees/beast/modules/beast_core/threads/beast_Process.h b/Subtrees/beast/modules/beast_core/threads/beast_Process.h index 05a9f1f367..2eb5044b26 100644 --- a/Subtrees/beast/modules/beast_core/threads/beast_Process.h +++ b/Subtrees/beast/modules/beast_core/threads/beast_Process.h @@ -90,11 +90,9 @@ public: */ static void lowerPrivilege(); - //============================================================================== /** Returns true if this process is being hosted by a debugger. */ static bool BEAST_CALLTYPE isRunningUnderDebugger(); - //============================================================================== /** Tries to launch the OS's default reader application for a given file or URL. */ static bool openDocument (const String& documentURL, const String& parameters); diff --git a/TODO.txt b/TODO.txt index d458afddb4..42531891c6 100644 --- a/TODO.txt +++ b/TODO.txt @@ -2,6 +2,12 @@ BEAST TODO -------------------------------------------------------------------------------- +- Fix FifoFreeStoreWithTLS reference counting bug + +- Implement a reasonable substitute for boost's thread_local_storage + +- Think about doing away with BEAST_CALLTYPE and BEAST_API + - Decide if headers should just include BeastConfig.h instead of making the host program do it. diff --git a/modules/ripple_app/ripple_app.cpp b/modules/ripple_app/ripple_app.cpp index 27e5baf09f..5493fbf5e9 100644 --- a/modules/ripple_app/ripple_app.cpp +++ b/modules/ripple_app/ripple_app.cpp @@ -252,7 +252,7 @@ static const uint64 tenTo17m1 = tenTo17 - 1; #include "src/cpp/ripple/LedgerProposal.cpp" #include "src/cpp/ripple/LedgerTiming.cpp" #include "src/cpp/ripple/ripple_LoadManager.cpp" -#include "src/cpp/ripple/main.cpp" +#include "src/cpp/ripple/ripple_Main.cpp" #include "src/cpp/ripple/ripple_NicknameState.cpp" #include "src/cpp/ripple/ripple_Offer.cpp" #include "src/cpp/ripple/OfferCancelTransactor.cpp" diff --git a/src/cpp/ripple/main.cpp b/src/cpp/ripple/ripple_Main.cpp similarity index 94% rename from src/cpp/ripple/main.cpp rename to src/cpp/ripple/ripple_Main.cpp index ed1dac2efb..f94d5b3658 100644 --- a/src/cpp/ripple/main.cpp +++ b/src/cpp/ripple/ripple_Main.cpp @@ -119,10 +119,30 @@ void printHelp (const po::options_description& desc) int rippleMain (int argc, char** argv) { + // + // These debug heap calls do nothing in release or non Visual Studio builds. + // + + // Checks the heap at every allocation and deallocation (slow). + Debug::setAlwaysCheckHeap (false); + + // Keeps freed memory blocks and fills them with a guard value. + Debug::setHeapDelayedFree (false); + + // At exit, reports all memory blocks which have not been freed. + Debug::setHeapReportLeaks (false); + +#if 0 +// This is some temporary leak checking test code +ThreadWithCallQueue t ("test"); +t.start (); +return 0; +#endif + using namespace std; setCallingThreadName ("main"); - int iResult = 0; + int iResult = 0; po::variables_map vm; // Map of options. //