mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Large tidying up of Beast
- Move key classes into beast_core - Tidy up various macros and files - Disable leaking FifoFreeStoreWithTLS
This commit is contained in:
@@ -112,26 +112,39 @@ namespace beast
|
||||
#include "containers/beast_NamedValueSet.cpp"
|
||||
#include "containers/beast_PropertySet.cpp"
|
||||
#include "containers/beast_Variant.cpp"
|
||||
|
||||
#include "diagnostic/beast_Debug.cpp"
|
||||
#include "diagnostic/beast_Error.cpp"
|
||||
#include "diagnostic/beast_FPUFlags.cpp"
|
||||
#include "diagnostic/beast_LeakChecked.cpp"
|
||||
|
||||
#include "files/beast_DirectoryIterator.cpp"
|
||||
#include "files/beast_File.cpp"
|
||||
#include "files/beast_FileInputStream.cpp"
|
||||
#include "files/beast_FileOutputStream.cpp"
|
||||
#include "files/beast_FileSearchPath.cpp"
|
||||
#include "files/beast_TemporaryFile.cpp"
|
||||
|
||||
#include "json/beast_JSON.cpp"
|
||||
|
||||
#include "logging/beast_FileLogger.cpp"
|
||||
#include "logging/beast_Logger.cpp"
|
||||
|
||||
#include "maths/beast_BigInteger.cpp"
|
||||
#include "maths/beast_Expression.cpp"
|
||||
#include "maths/beast_Random.cpp"
|
||||
|
||||
#include "memory/beast_MemoryBlock.cpp"
|
||||
|
||||
#include "misc/beast_Result.cpp"
|
||||
#include "misc/beast_Uuid.cpp"
|
||||
|
||||
#include "network/beast_MACAddress.cpp"
|
||||
#include "network/beast_NamedPipe.cpp"
|
||||
#include "network/beast_Socket.cpp"
|
||||
#include "network/beast_URL.cpp"
|
||||
#include "network/beast_IPAddress.cpp"
|
||||
|
||||
#include "streams/beast_BufferedInputStream.cpp"
|
||||
#include "streams/beast_FileInputSource.cpp"
|
||||
#include "streams/beast_InputStream.cpp"
|
||||
@@ -140,7 +153,9 @@ namespace beast
|
||||
#include "streams/beast_OutputStream.cpp"
|
||||
#include "streams/beast_SubregionStream.cpp"
|
||||
#include "system/beast_SystemStats.cpp"
|
||||
|
||||
#include "text/beast_CharacterFunctions.cpp"
|
||||
|
||||
#include "text/beast_Identifier.cpp"
|
||||
#include "text/beast_LocalisedStrings.cpp"
|
||||
#include "text/beast_String.cpp"
|
||||
@@ -148,17 +163,23 @@ namespace beast
|
||||
#include "text/beast_StringPairArray.cpp"
|
||||
#include "text/beast_StringPool.cpp"
|
||||
#include "text/beast_TextDiff.cpp"
|
||||
|
||||
#include "threads/beast_ChildProcess.cpp"
|
||||
#include "threads/beast_ReadWriteLock.cpp"
|
||||
#include "threads/beast_Thread.cpp"
|
||||
#include "threads/beast_ThreadPool.cpp"
|
||||
#include "threads/beast_TimeSliceThread.cpp"
|
||||
|
||||
#include "time/beast_PerformanceCounter.cpp"
|
||||
#include "time/beast_PerformedAtExit.cpp"
|
||||
#include "time/beast_RelativeTime.cpp"
|
||||
#include "time/beast_Time.cpp"
|
||||
|
||||
#include "unit_tests/beast_UnitTest.cpp"
|
||||
|
||||
#include "xml/beast_XmlDocument.cpp"
|
||||
#include "xml/beast_XmlElement.cpp"
|
||||
|
||||
#include "zip/beast_GZIPDecompressorInputStream.cpp"
|
||||
#include "zip/beast_GZIPCompressorOutputStream.cpp"
|
||||
#include "zip/beast_ZipFile.cpp"
|
||||
@@ -221,3 +242,22 @@ namespace beast
|
||||
#include "threads/beast_HighResolutionTimer.cpp"
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if BEAST_BOOST_IS_AVAILABLE
|
||||
namespace boost {
|
||||
namespace placeholders {
|
||||
boost::arg<1> _1;
|
||||
boost::arg<2> _2;
|
||||
boost::arg<3> _3;
|
||||
boost::arg<4> _4;
|
||||
boost::arg<5> _5;
|
||||
boost::arg<6> _6;
|
||||
boost::arg<7> _7;
|
||||
boost::arg<8> _8;
|
||||
boost::arg<9> _9;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -21,89 +21,52 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CORE_BEASTHEADER
|
||||
#define BEAST_CORE_BEASTHEADER
|
||||
#ifndef BEAST_CORE_H_INCLUDED
|
||||
#define BEAST_CORE_H_INCLUDED
|
||||
|
||||
#ifndef BEAST_BEASTCONFIG_HEADER
|
||||
/* If you fail to make sure that all your compile units are building Beast with the same set of
|
||||
option flags, then there's a risk that different compile units will treat the classes as having
|
||||
different memory layouts, leading to very nasty memory corruption errors when they all get
|
||||
linked together. That's why it's best to always include the BeastConfig.h file before any beast headers.
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#pragma message ("Have you included your BeastConfig.h file before including the Beast headers?")
|
||||
#else
|
||||
#warning "Have you included your BeastConfig.h file before including the Beast headers?"
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* If you fail to make sure that all your compile units are building Beast with
|
||||
the same set of option flags, then there's a risk that different compile
|
||||
units will treat the classes as having different memory layouts, leading to
|
||||
very nasty memory corruption errors when they all get linked together.
|
||||
That's why it's best to always include the BeastConfig.h file before any
|
||||
beast headers.
|
||||
*/
|
||||
#ifndef BEAST_BEASTCONFIG_H_INCLUDED
|
||||
# ifdef _MSC_VER
|
||||
# pragma message ("Have you included your BeastConfig.h file before including the Beast headers?")
|
||||
# else
|
||||
# warning "Have you included your BeastConfig.h file before including the Beast headers?"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "system/beast_TargetPlatform.h"
|
||||
|
||||
//=============================================================================
|
||||
/** Config: BEAST_FORCE_DEBUG
|
||||
//
|
||||
// Apply sensible defaults for the configuration settings
|
||||
//
|
||||
|
||||
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
|
||||
|
||||
//=============================================================================
|
||||
/** 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
|
||||
#if BEAST_ANDROID
|
||||
#define BEAST_LOG_ASSERTIONS 1
|
||||
#else
|
||||
#define BEAST_LOG_ASSERTIONS 0
|
||||
#endif
|
||||
# if BEAST_ANDROID
|
||||
# define BEAST_LOG_ASSERTIONS 1
|
||||
# else
|
||||
# define BEAST_LOG_ASSERTIONS 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
/** Config: BEAST_CHECK_MEMORY_LEAKS
|
||||
|
||||
Enables a memory-leak check for certain objects when the app terminates. See the LeakedObjectDetector
|
||||
class and the BEAST_LEAK_DETECTOR macro for more details about enabling leak checking for specific classes.
|
||||
*/
|
||||
#if BEAST_DEBUG && ! defined (BEAST_CHECK_MEMORY_LEAKS)
|
||||
#define BEAST_CHECK_MEMORY_LEAKS 1
|
||||
#define BEAST_CHECK_MEMORY_LEAKS 1
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
/** 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 0
|
||||
#endif
|
||||
|
||||
/* 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 1
|
||||
#define BEAST_INCLUDE_ZLIB_CODE 1
|
||||
#endif
|
||||
|
||||
#ifndef BEAST_ZLIB_INCLUDE_PATH
|
||||
#define BEAST_ZLIB_INCLUDE_PATH <zlib.h>
|
||||
#define BEAST_ZLIB_INCLUDE_PATH <zlib.h>
|
||||
#endif
|
||||
|
||||
/* Config: BEAST_CATCH_UNHANDLED_EXCEPTIONS
|
||||
@@ -111,18 +74,89 @@
|
||||
to your BEASTApplication::unhandledException() callback.
|
||||
*/
|
||||
#ifndef BEAST_CATCH_UNHANDLED_EXCEPTIONS
|
||||
//#define BEAST_CATCH_UNHANDLED_EXCEPTIONS 1
|
||||
//#define BEAST_CATCH_UNHANDLED_EXCEPTIONS 1
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
#ifndef BEAST_BOOST_IS_AVAILABLE
|
||||
#define BEAST_BOOST_IS_AVAILABLE 0
|
||||
#endif
|
||||
|
||||
#ifndef BEAST_USE_LEAKCHECKED
|
||||
#define BEAST_USE_LEAKCHECKED BEAST_CHECK_MEMORY_LEAKS
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// This is a hack to fix boost's goofy placeholders
|
||||
//
|
||||
|
||||
#if BEAST_BOOST_IS_AVAILABLE
|
||||
#ifdef BOOST_BIND_PLACEHOLDERS_HPP_INCLUDED
|
||||
#error <boost/bind.hpp> must not be included before this file
|
||||
#endif
|
||||
// Prevent <boost/bind/placeholders.hpp> from being included
|
||||
#define BOOST_BIND_PLACEHOLDERS_HPP_INCLUDED
|
||||
#include <boost/bind/arg.hpp>
|
||||
#include <boost/config.hpp>
|
||||
// This based on <boost/bind/placeholders.cpp>
|
||||
namespace boost {
|
||||
namespace placeholders {
|
||||
extern boost::arg<1> _1;
|
||||
extern boost::arg<2> _2;
|
||||
extern boost::arg<3> _3;
|
||||
extern boost::arg<4> _4;
|
||||
extern boost::arg<5> _5;
|
||||
extern boost::arg<6> _6;
|
||||
extern boost::arg<7> _7;
|
||||
extern boost::arg<8> _8;
|
||||
extern boost::arg<9> _9;
|
||||
}
|
||||
using namespace placeholders;
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Choose a source of bind, placeholders, and function
|
||||
//
|
||||
|
||||
#if !BEAST_BIND_USES_STD && !BEAST_BIND_USES_TR1 && !BEAST_BIND_USES_BOOST
|
||||
# if BEAST_MSVC
|
||||
# define BEAST_BIND_USES_STD 1
|
||||
# elif BEAST_IOS || BEAST_MAC
|
||||
# include <ciso646> // detect version of std::lib
|
||||
# if BEAST_IOS && BEAST_BOOST_IS_AVAILABLE // Work-around for iOS bugs with bind.
|
||||
# define BEAST_BIND_USES_BOOST 1
|
||||
# elif _LIBCPP_VERSION // libc++
|
||||
# define BEAST_BIND_USES_STD 1
|
||||
# else // libstdc++ (GNU)
|
||||
# define BEAST_BIND_USES_TR1 1
|
||||
# endif
|
||||
# elif BEAST_LINUX || BEAST_BSD
|
||||
# define BEAST_BIND_USES_TR1 1
|
||||
# else
|
||||
# define BEAST_BIND_USES_STD 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_USES_STD
|
||||
# include <functional>
|
||||
#elif BEAST_BIND_USES_TR1
|
||||
# include <tr1/functional>
|
||||
#elif BEAST_BIND_USES_BOOST
|
||||
# include <boost/bind.hpp>
|
||||
# include <boost/function.hpp>
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if BEAST_MSVC
|
||||
#pragma warning (disable: 4251) // (DLL build warning, must be disabled before pushing the warning state)
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4786) // (long class name warning)
|
||||
#ifdef __INTEL_COMPILER
|
||||
#pragma warning (disable: 1125)
|
||||
#endif
|
||||
# pragma warning (disable: 4251) // (DLL build warning, must be disabled before pushing the warning state)
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable: 4786) // (long class name warning)
|
||||
# ifdef __INTEL_COMPILER
|
||||
# pragma warning (disable: 1125)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "system/beast_StandardHeader.h"
|
||||
@@ -130,311 +164,135 @@
|
||||
namespace beast
|
||||
{
|
||||
|
||||
// START_AUTOINCLUDE containers, files, json, logging, maths, memory, misc, network,
|
||||
// streams, system, text, threads, time, unit_tests, xml, zip
|
||||
#ifndef BEAST_ABSTRACTFIFO_BEASTHEADER
|
||||
#include "containers/beast_AbstractFifo.h"
|
||||
#endif
|
||||
#ifndef BEAST_ARRAY_BEASTHEADER
|
||||
#include "containers/beast_Array.h"
|
||||
#endif
|
||||
#ifndef BEAST_ARRAYALLOCATIONBASE_BEASTHEADER
|
||||
#include "containers/beast_ArrayAllocationBase.h"
|
||||
#endif
|
||||
#ifndef BEAST_DYNAMICOBJECT_BEASTHEADER
|
||||
#include "containers/beast_DynamicObject.h"
|
||||
#endif
|
||||
#ifndef BEAST_ELEMENTCOMPARATOR_BEASTHEADER
|
||||
#include "containers/beast_ElementComparator.h"
|
||||
#endif
|
||||
#ifndef BEAST_HASHMAP_BEASTHEADER
|
||||
#include "containers/beast_HashMap.h"
|
||||
#endif
|
||||
#ifndef BEAST_LINKEDLISTPOINTER_BEASTHEADER
|
||||
#include "containers/beast_LinkedListPointer.h"
|
||||
#endif
|
||||
#ifndef BEAST_NAMEDVALUESET_BEASTHEADER
|
||||
#include "containers/beast_NamedValueSet.h"
|
||||
#endif
|
||||
#ifndef BEAST_OWNEDARRAY_BEASTHEADER
|
||||
#include "containers/beast_OwnedArray.h"
|
||||
#endif
|
||||
#ifndef BEAST_PROPERTYSET_BEASTHEADER
|
||||
#include "containers/beast_PropertySet.h"
|
||||
#endif
|
||||
#ifndef BEAST_REFERENCECOUNTEDARRAY_BEASTHEADER
|
||||
#include "containers/beast_ReferenceCountedArray.h"
|
||||
#endif
|
||||
#ifndef BEAST_SCOPEDVALUESETTER_BEASTHEADER
|
||||
#include "containers/beast_ScopedValueSetter.h"
|
||||
#endif
|
||||
#ifndef BEAST_SORTEDSET_BEASTHEADER
|
||||
#include "containers/beast_SortedSet.h"
|
||||
#endif
|
||||
#ifndef BEAST_SPARSESET_BEASTHEADER
|
||||
#include "containers/beast_SparseSet.h"
|
||||
#endif
|
||||
#ifndef BEAST_VARIANT_BEASTHEADER
|
||||
#include "containers/beast_Variant.h"
|
||||
#endif
|
||||
#ifndef BEAST_DIRECTORYITERATOR_BEASTHEADER
|
||||
#include "files/beast_DirectoryIterator.h"
|
||||
#endif
|
||||
#ifndef BEAST_FILE_BEASTHEADER
|
||||
#include "files/beast_File.h"
|
||||
#endif
|
||||
#ifndef BEAST_FILEINPUTSTREAM_BEASTHEADER
|
||||
#include "files/beast_FileInputStream.h"
|
||||
#endif
|
||||
#ifndef BEAST_FILEOUTPUTSTREAM_BEASTHEADER
|
||||
#include "files/beast_FileOutputStream.h"
|
||||
#endif
|
||||
#ifndef BEAST_FILESEARCHPATH_BEASTHEADER
|
||||
#include "files/beast_FileSearchPath.h"
|
||||
#endif
|
||||
#ifndef BEAST_MEMORYMAPPEDFILE_BEASTHEADER
|
||||
#include "files/beast_MemoryMappedFile.h"
|
||||
#endif
|
||||
#ifndef BEAST_TEMPORARYFILE_BEASTHEADER
|
||||
#include "files/beast_TemporaryFile.h"
|
||||
#endif
|
||||
#ifndef BEAST_JSON_BEASTHEADER
|
||||
#include "json/beast_JSON.h"
|
||||
#endif
|
||||
#ifndef BEAST_FILELOGGER_BEASTHEADER
|
||||
#include "logging/beast_FileLogger.h"
|
||||
#endif
|
||||
#ifndef BEAST_LOGGER_BEASTHEADER
|
||||
#include "logging/beast_Logger.h"
|
||||
#endif
|
||||
#ifndef BEAST_BIGINTEGER_BEASTHEADER
|
||||
#include "maths/beast_BigInteger.h"
|
||||
#endif
|
||||
#ifndef BEAST_EXPRESSION_BEASTHEADER
|
||||
#include "maths/beast_Expression.h"
|
||||
#endif
|
||||
#ifndef BEAST_MATHSFUNCTIONS_BEASTHEADER
|
||||
#include "maths/beast_MathsFunctions.h"
|
||||
#endif
|
||||
#ifndef BEAST_RANDOM_BEASTHEADER
|
||||
#include "maths/beast_Random.h"
|
||||
#endif
|
||||
#ifndef BEAST_RANGE_BEASTHEADER
|
||||
#include "maths/beast_Range.h"
|
||||
#endif
|
||||
#ifndef BEAST_ATOMIC_BEASTHEADER
|
||||
#include "memory/beast_Atomic.h"
|
||||
#endif
|
||||
#ifndef BEAST_BYTEORDER_BEASTHEADER
|
||||
#include "memory/beast_ByteOrder.h"
|
||||
#endif
|
||||
#ifndef BEAST_HEAPBLOCK_BEASTHEADER
|
||||
#include "memory/beast_HeapBlock.h"
|
||||
#endif
|
||||
#ifndef BEAST_LEAKEDOBJECTDETECTOR_BEASTHEADER
|
||||
#include "memory/beast_LeakedObjectDetector.h"
|
||||
#endif
|
||||
#ifndef BEAST_MEMORY_BEASTHEADER
|
||||
#include "memory/beast_Memory.h"
|
||||
#endif
|
||||
#ifndef BEAST_MEMORYBLOCK_BEASTHEADER
|
||||
#include "memory/beast_MemoryBlock.h"
|
||||
#endif
|
||||
#ifndef BEAST_OPTIONALSCOPEDPOINTER_BEASTHEADER
|
||||
#include "memory/beast_OptionalScopedPointer.h"
|
||||
#endif
|
||||
#ifndef BEAST_REFERENCECOUNTEDOBJECT_BEASTHEADER
|
||||
#include "memory/beast_ReferenceCountedObject.h"
|
||||
#endif
|
||||
#ifndef BEAST_SCOPEDPOINTER_BEASTHEADER
|
||||
#include "memory/beast_ScopedPointer.h"
|
||||
#endif
|
||||
#ifndef BEAST_SINGLETON_BEASTHEADER
|
||||
#include "memory/beast_Singleton.h"
|
||||
#endif
|
||||
#ifndef BEAST_WEAKREFERENCE_BEASTHEADER
|
||||
#include "memory/beast_WeakReference.h"
|
||||
#endif
|
||||
#ifndef BEAST_RESULT_BEASTHEADER
|
||||
#include "misc/beast_Result.h"
|
||||
#endif
|
||||
#ifndef BEAST_UUID_BEASTHEADER
|
||||
#include "misc/beast_Uuid.h"
|
||||
#endif
|
||||
#ifndef BEAST_WINDOWSREGISTRY_BEASTHEADER
|
||||
#include "misc/beast_WindowsRegistry.h"
|
||||
#endif
|
||||
#ifndef BEAST_IPADDRESS_BEASTHEADER
|
||||
#include "network/beast_IPAddress.h"
|
||||
#endif
|
||||
#ifndef BEAST_MACADDRESS_BEASTHEADER
|
||||
#include "network/beast_MACAddress.h"
|
||||
#endif
|
||||
#ifndef BEAST_NAMEDPIPE_BEASTHEADER
|
||||
#include "network/beast_NamedPipe.h"
|
||||
#endif
|
||||
#ifndef BEAST_SOCKET_BEASTHEADER
|
||||
#include "network/beast_Socket.h"
|
||||
#endif
|
||||
#ifndef BEAST_URL_BEASTHEADER
|
||||
#include "network/beast_URL.h"
|
||||
#endif
|
||||
#ifndef BEAST_BUFFEREDINPUTSTREAM_BEASTHEADER
|
||||
#include "streams/beast_BufferedInputStream.h"
|
||||
#endif
|
||||
#ifndef BEAST_FILEINPUTSOURCE_BEASTHEADER
|
||||
#include "streams/beast_FileInputSource.h"
|
||||
#endif
|
||||
#ifndef BEAST_INPUTSOURCE_BEASTHEADER
|
||||
#include "streams/beast_InputSource.h"
|
||||
#endif
|
||||
#ifndef BEAST_INPUTSTREAM_BEASTHEADER
|
||||
#include "streams/beast_InputStream.h"
|
||||
#endif
|
||||
#ifndef BEAST_MEMORYINPUTSTREAM_BEASTHEADER
|
||||
#include "streams/beast_MemoryInputStream.h"
|
||||
#endif
|
||||
#ifndef BEAST_MEMORYOUTPUTSTREAM_BEASTHEADER
|
||||
#include "streams/beast_MemoryOutputStream.h"
|
||||
#endif
|
||||
#ifndef BEAST_OUTPUTSTREAM_BEASTHEADER
|
||||
#include "streams/beast_OutputStream.h"
|
||||
#endif
|
||||
#ifndef BEAST_SUBREGIONSTREAM_BEASTHEADER
|
||||
#include "streams/beast_SubregionStream.h"
|
||||
#endif
|
||||
#ifndef BEAST_PLATFORMDEFS_BEASTHEADER
|
||||
#include "system/beast_PlatformDefs.h"
|
||||
#endif
|
||||
#ifndef BEAST_STANDARDHEADER_BEASTHEADER
|
||||
#include "system/beast_StandardHeader.h"
|
||||
#endif
|
||||
#ifndef BEAST_SYSTEMSTATS_BEASTHEADER
|
||||
#include "system/beast_SystemStats.h"
|
||||
#endif
|
||||
#ifndef BEAST_TARGETPLATFORM_BEASTHEADER
|
||||
#include "system/beast_TargetPlatform.h"
|
||||
#endif
|
||||
#ifndef BEAST_CHARACTERFUNCTIONS_BEASTHEADER
|
||||
#include "text/beast_CharacterFunctions.h"
|
||||
#endif
|
||||
#ifndef BEAST_CHARPOINTER_ASCII_BEASTHEADER
|
||||
#include "text/beast_CharPointer_ASCII.h"
|
||||
#endif
|
||||
#ifndef BEAST_CHARPOINTER_UTF16_BEASTHEADER
|
||||
#include "text/beast_CharPointer_UTF16.h"
|
||||
#endif
|
||||
#ifndef BEAST_CHARPOINTER_UTF32_BEASTHEADER
|
||||
#include "text/beast_CharPointer_UTF32.h"
|
||||
#endif
|
||||
#ifndef BEAST_CHARPOINTER_UTF8_BEASTHEADER
|
||||
#include "text/beast_CharPointer_UTF8.h"
|
||||
#endif
|
||||
#ifndef BEAST_IDENTIFIER_BEASTHEADER
|
||||
#include "text/beast_Identifier.h"
|
||||
#endif
|
||||
#ifndef BEAST_LOCALISEDSTRINGS_BEASTHEADER
|
||||
#include "text/beast_LocalisedStrings.h"
|
||||
#endif
|
||||
#ifndef BEAST_NEWLINE_BEASTHEADER
|
||||
#include "text/beast_NewLine.h"
|
||||
#endif
|
||||
#ifndef BEAST_STRING_BEASTHEADER
|
||||
#include "text/beast_String.h"
|
||||
#endif
|
||||
#ifndef BEAST_STRINGARRAY_BEASTHEADER
|
||||
#include "text/beast_StringArray.h"
|
||||
#endif
|
||||
#ifndef BEAST_STRINGPAIRARRAY_BEASTHEADER
|
||||
#include "text/beast_StringPairArray.h"
|
||||
#endif
|
||||
#ifndef BEAST_STRINGPOOL_BEASTHEADER
|
||||
#include "text/beast_StringPool.h"
|
||||
#endif
|
||||
#ifndef BEAST_TEXTDIFF_BEASTHEADER
|
||||
#include "text/beast_TextDiff.h"
|
||||
#endif
|
||||
#ifndef BEAST_CHILDPROCESS_BEASTHEADER
|
||||
#include "threads/beast_ChildProcess.h"
|
||||
#endif
|
||||
#ifndef BEAST_CRITICALSECTION_BEASTHEADER
|
||||
#include "threads/beast_CriticalSection.h"
|
||||
#endif
|
||||
#ifndef BEAST_DYNAMICLIBRARY_BEASTHEADER
|
||||
#include "threads/beast_DynamicLibrary.h"
|
||||
#endif
|
||||
#ifndef BEAST_HIGHRESOLUTIONTIMER_BEASTHEADER
|
||||
#include "threads/beast_HighResolutionTimer.h"
|
||||
#endif
|
||||
#ifndef BEAST_INTERPROCESSLOCK_BEASTHEADER
|
||||
#include "threads/beast_InterProcessLock.h"
|
||||
#endif
|
||||
#ifndef BEAST_PROCESS_BEASTHEADER
|
||||
#include "threads/beast_Process.h"
|
||||
#endif
|
||||
#ifndef BEAST_READWRITELOCK_BEASTHEADER
|
||||
#include "threads/beast_ReadWriteLock.h"
|
||||
#endif
|
||||
#ifndef BEAST_SCOPEDLOCK_BEASTHEADER
|
||||
#include "threads/beast_ScopedLock.h"
|
||||
#endif
|
||||
#ifndef BEAST_SCOPEDREADLOCK_BEASTHEADER
|
||||
#include "threads/beast_ScopedReadLock.h"
|
||||
#endif
|
||||
#ifndef BEAST_SCOPEDWRITELOCK_BEASTHEADER
|
||||
#include "threads/beast_ScopedWriteLock.h"
|
||||
#endif
|
||||
#ifndef BEAST_SPINLOCK_BEASTHEADER
|
||||
#include "threads/beast_SpinLock.h"
|
||||
#endif
|
||||
#ifndef BEAST_THREAD_BEASTHEADER
|
||||
#include "threads/beast_Thread.h"
|
||||
#endif
|
||||
#ifndef BEAST_THREADLOCALVALUE_BEASTHEADER
|
||||
#include "threads/beast_ThreadLocalValue.h"
|
||||
#endif
|
||||
#ifndef BEAST_THREADPOOL_BEASTHEADER
|
||||
#include "threads/beast_ThreadPool.h"
|
||||
#endif
|
||||
#ifndef BEAST_TIMESLICETHREAD_BEASTHEADER
|
||||
#include "threads/beast_TimeSliceThread.h"
|
||||
#endif
|
||||
#ifndef BEAST_WAITABLEEVENT_BEASTHEADER
|
||||
#include "threads/beast_WaitableEvent.h"
|
||||
#endif
|
||||
#ifndef BEAST_PERFORMANCECOUNTER_BEASTHEADER
|
||||
#include "time/beast_PerformanceCounter.h"
|
||||
#endif
|
||||
#ifndef BEAST_RELATIVETIME_BEASTHEADER
|
||||
#include "time/beast_RelativeTime.h"
|
||||
#endif
|
||||
#ifndef BEAST_TIME_BEASTHEADER
|
||||
#include "time/beast_Time.h"
|
||||
#endif
|
||||
#ifndef BEAST_UNITTEST_BEASTHEADER
|
||||
#include "unit_tests/beast_UnitTest.h"
|
||||
#endif
|
||||
#ifndef BEAST_XMLDOCUMENT_BEASTHEADER
|
||||
#include "xml/beast_XmlDocument.h"
|
||||
#endif
|
||||
#ifndef BEAST_XMLELEMENT_BEASTHEADER
|
||||
#include "xml/beast_XmlElement.h"
|
||||
#endif
|
||||
#ifndef BEAST_GZIPCOMPRESSOROUTPUTSTREAM_BEASTHEADER
|
||||
#include "zip/beast_GZIPCompressorOutputStream.h"
|
||||
#endif
|
||||
#ifndef BEAST_GZIPDECOMPRESSORINPUTSTREAM_BEASTHEADER
|
||||
#include "zip/beast_GZIPDecompressorInputStream.h"
|
||||
#endif
|
||||
#ifndef BEAST_ZIPFILE_BEASTHEADER
|
||||
#include "zip/beast_ZipFile.h"
|
||||
#endif
|
||||
// END_AUTOINCLUDE
|
||||
// Order matters, since headers don't have their own #include lines.
|
||||
// Add new includes to the bottom.
|
||||
|
||||
#include "threads/beast_Thread.h"
|
||||
#include "threads/beast_SpinDelay.h"
|
||||
#include "memory/beast_Atomic.h"
|
||||
#include "memory/beast_AtomicCounter.h"
|
||||
#include "memory/beast_AtomicFlag.h"
|
||||
#include "memory/beast_AtomicPointer.h"
|
||||
#include "memory/beast_AtomicState.h"
|
||||
#include "containers/beast_LockFreeStack.h"
|
||||
#include "memory/beast_StaticObject.h"
|
||||
#include "diagnostic/beast_LeakChecked.h"
|
||||
|
||||
#include "diagnostic/beast_Debug.h"
|
||||
#include "diagnostic/beast_SafeBool.h"
|
||||
#include "diagnostic/beast_Error.h"
|
||||
#include "diagnostic/beast_FPUFlags.h"
|
||||
#include "diagnostic/beast_Throw.h"
|
||||
#include "containers/beast_AbstractFifo.h"
|
||||
#include "containers/beast_Array.h"
|
||||
#include "containers/beast_ArrayAllocationBase.h"
|
||||
#include "containers/beast_DynamicObject.h"
|
||||
#include "containers/beast_ElementComparator.h"
|
||||
#include "containers/beast_HashMap.h"
|
||||
#include "containers/beast_List.h"
|
||||
#include "containers/beast_LinkedListPointer.h"
|
||||
#include "containers/beast_LockFreeQueue.h"
|
||||
#include "containers/beast_NamedValueSet.h"
|
||||
#include "containers/beast_OwnedArray.h"
|
||||
#include "containers/beast_PropertySet.h"
|
||||
#include "containers/beast_ReferenceCountedArray.h"
|
||||
#include "containers/beast_ScopedValueSetter.h"
|
||||
#include "containers/beast_SharedTable.h"
|
||||
#include "containers/beast_SortedLookupTable.h"
|
||||
#include "containers/beast_SortedSet.h"
|
||||
#include "containers/beast_SparseSet.h"
|
||||
#include "containers/beast_Variant.h"
|
||||
#include "files/beast_DirectoryIterator.h"
|
||||
#include "files/beast_File.h"
|
||||
#include "files/beast_FileInputStream.h"
|
||||
#include "files/beast_FileOutputStream.h"
|
||||
#include "files/beast_FileSearchPath.h"
|
||||
#include "files/beast_MemoryMappedFile.h"
|
||||
#include "files/beast_TemporaryFile.h"
|
||||
#include "functional/beast_Bind.h"
|
||||
#include "json/beast_JSON.h"
|
||||
#include "logging/beast_FileLogger.h"
|
||||
#include "logging/beast_Logger.h"
|
||||
#include "maths/beast_BigInteger.h"
|
||||
#include "maths/beast_Expression.h"
|
||||
#include "maths/beast_MathsFunctions.h"
|
||||
#include "maths/beast_Random.h"
|
||||
#include "maths/beast_Range.h"
|
||||
#include "memory/beast_ByteOrder.h"
|
||||
#include "memory/beast_HeapBlock.h"
|
||||
#include "memory/beast_LeakedObjectDetector.h"
|
||||
#include "memory/beast_Memory.h"
|
||||
#include "memory/beast_MemoryBlock.h"
|
||||
#include "memory/beast_OptionalScopedPointer.h"
|
||||
#include "memory/beast_ReferenceCountedObject.h"
|
||||
#include "memory/beast_ScopedPointer.h"
|
||||
#include "memory/beast_Singleton.h"
|
||||
#include "memory/beast_WeakReference.h"
|
||||
#include "memory/beast_MemoryAlignment.h"
|
||||
#include "memory/beast_CacheLine.h"
|
||||
#include "misc/beast_Result.h"
|
||||
#include "misc/beast_Uuid.h"
|
||||
#include "misc/beast_WindowsRegistry.h"
|
||||
#include "network/beast_IPAddress.h"
|
||||
#include "network/beast_MACAddress.h"
|
||||
#include "network/beast_NamedPipe.h"
|
||||
#include "network/beast_Socket.h"
|
||||
#include "network/beast_URL.h"
|
||||
#include "streams/beast_BufferedInputStream.h"
|
||||
#include "streams/beast_FileInputSource.h"
|
||||
#include "streams/beast_InputSource.h"
|
||||
#include "streams/beast_InputStream.h"
|
||||
#include "streams/beast_MemoryInputStream.h"
|
||||
#include "streams/beast_MemoryOutputStream.h"
|
||||
#include "streams/beast_OutputStream.h"
|
||||
#include "streams/beast_SubregionStream.h"
|
||||
#include "system/beast_PlatformDefs.h"
|
||||
#include "system/beast_StandardHeader.h"
|
||||
#include "system/beast_SystemStats.h"
|
||||
#include "system/beast_TargetPlatform.h"
|
||||
#include "text/beast_CharacterFunctions.h"
|
||||
#include "text/beast_CharPointer_ASCII.h"
|
||||
#include "text/beast_CharPointer_UTF16.h"
|
||||
#include "text/beast_CharPointer_UTF32.h"
|
||||
#include "text/beast_CharPointer_UTF8.h"
|
||||
#include "text/beast_Identifier.h"
|
||||
#include "text/beast_LocalisedStrings.h"
|
||||
#include "text/beast_NewLine.h"
|
||||
#include "text/beast_String.h"
|
||||
#include "text/beast_StringArray.h"
|
||||
#include "text/beast_StringPairArray.h"
|
||||
#include "text/beast_StringPool.h"
|
||||
#include "text/beast_TextDiff.h"
|
||||
#include "threads/beast_ChildProcess.h"
|
||||
#include "threads/beast_CriticalSection.h"
|
||||
#include "threads/beast_DynamicLibrary.h"
|
||||
#include "threads/beast_HighResolutionTimer.h"
|
||||
#include "threads/beast_InterProcessLock.h"
|
||||
#include "threads/beast_Process.h"
|
||||
#include "threads/beast_ReadWriteLock.h"
|
||||
#include "threads/beast_ScopedLock.h"
|
||||
#include "threads/beast_ScopedReadLock.h"
|
||||
#include "threads/beast_ScopedWriteLock.h"
|
||||
#include "threads/beast_SpinLock.h"
|
||||
#include "threads/beast_ThreadLocalValue.h"
|
||||
#include "threads/beast_ThreadPool.h"
|
||||
#include "threads/beast_TimeSliceThread.h"
|
||||
#include "threads/beast_WaitableEvent.h"
|
||||
#include "time/beast_PerformanceCounter.h"
|
||||
#include "time/beast_PerformedAtExit.h"
|
||||
#include "time/beast_RelativeTime.h"
|
||||
#include "time/beast_Time.h"
|
||||
#include "unit_tests/beast_UnitTest.h"
|
||||
#include "xml/beast_XmlDocument.h"
|
||||
#include "xml/beast_XmlElement.h"
|
||||
#include "zip/beast_GZIPCompressorOutputStream.h"
|
||||
#include "zip/beast_GZIPDecompressorInputStream.h"
|
||||
#include "zip/beast_ZipFile.h"
|
||||
|
||||
}
|
||||
|
||||
#if BEAST_MSVC
|
||||
#pragma warning (pop)
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#endif // BEAST_CORE_BEASTHEADER
|
||||
#endif
|
||||
|
||||
@@ -24,21 +24,19 @@
|
||||
#ifndef BEAST_ABSTRACTFIFO_BEASTHEADER
|
||||
#define BEAST_ABSTRACTFIFO_BEASTHEADER
|
||||
|
||||
#include "../memory/beast_Atomic.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Encapsulates the logic required to implement a lock-free FIFO.
|
||||
|
||||
This class handles the logic needed when building a single-reader, single-writer FIFO.
|
||||
This class handles the logic needed when building a single-reader,
|
||||
single-writer FIFO.
|
||||
|
||||
It doesn't actually hold any data itself, but your FIFO class can use one of these to manage
|
||||
its position and status when reading or writing to it.
|
||||
It doesn't actually hold any data itself, but your FIFO class can use one of
|
||||
these to manage its position and status when reading or writing to it.
|
||||
|
||||
To use it, you can call prepareToWrite() to determine the position within your own buffer that
|
||||
an incoming block of data should be stored, and prepareToRead() to find out when the next
|
||||
outgoing block should be read from.
|
||||
To use it, you can call prepareToWrite() to determine the position within
|
||||
your own buffer that an incoming block of data should be stored, and
|
||||
prepareToRead() to find out when the next outgoing block should be read from.
|
||||
|
||||
e.g.
|
||||
@code
|
||||
@@ -204,7 +202,6 @@ public:
|
||||
*/
|
||||
void finishedRead (int numRead) noexcept;
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
int bufferSize;
|
||||
@@ -213,5 +210,5 @@ private:
|
||||
BEAST_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AbstractFifo)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BEAST_ABSTRACTFIFO_BEASTHEADER
|
||||
|
||||
796
modules/beast_core/containers/beast_List.h
Normal file
796
modules/beast_core/containers/beast_List.h
Normal file
@@ -0,0 +1,796 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_LIST_BEASTHEADER
|
||||
#define BEAST_LIST_BEASTHEADER
|
||||
|
||||
struct ListDefaultTag;
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
Intrusive Containers
|
||||
|
||||
# Introduction
|
||||
|
||||
Intrusive containers are special containers that offer better performance
|
||||
and exception safety guarantees than non-intrusive containers (like the
|
||||
STL containers). They are useful building blocks for high performance
|
||||
concurrent systems or other purposes where allocations are restricted
|
||||
(such as the AudioIODeviceCallback object), because intrusive list
|
||||
operations do not allocate or free memory.
|
||||
|
||||
While intrusive containers were and are widely used in C, they became more
|
||||
and more forgotten in C++ due to the presence of the standard containers
|
||||
which don't support intrusive techniques. VFLib not only reintroduces this
|
||||
technique to C++ for lists, it also encapsulates the implementation in a
|
||||
mostly compliant STL interface. Hence anyone familiar with standard
|
||||
containers can easily use them.
|
||||
|
||||
# Interface
|
||||
|
||||
The interface for intrusive elements in this library is unified for all
|
||||
containers. Unlike STL containers, objects placed into intrusive containers
|
||||
are not copied. Instead, a pointer to the object is stored. All
|
||||
responsibility for object lifetime is the responsibility of the caller;
|
||||
the intrusive container just keeps track of what is in it.
|
||||
|
||||
Summary of intrusive container differences:
|
||||
|
||||
- Holds pointers to existing objects instead of copies.
|
||||
|
||||
- Does not allocate or free any objects.
|
||||
|
||||
- Requires a element's class declaration to be modified.
|
||||
|
||||
- Methods never throw exceptions when called with valid arguments.
|
||||
|
||||
# Usage
|
||||
|
||||
Like STL containers, intrusive containers are all template based, where the
|
||||
template argument specifies the type of object that the container will hold.
|
||||
These declarations specify a doubly linked list where each element points
|
||||
to a user defined class:
|
||||
|
||||
@code
|
||||
|
||||
class Object; // Forward declaration
|
||||
|
||||
List <Object> list; // Doubly-linked list of Object
|
||||
|
||||
@endcode
|
||||
|
||||
Because intrusive containers allocate no memory, allowing objects to be
|
||||
placed inside requires a modification to their class declaration. Each
|
||||
intrusive container declares a nested class `Node` which elements must be
|
||||
derived from, using the Curiously Recurring Template Pattern (CRTP). We
|
||||
will continue to fully declare the Object type from the previous example
|
||||
to support emplacement into an intrusive container:
|
||||
|
||||
@code
|
||||
|
||||
class Object : public List <Object>::Node // Required for List
|
||||
{
|
||||
public:
|
||||
void performAction ();
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
Usage of a typedef eliminates redundant specification of the template
|
||||
arguments but requires a forward declaration. The following code is
|
||||
equivalent.
|
||||
|
||||
@code
|
||||
|
||||
class Object; // Forward declaration
|
||||
|
||||
// Specify template parameters just once
|
||||
typedef List <Object> ListType;
|
||||
|
||||
class Object : public ListType::Node
|
||||
{
|
||||
void performAction ();
|
||||
};
|
||||
|
||||
ListType::Node list;
|
||||
|
||||
@endcode
|
||||
|
||||
With these declarations we may proceed to create our objects, add them to
|
||||
the list, and perform operations:
|
||||
|
||||
@code
|
||||
|
||||
// Create a few objects and put them in the list
|
||||
for (i = 0; i < 5; ++i)
|
||||
list.push_back (*new Object);
|
||||
|
||||
// Call a method on each list
|
||||
for (ListType::iterator iter = list.begin(); iter != list.end (); ++iter)
|
||||
iter->performAction ();
|
||||
|
||||
@endcode
|
||||
|
||||
Unlike regular STL containers, an object derived from an intrusive container
|
||||
node cannot exist in more than one instance of that list at a time. This is
|
||||
because the bookkeeping information for maintaining the list is kept in
|
||||
the object rather than the list.
|
||||
|
||||
To support objects existing in multiple containers, templates variations
|
||||
are instantiated by distinguishing them with an empty structure, called a
|
||||
tag. The object is derived from multiple instances of Node, where each
|
||||
instance specifies a unique tag. The tag is passed as the second template
|
||||
argument. When the second argument is unspecified, the default tag is used.
|
||||
|
||||
This declaration example shows the usage of tags to allow an object to exist
|
||||
simultaneously in two separate lists:
|
||||
|
||||
@code
|
||||
|
||||
struct GlobalListTag { }; // list of all objects
|
||||
struct ActiveListTag { }; // subset of all objects that are active
|
||||
|
||||
class Object : public List <Object, GlobalListTag>
|
||||
, public List <Object, ActiveListTag>
|
||||
{
|
||||
public:
|
||||
Object () : m_isActive (false)
|
||||
{
|
||||
// Add ourselves to the global list
|
||||
s_globalList.push_front (*this);
|
||||
}
|
||||
|
||||
~Object ()
|
||||
{
|
||||
deactivate ();
|
||||
}
|
||||
|
||||
void becomeActive ()
|
||||
{
|
||||
// Add ourselves to the active list
|
||||
if (!m_isActive)
|
||||
{
|
||||
s_activeList.push_front (*this);
|
||||
m_isActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
void deactivate ()
|
||||
{
|
||||
if (m_isActive)
|
||||
{
|
||||
// Doesn't delete the object
|
||||
s_activeList.erase (s_activeList.iterator_to (this));
|
||||
|
||||
m_isActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_isActive;
|
||||
|
||||
static List <Object, GlobalListTag> s_globalList;
|
||||
static List <Object, ActiveListTag> s_activeList;
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
@defgroup intrusive intrusive
|
||||
@ingroup beast_core
|
||||
*/
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
Intrusive doubly linked list.
|
||||
|
||||
This intrusive List is a container similar in operation to std::list in the
|
||||
Standard Template Library (STL). Like all @ref intrusive containers, List
|
||||
requires you to first derive your class from List<>::Node:
|
||||
|
||||
@code
|
||||
|
||||
struct Object : List <Object>::Node
|
||||
{
|
||||
Object (int value) : m_value (value)
|
||||
{
|
||||
}
|
||||
|
||||
int m_value;
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
Now we define the list, and add a couple of items.
|
||||
|
||||
@code
|
||||
|
||||
List <Object> list;
|
||||
|
||||
list.push_back (* (new Object (1)));
|
||||
list.push_back (* (new Object (2)));
|
||||
|
||||
@endcode
|
||||
|
||||
For compatibility with the standard containers, push_back() expects a
|
||||
reference to the object. Unlike the standard container, however, push_back()
|
||||
places the actual object in the list and not a copy-constructed duplicate.
|
||||
|
||||
Iterating over the list follows the same idiom as the STL:
|
||||
|
||||
@code
|
||||
|
||||
for (List <Object>::iterator iter = list.begin(); iter != list.end; ++iter)
|
||||
std::cout << iter->m_value;
|
||||
|
||||
@endcode
|
||||
|
||||
You can even use BOOST_FOREACH, or range based for loops:
|
||||
|
||||
@code
|
||||
|
||||
BOOST_FOREACH (Object& object, list) // boost only
|
||||
std::cout << object.m_value;
|
||||
|
||||
for (Object& object : list) // C++11 only
|
||||
std::cout << object.m_value;
|
||||
|
||||
@endcode
|
||||
|
||||
Because List is mostly STL compliant, it can be passed into STL algorithms:
|
||||
e.g. `std::for_each()` or `std::find_first_of()`.
|
||||
|
||||
In general, objects placed into a List should be dynamically allocated
|
||||
although this cannot be enforced at compile time. Since the caller provides
|
||||
the storage for the object, the caller is also responsible for deleting the
|
||||
object. An object still exists after being removed from a List, until the
|
||||
caller deletes it. This means an element can be moved from one List to
|
||||
another with practically no overhead.
|
||||
|
||||
Unlike the standard containers, an object may only exist in one list at a
|
||||
time, unless special preparations are made. The Tag template parameter is
|
||||
used to distinguish between different list types for the same object,
|
||||
allowing the object to exist in more than one list simultaneously.
|
||||
|
||||
For example, consider an actor system where a global list of actors is
|
||||
maintained, so that they can each be periodically receive processing
|
||||
time. We wish to also maintain a list of the subset of actors that require
|
||||
a domain-dependent update. To achieve this, we declare two tags, the
|
||||
associated list types, and the list element thusly:
|
||||
|
||||
@code
|
||||
|
||||
struct Actor; // Forward declaration required
|
||||
|
||||
struct ProcessTag { };
|
||||
struct UpdateTag { };
|
||||
|
||||
typedef List <Actor, ProcessTag> ProcessList;
|
||||
typedef List <Actor, UpdateTag> UpdateList;
|
||||
|
||||
// Derive from both node types so we can be in each list at once.
|
||||
//
|
||||
struct Actor : ProcessList::Node, UpdateList::Node
|
||||
{
|
||||
bool process (); // returns true if we need an update
|
||||
void update ();
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
@tparam Element The base type of element which the list will store
|
||||
pointers to.
|
||||
|
||||
@tparam Tag An optional unique type name used to distinguish lists and nodes,
|
||||
when the object can exist in multiple lists simultaneously.
|
||||
|
||||
@ingroup beast_core intrusive
|
||||
*/
|
||||
template <class Element, class Tag = ListDefaultTag>
|
||||
class List : Uncopyable
|
||||
{
|
||||
public:
|
||||
typedef int size_type;
|
||||
|
||||
typedef Element value_type;
|
||||
typedef Element& reference;
|
||||
typedef Element const& const_reference;
|
||||
typedef Element* pointer;
|
||||
typedef Element const* const_pointer;
|
||||
|
||||
class Node : Uncopyable
|
||||
{
|
||||
public:
|
||||
Node () { }
|
||||
|
||||
private:
|
||||
friend class List;
|
||||
Node* m_next;
|
||||
Node* m_prev;
|
||||
};
|
||||
|
||||
private:
|
||||
template <class ElemType, class NodeType>
|
||||
class iterator_base : public std::iterator <
|
||||
std::bidirectional_iterator_tag, int >
|
||||
{
|
||||
public:
|
||||
typedef ElemType value_type;
|
||||
typedef ElemType* pointer;
|
||||
typedef ElemType& reference;
|
||||
|
||||
iterator_base (NodeType* node = nullptr) : m_node (node)
|
||||
{
|
||||
}
|
||||
|
||||
template <class OtherElemType, class OtherNodeType>
|
||||
iterator_base (iterator_base <OtherElemType, OtherNodeType> const& other)
|
||||
: m_node (other.m_node)
|
||||
{
|
||||
}
|
||||
|
||||
template <class OtherElemType, class OtherNodeType>
|
||||
iterator_base& operator= (iterator_base <OtherElemType, OtherNodeType> const& other)
|
||||
{
|
||||
m_node = other.m_node;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class OtherElemType, class OtherNodeType>
|
||||
bool operator == (iterator_base <OtherElemType, OtherNodeType> const& other) const
|
||||
{
|
||||
return m_node == other.m_node;
|
||||
}
|
||||
|
||||
template <class OtherElemType, class OtherNodeType>
|
||||
bool operator != (iterator_base <OtherElemType, OtherNodeType> const& other) const
|
||||
{
|
||||
return ! this->operator== (other);
|
||||
}
|
||||
|
||||
reference operator* () const
|
||||
{
|
||||
return dereference ();
|
||||
}
|
||||
|
||||
pointer operator-> () const
|
||||
{
|
||||
return &dereference ();
|
||||
}
|
||||
|
||||
iterator_base& operator++ ()
|
||||
{
|
||||
increment ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_base operator++ (int)
|
||||
{
|
||||
iterator_base result (*this);
|
||||
increment ();
|
||||
return result;
|
||||
}
|
||||
|
||||
iterator_base& operator-- ()
|
||||
{
|
||||
decrement ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_base operator-- (int)
|
||||
{
|
||||
iterator_base result (*this);
|
||||
decrement ();
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class List;
|
||||
|
||||
NodeType* get_node ()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
NodeType const* get_node () const
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
reference dereference () const
|
||||
{
|
||||
return *static_cast <ElemType*> (m_node);
|
||||
}
|
||||
|
||||
bool equal (NodeType* const* node) const
|
||||
{
|
||||
return m_node == node;
|
||||
}
|
||||
|
||||
void increment ()
|
||||
{
|
||||
bassert (m_node->m_next);
|
||||
m_node = m_node->m_next;
|
||||
}
|
||||
|
||||
void decrement ()
|
||||
{
|
||||
bassert (m_node->m_prev && m_node->m_prev->m_prev != 0);
|
||||
m_node = m_node->m_prev;
|
||||
}
|
||||
|
||||
private:
|
||||
NodeType* m_node;
|
||||
};
|
||||
|
||||
public:
|
||||
/** A read/write List iterator. */
|
||||
typedef iterator_base <Element, Node> iterator;
|
||||
|
||||
/** A read-only List iterator. */
|
||||
typedef iterator_base <Element const, Node const> const_iterator;
|
||||
|
||||
public:
|
||||
/** Create an empty list. */
|
||||
List () : m_size (0)
|
||||
{
|
||||
m_head.m_prev = nullptr; // identifies the head
|
||||
m_tail.m_next = nullptr; // identifies the tail
|
||||
clear ();
|
||||
}
|
||||
|
||||
/** Returns the number of elements in the list
|
||||
|
||||
@return The number of elements in the list.
|
||||
*/
|
||||
size_type size () const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/** Obtain a reference to the first element.
|
||||
|
||||
@invariant The list may not be empty.
|
||||
|
||||
@return A reference to the first element.
|
||||
*/
|
||||
reference front ()
|
||||
{
|
||||
if (empty ())
|
||||
Throw (Error ().fail (__FILE__, __LINE__, Error::noMoreData));
|
||||
|
||||
return element_from (m_head.m_next);
|
||||
}
|
||||
|
||||
/** Obtain a const reference to the first element.
|
||||
|
||||
@invariant The list may not be empty.
|
||||
|
||||
@return A const reference to the first element.
|
||||
*/
|
||||
const_reference front () const
|
||||
{
|
||||
if (empty ())
|
||||
Throw (Error ().fail (__FILE__, __LINE__, Error::noMoreData));
|
||||
|
||||
return element_from (m_head.m_next);
|
||||
}
|
||||
|
||||
/** Obtain a reference to the last element.
|
||||
|
||||
@invariant The list may not be empty.
|
||||
|
||||
@return A reference to the last element.
|
||||
*/
|
||||
reference back ()
|
||||
{
|
||||
if (empty ())
|
||||
Throw (Error ().fail (__FILE__, __LINE__, Error::noMoreData));
|
||||
|
||||
return element_from (m_tail.m_prev);
|
||||
}
|
||||
|
||||
/** Obtain a const reference to the last element.
|
||||
|
||||
@invariant The list may not be empty.
|
||||
|
||||
@return A const reference to the last element.
|
||||
*/
|
||||
const_reference back () const
|
||||
{
|
||||
if (empty ())
|
||||
Throw (Error ().fail (__FILE__, __LINE__, Error::noMoreData));
|
||||
|
||||
return element_from (m_tail.m_prev);
|
||||
}
|
||||
|
||||
/** Obtain an iterator to the beginning of the list.
|
||||
|
||||
@return An iterator pointing to the beginning of the list.
|
||||
*/
|
||||
iterator begin ()
|
||||
{
|
||||
return iterator (m_head.m_next);
|
||||
}
|
||||
|
||||
/** Obtain a const iterator to the beginning of the list.
|
||||
|
||||
@return A const iterator pointing to the beginning of the list.
|
||||
*/
|
||||
const_iterator begin () const
|
||||
{
|
||||
return const_iterator (m_head.m_next);
|
||||
}
|
||||
|
||||
/** Obtain a const iterator to the beginning of the list.
|
||||
|
||||
@return A const iterator pointing to the beginning of the list.
|
||||
*/
|
||||
const_iterator cbegin () const
|
||||
{
|
||||
return const_iterator (m_head.m_next);
|
||||
}
|
||||
|
||||
/** Obtain a iterator to the end of the list.
|
||||
|
||||
@return An iterator pointing to the end of the list.
|
||||
*/
|
||||
iterator end ()
|
||||
{
|
||||
return iterator (&m_tail);
|
||||
}
|
||||
|
||||
/** Obtain a const iterator to the end of the list.
|
||||
|
||||
@return A constiterator pointing to the end of the list.
|
||||
*/
|
||||
const_iterator end () const
|
||||
{
|
||||
return const_iterator (&m_tail);
|
||||
}
|
||||
|
||||
/** Obtain a const iterator to the end of the list.
|
||||
|
||||
@return A constiterator pointing to the end of the list.
|
||||
*/
|
||||
const_iterator cend () const
|
||||
{
|
||||
return const_iterator (&m_tail);
|
||||
}
|
||||
|
||||
/** Determine if the list is empty.
|
||||
|
||||
@return `true` if the list is empty.
|
||||
*/
|
||||
bool empty () const
|
||||
{
|
||||
return m_head.m_next == &m_tail;
|
||||
}
|
||||
|
||||
/** Clear the list.
|
||||
|
||||
@note This does not free the elements.
|
||||
*/
|
||||
void clear ()
|
||||
{
|
||||
m_head.m_next = &m_tail;
|
||||
m_tail.m_prev = &m_head;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
/** Insert an element.
|
||||
|
||||
@invariant The element must not already be in the list.
|
||||
|
||||
@param pos The location to insert after.
|
||||
|
||||
@param elem The element to insert.
|
||||
|
||||
@return An iterator pointing to the newly inserted element.
|
||||
*/
|
||||
iterator insert (iterator pos, Element& elem)
|
||||
{
|
||||
Node* node = node_from (elem);
|
||||
node->m_next = pos.get_node ();
|
||||
node->m_prev = node->m_next->m_prev;
|
||||
node->m_next->m_prev = node;
|
||||
node->m_prev->m_next = node;
|
||||
++m_size;
|
||||
return iterator (node);
|
||||
}
|
||||
|
||||
/** Insert another list into this one.
|
||||
|
||||
The other list is cleared.
|
||||
|
||||
@param pos The location to insert after.
|
||||
|
||||
@param other The list to insert.
|
||||
*/
|
||||
|
||||
void insert (iterator pos, List& other)
|
||||
{
|
||||
if (!other.empty ())
|
||||
{
|
||||
Node* before = pos.get_node ();
|
||||
other.m_head.m_next->m_prev = before->m_prev;
|
||||
before->m_prev->m_next = other.m_head.m_next;
|
||||
other.m_tail.m_prev->m_next = before;
|
||||
before->m_prev = other.m_tail.m_prev;
|
||||
m_size += other.m_size;
|
||||
other.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove an element.
|
||||
|
||||
@invariant The element must exist in the list.
|
||||
|
||||
@param pos An iterator pointing to the element to remove.
|
||||
|
||||
@return An iterator pointing to the next element after the one removed.
|
||||
*/
|
||||
iterator erase (iterator pos)
|
||||
{
|
||||
Node* node = pos.get_node ();
|
||||
++pos;
|
||||
node->m_next->m_prev = node->m_prev;
|
||||
node->m_prev->m_next = node->m_next;
|
||||
--m_size;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/** Insert an element at the beginning of the list.
|
||||
|
||||
@invariant The element must not exist in the list.
|
||||
|
||||
@param elem The element to insert.
|
||||
*/
|
||||
void push_front (Element& elem)
|
||||
{
|
||||
insert (begin (), elem);
|
||||
}
|
||||
|
||||
/** Remove the element at the beginning of the list.
|
||||
|
||||
@invariant The list must not be empty.
|
||||
*/
|
||||
void pop_front ()
|
||||
{
|
||||
if (empty ())
|
||||
Throw (Error ().fail (__FILE__, __LINE__, Error::noMoreData));
|
||||
|
||||
erase (begin ());
|
||||
}
|
||||
|
||||
/** Append an element at the end of the list.
|
||||
|
||||
@invariant The element must not exist in the list.
|
||||
|
||||
@param elem The element to append.
|
||||
*/
|
||||
void push_back (Element& elem)
|
||||
{
|
||||
insert (end (), elem);
|
||||
}
|
||||
|
||||
/** Remove the element at the end of the list.
|
||||
|
||||
@invariant The list must not be empty.
|
||||
*/
|
||||
void pop_back ()
|
||||
{
|
||||
if (empty ())
|
||||
Throw (Error ().fail (__FILE__, __LINE__, Error::noMoreData));
|
||||
|
||||
erase (--end ());
|
||||
}
|
||||
|
||||
/** Swap contents with another list.
|
||||
*/
|
||||
void swap (List& other)
|
||||
{
|
||||
List temp;
|
||||
temp.append (other);
|
||||
other.append (*this);
|
||||
append (temp);
|
||||
}
|
||||
|
||||
/** Insert another list at the beginning of this list.
|
||||
|
||||
The other list is cleared.
|
||||
|
||||
@param list The other list to insert.
|
||||
*/
|
||||
void prepend (List& list)
|
||||
{
|
||||
insert (begin (), list);
|
||||
}
|
||||
|
||||
/** Append another list at the end of this list.
|
||||
|
||||
The other list is cleared.
|
||||
|
||||
@param list the other list to append.
|
||||
*/
|
||||
void append (List& list)
|
||||
{
|
||||
insert (end (), list);
|
||||
}
|
||||
|
||||
/** Obtain an iterator from an element.
|
||||
|
||||
@invariant The element must exist in the list.
|
||||
|
||||
@param elem The element to obtain an iterator for.
|
||||
|
||||
@return An iterator to the element.
|
||||
*/
|
||||
iterator iterator_to (Element& elem) const
|
||||
{
|
||||
return iterator (static_cast <Node*> (&elem));
|
||||
}
|
||||
|
||||
/** Obtain a const iterator from an element.
|
||||
|
||||
@invariant The element must exist in the list.
|
||||
|
||||
@param elem The element to obtain an iterator for.
|
||||
|
||||
@return A const iterator to the element.
|
||||
*/
|
||||
const_iterator const_iterator_to (Element const& elem) const
|
||||
{
|
||||
return const_iterator (static_cast <Node const*> (&elem));
|
||||
}
|
||||
|
||||
private:
|
||||
inline reference element_from (Node* node)
|
||||
{
|
||||
return * (static_cast <pointer> (node));
|
||||
}
|
||||
|
||||
inline const_reference element_from (Node const* node) const
|
||||
{
|
||||
return * (static_cast <const_pointer> (node));
|
||||
}
|
||||
|
||||
inline Node* node_from (Element& elem)
|
||||
{
|
||||
return static_cast <Node*> (&elem);
|
||||
}
|
||||
|
||||
inline Node const* node_from (Element const& elem) const
|
||||
{
|
||||
return static_cast <Node const*> (&elem);
|
||||
}
|
||||
|
||||
private:
|
||||
size_type m_size;
|
||||
Node m_head;
|
||||
Node m_tail;
|
||||
};
|
||||
|
||||
/**
|
||||
Default tag for List.
|
||||
|
||||
@ingroup beast_core intrusive
|
||||
*/
|
||||
struct ListDefaultTag { };
|
||||
|
||||
#endif
|
||||
217
modules/beast_core/containers/beast_LockFreeQueue.h
Normal file
217
modules/beast_core/containers/beast_LockFreeQueue.h
Normal file
@@ -0,0 +1,217 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_LOCKFREEQUEUE_BEASTHEADER
|
||||
#define BEAST_LOCKFREEQUEUE_BEASTHEADER
|
||||
|
||||
/** Default tag for LockFreeQueue
|
||||
|
||||
@ingroup beast_core intrusive
|
||||
*/
|
||||
struct LockFreeQueueDefaultTag { };
|
||||
|
||||
/** Multiple Producer, Single Consumer (MPSC) intrusive FIFO.
|
||||
|
||||
This container uses the same intrusive interface as List. It is wait-free
|
||||
for producers and lock-free for consumers. The caller is responsible for
|
||||
preventing the ABA problem (http://en.wikipedia.org/wiki/ABA_problem)
|
||||
|
||||
Invariants:
|
||||
|
||||
- Any thread may call push_back() at any time (Multiple Producer).
|
||||
|
||||
- Only one thread may call try_pop_front() at a time (Single Consumer)
|
||||
|
||||
- The queue is signaled if there are one or more elements.
|
||||
|
||||
@param Tag A type name used to distinguish lists and nodes, for
|
||||
putting objects in multiple lists. If this parameter is
|
||||
omitted, the default tag is used.
|
||||
|
||||
@ingroup beast_core intrusive
|
||||
*/
|
||||
template <class Element, class Tag = LockFreeQueueDefaultTag>
|
||||
class LockFreeQueue
|
||||
{
|
||||
public:
|
||||
class Node : Uncopyable
|
||||
{
|
||||
public:
|
||||
Node () { }
|
||||
explicit Node (Node* next) : m_next (next) { }
|
||||
|
||||
AtomicPointer <Node> m_next;
|
||||
};
|
||||
|
||||
public:
|
||||
/** Create an empty list.
|
||||
*/
|
||||
LockFreeQueue ()
|
||||
: m_head (&m_null)
|
||||
, m_tail (&m_null)
|
||||
, m_null (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/** Determine if the list is empty.
|
||||
|
||||
This is not thread safe, the caller must synchronize.
|
||||
|
||||
@return true if the list is empty.
|
||||
*/
|
||||
bool empty () const
|
||||
{
|
||||
return (m_head.get () == m_tail);
|
||||
}
|
||||
|
||||
/** Put an element into the list.
|
||||
|
||||
This operation is wait-free.
|
||||
|
||||
@param node The element to enqueue.
|
||||
|
||||
@return true if the list was previously empty.
|
||||
*/
|
||||
bool push_back (Node* node)
|
||||
{
|
||||
node->m_next.set (0);
|
||||
|
||||
Node* prev = m_head.exchange (node);
|
||||
|
||||
// (*) If a try_pop_front() happens at this point, it might not see the
|
||||
// element we are pushing. This only happens when the list is empty,
|
||||
// and furthermore it is detectable.
|
||||
|
||||
prev->m_next.set (node);
|
||||
|
||||
return prev == &m_null;
|
||||
}
|
||||
|
||||
/** Retrieve an element from the list.
|
||||
|
||||
This operation is lock-free.
|
||||
|
||||
@return The element, or nullptr if the list was empty.
|
||||
*/
|
||||
Element* pop_front ()
|
||||
{
|
||||
Element* elem;
|
||||
|
||||
// Avoid the SpinDelay ctor if possible
|
||||
if (!try_pop_front (&elem))
|
||||
{
|
||||
SpinDelay delay;
|
||||
|
||||
do
|
||||
{
|
||||
delay.pause ();
|
||||
}
|
||||
while (!try_pop_front (&elem));
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
/** Attempt to retrieve an element.
|
||||
|
||||
This attempts to pop an element from the front of the list. The return
|
||||
value indicates if the operation was successful. An operation is
|
||||
successful if there is no contention for the list. On a successful
|
||||
operation, an element is returned if the list was non empty, else nullptr
|
||||
is returned. On failure, the returned element is undefined.
|
||||
|
||||
This operation is wait-free.
|
||||
|
||||
@param[out] pElem The element that was retrieved, or nullptr if the
|
||||
list was empty.
|
||||
|
||||
@return true if the list was uncontended.
|
||||
*/
|
||||
bool try_pop_front (Element** pElem)
|
||||
{
|
||||
Node* tail = m_tail;
|
||||
Node* next = tail->m_next.get ();
|
||||
|
||||
if (tail == &m_null)
|
||||
{
|
||||
if (next == 0)
|
||||
{
|
||||
// (*) If a push_back() happens at this point,
|
||||
// we might not see the element.
|
||||
|
||||
if (m_head.get () == tail)
|
||||
{
|
||||
*pElem = nullptr;
|
||||
return true; // success, but queue empty
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // failure: a push_back() caused contention
|
||||
}
|
||||
}
|
||||
|
||||
m_tail = next;
|
||||
tail = next;
|
||||
next = next->m_next.get ();
|
||||
}
|
||||
|
||||
if (next)
|
||||
{
|
||||
m_tail = next;
|
||||
*pElem = static_cast <Element*> (tail);
|
||||
return true;
|
||||
}
|
||||
|
||||
Node* head = m_head.get ();
|
||||
|
||||
if (tail == head)
|
||||
{
|
||||
push_back (&m_null);
|
||||
next = tail->m_next.get ();
|
||||
|
||||
if (next)
|
||||
{
|
||||
m_tail = next;
|
||||
*pElem = static_cast <Element*> (tail);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// (*) If a push_back() happens at this point,
|
||||
// we might not see the element.
|
||||
|
||||
if (head == m_tail)
|
||||
{
|
||||
*pElem = nullptr;
|
||||
return true; // success, but queue empty
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // failure: a push_back() caused contention
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Elements are pushed on to the head and popped from the tail.
|
||||
AtomicPointer <Node> m_head;
|
||||
Node* m_tail;
|
||||
Node m_null;
|
||||
};
|
||||
|
||||
#endif
|
||||
165
modules/beast_core/containers/beast_LockFreeStack.h
Normal file
165
modules/beast_core/containers/beast_LockFreeStack.h
Normal file
@@ -0,0 +1,165 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_LOCKFREESTACK_BEASTHEADER
|
||||
#define BEAST_LOCKFREESTACK_BEASTHEADER
|
||||
|
||||
struct LockFreeStackDefaultTag;
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
Multiple Producer, Multiple Consumer (MPMC) intrusive stack.
|
||||
|
||||
This stack is implemented using the same intrusive interface as List. All
|
||||
operations are lock-free.
|
||||
|
||||
The caller is responsible for preventing the "ABA" problem
|
||||
(http://en.wikipedia.org/wiki/ABA_problem)
|
||||
|
||||
@param Tag A type name used to distinguish lists and nodes, for
|
||||
putting objects in multiple lists. If this parameter is
|
||||
omitted, the default tag is used.
|
||||
|
||||
@ingroup beast_core intrusive
|
||||
*/
|
||||
template <class Element, class Tag = LockFreeStackDefaultTag>
|
||||
class LockFreeStack : Uncopyable
|
||||
{
|
||||
public:
|
||||
class Node : Uncopyable
|
||||
{
|
||||
public:
|
||||
Node ()
|
||||
{
|
||||
}
|
||||
|
||||
explicit Node (Node* next) : m_next (next)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend class LockFreeStack;
|
||||
|
||||
// VFALCO TODO Use regular Atomic<>
|
||||
AtomicPointer <Node> m_next;
|
||||
};
|
||||
|
||||
public:
|
||||
LockFreeStack () : m_head (0)
|
||||
{
|
||||
}
|
||||
|
||||
/** Create a LockFreeStack from another stack.
|
||||
|
||||
The contents of the other stack are atomically acquired.
|
||||
The other stack is cleared.
|
||||
|
||||
@param other The other stack to acquire.
|
||||
*/
|
||||
explicit LockFreeStack (LockFreeStack& other)
|
||||
{
|
||||
Node* head;
|
||||
|
||||
do
|
||||
{
|
||||
head = other.m_head.get ();
|
||||
}
|
||||
while (!other.m_head.compareAndSet (0, head));
|
||||
|
||||
m_head = head;
|
||||
}
|
||||
|
||||
/** Push a node onto the stack.
|
||||
|
||||
The caller is responsible for preventing the ABA problem. This operation
|
||||
is lock-free.
|
||||
|
||||
@param node The node to push.
|
||||
|
||||
@return True if the stack was previously empty. If multiple threads
|
||||
are attempting to push, only one will receive true.
|
||||
*/
|
||||
bool push_front (Node* node)
|
||||
{
|
||||
bool first;
|
||||
Node* head;
|
||||
|
||||
do
|
||||
{
|
||||
head = m_head.get ();
|
||||
first = head == 0;
|
||||
node->m_next = head;
|
||||
}
|
||||
while (!m_head.compareAndSet (node, head));
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
/** Pop an element off the stack.
|
||||
|
||||
The caller is responsible for preventing the ABA problem. This operation
|
||||
is lock-free.
|
||||
|
||||
@return The element that was popped, or nullptr if the stack was empty.
|
||||
*/
|
||||
Element* pop_front ()
|
||||
{
|
||||
Node* node;
|
||||
Node* head;
|
||||
|
||||
do
|
||||
{
|
||||
node = m_head.get ();
|
||||
|
||||
if (node == 0)
|
||||
break;
|
||||
|
||||
head = node->m_next.get ();
|
||||
}
|
||||
while (!m_head.compareAndSet (head, node));
|
||||
|
||||
return node ? static_cast <Element*> (node) : nullptr;
|
||||
}
|
||||
|
||||
/** Swap the contents of this stack with another stack.
|
||||
|
||||
This call is not thread safe or atomic. The caller is responsible for
|
||||
synchronizing access.
|
||||
|
||||
@param other The other stack to swap contents with.
|
||||
*/
|
||||
void swap (LockFreeStack& other)
|
||||
{
|
||||
Node* temp = other.m_head.get ();
|
||||
other.m_head.set (m_head.get ());
|
||||
m_head.set (temp);
|
||||
}
|
||||
|
||||
private:
|
||||
AtomicPointer <Node> m_head;
|
||||
};
|
||||
|
||||
/*============================================================================*/
|
||||
/** Default tag for LockFreeStack
|
||||
|
||||
@ingroup beast_core intrusive
|
||||
*/
|
||||
struct LockFreeStackDefaultTag { };
|
||||
|
||||
#endif
|
||||
212
modules/beast_core/containers/beast_SharedTable.h
Normal file
212
modules/beast_core/containers/beast_SharedTable.h
Normal file
@@ -0,0 +1,212 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SHAREDTABLE_BEASTHEADER
|
||||
#define BEAST_SHAREDTABLE_BEASTHEADER
|
||||
|
||||
/** Handle to a reference counted fixed size table.
|
||||
|
||||
@note Currently, ElementType must be an aggregate of POD.
|
||||
|
||||
@tparam ElementType The type of element.
|
||||
|
||||
@ingroup beast_basics
|
||||
*/
|
||||
template <class ElementType>
|
||||
class SharedTable
|
||||
{
|
||||
public:
|
||||
typedef ElementType Entry;
|
||||
|
||||
static SharedTable <ElementType> const null;
|
||||
|
||||
/** Creates a null table.
|
||||
*/
|
||||
SharedTable ()
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a table with the specified number of entries.
|
||||
|
||||
The entries are uninitialized.
|
||||
|
||||
@param numEntries The number of entries in the table.
|
||||
|
||||
@todo Initialize the data if ElementType is not POD.
|
||||
*/
|
||||
explicit SharedTable (int numEntries)
|
||||
: m_data (new Data (numEntries))
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a shared reference to another table.
|
||||
*/
|
||||
SharedTable (SharedTable const& other)
|
||||
: m_data (other.m_data)
|
||||
{
|
||||
}
|
||||
|
||||
/** Makes this table refer to another table.
|
||||
*/
|
||||
SharedTable& operator= (SharedTable const& other)
|
||||
{
|
||||
m_data = other.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
SharedTable (SharedTable&& other) noexcept
|
||||
: m_data (static_cast < typename Data::Ptr&& > (other.m_data))
|
||||
{
|
||||
}
|
||||
|
||||
SharedTable& operator= (SharedTable && other) noexcept
|
||||
{
|
||||
m_data = static_cast < typename Data::Ptr && > (other.m_data);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Destructor.
|
||||
*/
|
||||
~SharedTable ()
|
||||
{
|
||||
}
|
||||
|
||||
/** Returns true if the two tables share the same set of entries.
|
||||
*/
|
||||
bool operator== (SharedTable const& other) const noexcept
|
||||
{
|
||||
return m_data == other.m_data;
|
||||
}
|
||||
|
||||
/** Returns true if the two tables do not share the same set of entries.
|
||||
*/
|
||||
bool operator!= (SharedTable const& other) const noexcept
|
||||
{
|
||||
return m_data != other.m_data;
|
||||
}
|
||||
|
||||
/** Returns true if the table is not null.
|
||||
*/
|
||||
inline bool isValid () const noexcept
|
||||
{
|
||||
return m_data != nullptr;
|
||||
}
|
||||
|
||||
/** Returns true if the table is null.
|
||||
*/
|
||||
inline bool isNull () const noexcept
|
||||
{
|
||||
return m_data == nullptr;
|
||||
}
|
||||
|
||||
/** Returns the number of tables referring to the same shared entries.
|
||||
*/
|
||||
int getReferenceCount () const noexcept
|
||||
{
|
||||
return m_data == nullptr ? 0 : m_data->getReferenceCount ();
|
||||
}
|
||||
|
||||
/** Create a physical duplicate of the table.
|
||||
*/
|
||||
SharedTable createCopy () const
|
||||
{
|
||||
return SharedTable (m_data != nullptr ? m_data->clone () : nullptr);
|
||||
}
|
||||
|
||||
/** Makes sure no other tables share the same entries as this table.
|
||||
*/
|
||||
void duplicateIfShared ()
|
||||
{
|
||||
if (m_data != nullptr && m_data->getReferenceCount () > 1)
|
||||
m_data = m_data->clone ();
|
||||
}
|
||||
|
||||
/** Return the number of entries in this table.
|
||||
*/
|
||||
inline int getNumEntries () const noexcept
|
||||
{
|
||||
return m_data->getNumEntries ();
|
||||
}
|
||||
|
||||
/** Retrieve a table entry.
|
||||
|
||||
@param index The index of the entry, from 0 to getNumEntries ().
|
||||
*/
|
||||
inline ElementType& operator [] (int index) const noexcept
|
||||
{
|
||||
return m_data->getReference (index);
|
||||
}
|
||||
|
||||
private:
|
||||
class Data : public ReferenceCountedObject
|
||||
{
|
||||
public:
|
||||
typedef ReferenceCountedObjectPtr <Data> Ptr;
|
||||
|
||||
explicit Data (int numEntries)
|
||||
: m_numEntries (numEntries)
|
||||
, m_table (numEntries)
|
||||
{
|
||||
}
|
||||
|
||||
inline Data* clone () const
|
||||
{
|
||||
Data* data = new Data (m_numEntries);
|
||||
|
||||
memcpy (
|
||||
data->m_table.getData (),
|
||||
m_table.getData (),
|
||||
m_numEntries * sizeof (ElementType));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
inline int getNumEntries () const
|
||||
{
|
||||
return m_numEntries;
|
||||
}
|
||||
|
||||
inline ElementType& getReference (int index) const
|
||||
{
|
||||
bassert (index >= 0 && index < m_numEntries);
|
||||
return m_table [index];
|
||||
}
|
||||
|
||||
private:
|
||||
int const m_numEntries;
|
||||
HeapBlock <ElementType> const m_table;
|
||||
};
|
||||
|
||||
explicit SharedTable (Data* data)
|
||||
: m_data (data)
|
||||
{
|
||||
}
|
||||
|
||||
ReferenceCountedObjectPtr <Data> m_data;
|
||||
};
|
||||
|
||||
template <class ElementType>
|
||||
SharedTable <ElementType> const SharedTable <ElementType>::null;
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
154
modules/beast_core/containers/beast_SortedLookupTable.h
Normal file
154
modules/beast_core/containers/beast_SortedLookupTable.h
Normal file
@@ -0,0 +1,154 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SORTEDLOOKUPTABLE_BEASTHEADER
|
||||
#define BEAST_SORTEDLOOKUPTABLE_BEASTHEADER
|
||||
|
||||
/** Sorted map for fast lookups.
|
||||
|
||||
This container is optimized for a data set with fixed elements.
|
||||
|
||||
SchemaType obeys this concept:
|
||||
|
||||
@code
|
||||
|
||||
struct SchemaType
|
||||
{
|
||||
typename KeyType;
|
||||
typename ValueType;
|
||||
|
||||
// Retrieve the key for a specified value.
|
||||
KeyType getKey (Value const& value);
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
To use the table, reserve space with reserveSpaceForValues() if the number
|
||||
of elements is known ahead of time. Then, call insert() for all the your
|
||||
elements. Call prepareForLookups() once then call lookupValueByKey ()
|
||||
*/
|
||||
template <class SchemaType>
|
||||
class SortedLookupTable
|
||||
{
|
||||
private:
|
||||
typedef typename SchemaType::KeyType KeyType;
|
||||
typedef typename SchemaType::ValueType ValueType;
|
||||
typedef std::vector <ValueType> values_t;
|
||||
|
||||
private:
|
||||
struct SortCompare
|
||||
{
|
||||
bool operator () (ValueType const& lhs, ValueType const& rhs) const
|
||||
{
|
||||
return SchemaType ().getKey (lhs) < SchemaType ().getKey (rhs);
|
||||
}
|
||||
};
|
||||
|
||||
struct FindCompare
|
||||
{
|
||||
bool operator () (ValueType const& lhs, ValueType const& rhs)
|
||||
{
|
||||
return SchemaType ().getKey (lhs) < SchemaType ().getKey (rhs);
|
||||
}
|
||||
|
||||
bool operator () (KeyType const& key, ValueType const& rhs)
|
||||
{
|
||||
return key < SchemaType ().getKey (rhs);
|
||||
}
|
||||
|
||||
bool operator () (ValueType const& lhs, KeyType const& key)
|
||||
{
|
||||
return SchemaType ().getKey (lhs) < key;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename values_t::size_type size_type;
|
||||
|
||||
/** Reserve space for values.
|
||||
|
||||
Although not necessary, this can help with memory usage if the
|
||||
number of values is known ahead of time.
|
||||
|
||||
@param numberOfValues The amount of space to reserve.
|
||||
*/
|
||||
void reserveSpaceForValues (size_type numberOfValues)
|
||||
{
|
||||
m_values.reserve (numberOfValues);
|
||||
}
|
||||
|
||||
/** Insert a value into the index.
|
||||
|
||||
@invariant The value must not already exist in the index.
|
||||
|
||||
@param valueToInsert The value to insert.
|
||||
*/
|
||||
void insert (ValueType const& valueToInsert)
|
||||
{
|
||||
m_values.push_back (valueToInsert);
|
||||
}
|
||||
|
||||
/** Prepare the index for lookups.
|
||||
|
||||
This must be called at least once after calling insert()
|
||||
and before calling find().
|
||||
*/
|
||||
void prepareForLookups ()
|
||||
{
|
||||
std::sort (m_values.begin (), m_values.end (), SortCompare ());
|
||||
}
|
||||
|
||||
/** Find the value for a key.
|
||||
|
||||
Quickly locates a value matching the key, or returns false
|
||||
indicating no value was found.
|
||||
|
||||
@invariant You must call prepareForLookups() once, after all
|
||||
insertions, before calling this function.
|
||||
|
||||
@param key The key to locate.
|
||||
@param pFoundValue Pointer to store the value if a matching
|
||||
key was found.
|
||||
@return `true` if the value was found.
|
||||
*/
|
||||
bool lookupValueByKey (KeyType const& key, ValueType* pFoundValue)
|
||||
{
|
||||
bool found;
|
||||
|
||||
std::pair <typename values_t::iterator, typename values_t::iterator> result =
|
||||
std::equal_range (m_values.begin (), m_values.end (), key, FindCompare ());
|
||||
|
||||
if (result.first != result.second)
|
||||
{
|
||||
*pFoundValue = *result.first;
|
||||
found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
found = false;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private:
|
||||
values_t m_values;
|
||||
};
|
||||
|
||||
#endif
|
||||
255
modules/beast_core/diagnostic/beast_Debug.cpp
Normal file
255
modules/beast_core/diagnostic/beast_Debug.cpp
Normal file
@@ -0,0 +1,255 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace Debug
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool isDebuggerAttached ()
|
||||
{
|
||||
return beast_isRunningUnderDebugger ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if BEAST_DEBUG && defined (beast_breakDebugger)
|
||||
void breakPoint ()
|
||||
{
|
||||
if (isDebuggerAttached ())
|
||||
beast_breakDebugger;
|
||||
}
|
||||
|
||||
#else
|
||||
void breakPoint ()
|
||||
{
|
||||
bassertfalse
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if BEAST_MSVC && defined (_DEBUG)
|
||||
|
||||
void setHeapAlwaysCheck (bool bAlwaysCheck)
|
||||
{
|
||||
int flags = _CrtSetDbgFlag (_CRTDBG_REPORT_FLAG);
|
||||
|
||||
if (bAlwaysCheck) flags |= _CRTDBG_CHECK_ALWAYS_DF; // on
|
||||
else flags &= ~_CRTDBG_CHECK_ALWAYS_DF; // off
|
||||
|
||||
_CrtSetDbgFlag (flags);
|
||||
}
|
||||
|
||||
void setHeapDelayedFree (bool bDelayedFree)
|
||||
{
|
||||
int flags = _CrtSetDbgFlag (_CRTDBG_REPORT_FLAG);
|
||||
|
||||
if (bDelayedFree) flags |= _CRTDBG_DELAY_FREE_MEM_DF; // on
|
||||
else flags &= ~_CRTDBG_DELAY_FREE_MEM_DF; // off
|
||||
|
||||
_CrtSetDbgFlag (flags);
|
||||
}
|
||||
|
||||
void setHeapReportLeaks (bool bReportLeaks)
|
||||
{
|
||||
int flags = _CrtSetDbgFlag (_CRTDBG_REPORT_FLAG);
|
||||
|
||||
if (bReportLeaks) flags |= _CRTDBG_LEAK_CHECK_DF; // on
|
||||
else flags &= ~_CRTDBG_LEAK_CHECK_DF; // off
|
||||
|
||||
_CrtSetDbgFlag (flags);
|
||||
}
|
||||
|
||||
void checkHeap ()
|
||||
{
|
||||
_CrtCheckMemory ();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void setHeapAlwaysCheck (bool)
|
||||
{
|
||||
}
|
||||
|
||||
void setHeapDelayedFree (bool)
|
||||
{
|
||||
}
|
||||
|
||||
void setHeapReportLeaks (bool)
|
||||
{
|
||||
}
|
||||
|
||||
void checkHeap ()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const String getFileNameFromPath (const char* sourceFileName)
|
||||
{
|
||||
return File::createFileWithoutCheckingPath (sourceFileName).getFileName ();
|
||||
}
|
||||
|
||||
// Returns a String with double quotes escaped
|
||||
static const String withEscapedQuotes (String const& string)
|
||||
{
|
||||
String escaped;
|
||||
|
||||
int i0 = 0;
|
||||
int i;
|
||||
|
||||
do
|
||||
{
|
||||
i = string.indexOfChar (i0, '"');
|
||||
|
||||
if (i == -1)
|
||||
{
|
||||
escaped << string.substring (i0, string.length ());
|
||||
}
|
||||
else
|
||||
{
|
||||
escaped << string.substring (i0, i) << "\\\"";
|
||||
i0 = i + 1;
|
||||
}
|
||||
}
|
||||
while (i != -1);
|
||||
|
||||
return escaped;
|
||||
}
|
||||
|
||||
// Converts escaped quotes back into regular quotes
|
||||
static const String withUnescapedQuotes (String const& string)
|
||||
{
|
||||
String unescaped;
|
||||
|
||||
int i0 = 0;
|
||||
int i;
|
||||
|
||||
do
|
||||
{
|
||||
i = string.indexOfChar (i0, '\\');
|
||||
|
||||
if (i == -1)
|
||||
{
|
||||
unescaped << string.substring (i0, string.length ());
|
||||
}
|
||||
else
|
||||
{
|
||||
// peek
|
||||
if (string.length () > i && string[i + 1] == '\"')
|
||||
{
|
||||
unescaped << string.substring (i0, i) << '"';
|
||||
i0 = i + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
unescaped << string.substring (i0, i + 1);
|
||||
i0 = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (i != -1);
|
||||
|
||||
return unescaped;
|
||||
}
|
||||
|
||||
// Converts a String that may contain newlines, into a
|
||||
// command line where each line is delimited with quotes.
|
||||
// Any quotes in the actual string will be escaped via \".
|
||||
String stringToCommandLine (String const& string)
|
||||
{
|
||||
String commandLine;
|
||||
|
||||
int i0 = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < string.length (); i++)
|
||||
{
|
||||
beast_wchar c = string[i];
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
if (i0 != 0)
|
||||
commandLine << ' ';
|
||||
|
||||
commandLine << '"' << withEscapedQuotes (string.substring (i0, i)) << '"';
|
||||
i0 = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (i0 < i)
|
||||
{
|
||||
if (i0 != 0)
|
||||
commandLine << ' ';
|
||||
|
||||
commandLine << '"' << withEscapedQuotes (string.substring (i0, i)) << '"';
|
||||
}
|
||||
|
||||
return commandLine;
|
||||
}
|
||||
|
||||
// Converts a command line consisting of multiple quoted strings
|
||||
// back into a single string with newlines delimiting each quoted
|
||||
// string. Escaped quotes \" are turned into real quotes.
|
||||
String commandLineToString (const String& commandLine)
|
||||
{
|
||||
String string;
|
||||
|
||||
bool quoting = false;
|
||||
int i0 = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < commandLine.length (); i++)
|
||||
{
|
||||
beast_wchar c = commandLine[i];
|
||||
|
||||
if (c == '\\')
|
||||
{
|
||||
// peek
|
||||
if (commandLine.length () > i && commandLine[i + 1] == '\"')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else if (c == '"')
|
||||
{
|
||||
if (!quoting)
|
||||
{
|
||||
i0 = i + 1;
|
||||
quoting = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.isEmpty ())
|
||||
string << '\n';
|
||||
|
||||
string << withUnescapedQuotes (commandLine.substring (i0, i));
|
||||
quoting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
}
|
||||
56
modules/beast_core/diagnostic/beast_Debug.h
Normal file
56
modules/beast_core/diagnostic/beast_Debug.h
Normal file
@@ -0,0 +1,56 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_DEBUG_BEASTHEADER
|
||||
#define BEAST_DEBUG_BEASTHEADER
|
||||
|
||||
// Auxiliary outines for debugging
|
||||
|
||||
namespace Debug
|
||||
{
|
||||
|
||||
// Returns true if a debugger is attached, for any build.
|
||||
extern bool isDebuggerAttached ();
|
||||
|
||||
// Breaks to the debugger if a debugger is attached.
|
||||
extern void breakPoint ();
|
||||
|
||||
// VFALCO NOTE IS THIS REALLY THE RIGHT PLACE FOR THESE??
|
||||
//
|
||||
// Return only the filename portion of sourceFileName
|
||||
// This hides the programmer's directory structure from end-users.
|
||||
const String getFileNameFromPath (const char* sourceFileName);
|
||||
|
||||
// Convert a String that may contain double quotes and newlines
|
||||
// into a String with double quotes escaped as \" and each
|
||||
// line as a separate quoted command line argument.
|
||||
String stringToCommandLine (const String& s);
|
||||
|
||||
// Convert a quoted and escaped command line back into a String
|
||||
// that can contain newlines and double quotes.
|
||||
String commandLineToString (const String& commandLine);
|
||||
|
||||
extern void setHeapAlwaysCheck (bool bAlwaysCheck);
|
||||
extern void setHeapDelayedFree (bool bDelayedFree);
|
||||
extern void setHeapReportLeaks (bool bReportLeaks);
|
||||
extern void checkHeap ();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
243
modules/beast_core/diagnostic/beast_Error.cpp
Normal file
243
modules/beast_core/diagnostic/beast_Error.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
Error::Error ()
|
||||
: m_code (success)
|
||||
, m_lineNumber (0)
|
||||
, m_needsToBeChecked (true)
|
||||
, m_szWhat (0)
|
||||
{
|
||||
}
|
||||
|
||||
Error::Error (Error const& other)
|
||||
: m_code (other.m_code)
|
||||
, m_reasonText (other.m_reasonText)
|
||||
, m_sourceFileName (other.m_sourceFileName)
|
||||
, m_lineNumber (other.m_lineNumber)
|
||||
, m_needsToBeChecked (true)
|
||||
, m_szWhat (0)
|
||||
{
|
||||
other.m_needsToBeChecked = false;
|
||||
}
|
||||
|
||||
Error::~Error () noexcept
|
||||
{
|
||||
/* If this goes off it means an error object was created but never tested */
|
||||
bassert (!m_needsToBeChecked);
|
||||
}
|
||||
|
||||
Error& Error::operator= (Error const& other)
|
||||
{
|
||||
m_code = other.m_code;
|
||||
m_reasonText = other.m_reasonText;
|
||||
m_sourceFileName = other.m_sourceFileName;
|
||||
m_lineNumber = other.m_lineNumber;
|
||||
m_needsToBeChecked = true;
|
||||
m_what = String::empty;
|
||||
m_szWhat = 0;
|
||||
|
||||
other.m_needsToBeChecked = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Error::Code Error::code () const
|
||||
{
|
||||
m_needsToBeChecked = false;
|
||||
return m_code;
|
||||
}
|
||||
|
||||
bool Error::failed () const
|
||||
{
|
||||
return code () != success;
|
||||
}
|
||||
|
||||
bool Error::asBoolean () const
|
||||
{
|
||||
return code () != success;
|
||||
}
|
||||
|
||||
String const Error::getReasonText () const
|
||||
{
|
||||
return m_reasonText;
|
||||
}
|
||||
|
||||
String const Error::getSourceFilename () const
|
||||
{
|
||||
return m_sourceFileName;
|
||||
}
|
||||
|
||||
int Error::getLineNumber () const
|
||||
{
|
||||
return m_lineNumber;
|
||||
}
|
||||
|
||||
Error& Error::fail (char const* sourceFileName,
|
||||
int lineNumber,
|
||||
String const reasonText,
|
||||
Code errorCode)
|
||||
{
|
||||
bassert (m_code == success);
|
||||
bassert (errorCode != success);
|
||||
|
||||
m_code = errorCode;
|
||||
m_reasonText = reasonText;
|
||||
m_sourceFileName = Debug::getFileNameFromPath (sourceFileName);
|
||||
m_lineNumber = lineNumber;
|
||||
m_needsToBeChecked = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Error& Error::fail (char const* sourceFileName,
|
||||
int lineNumber,
|
||||
Code errorCode)
|
||||
{
|
||||
return fail (sourceFileName,
|
||||
lineNumber,
|
||||
getReasonTextForCode (errorCode),
|
||||
errorCode);
|
||||
}
|
||||
|
||||
void Error::reset ()
|
||||
{
|
||||
m_code = success;
|
||||
m_reasonText = String::empty;
|
||||
m_sourceFileName = String::empty;
|
||||
m_lineNumber = 0;
|
||||
m_needsToBeChecked = true;
|
||||
m_what = String::empty;
|
||||
m_szWhat = 0;
|
||||
}
|
||||
|
||||
void Error::willBeReported () const
|
||||
{
|
||||
m_needsToBeChecked = false;
|
||||
}
|
||||
|
||||
char const* Error::what () const noexcept
|
||||
{
|
||||
if (! m_szWhat)
|
||||
{
|
||||
// The application could not be initialized because sqlite was denied access permission
|
||||
// The application unexpectedly quit because the exception 'sqlite was denied access permission at file ' was thrown
|
||||
m_what <<
|
||||
m_reasonText << " " <<
|
||||
TRANS ("at file") << " '" <<
|
||||
m_sourceFileName << "' " <<
|
||||
TRANS ("line") << " " <<
|
||||
String (m_lineNumber) << " " <<
|
||||
TRANS ("with code") << " = " <<
|
||||
String (m_code);
|
||||
|
||||
m_szWhat = (const char*)m_what.toUTF8 ();
|
||||
}
|
||||
|
||||
return m_szWhat;
|
||||
}
|
||||
|
||||
String const Error::getReasonTextForCode (Code code)
|
||||
{
|
||||
String s;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case success:
|
||||
s = TRANS ("the operation was successful");
|
||||
break;
|
||||
|
||||
case general:
|
||||
s = TRANS ("a general error occurred");
|
||||
break;
|
||||
|
||||
case canceled:
|
||||
s = TRANS ("the operation was canceled");
|
||||
break;
|
||||
|
||||
case exception:
|
||||
s = TRANS ("an exception was thrown");
|
||||
break;
|
||||
|
||||
case unexpected:
|
||||
s = TRANS ("an unexpected result was encountered");
|
||||
break;
|
||||
|
||||
case platform:
|
||||
s = TRANS ("a system exception was signaled");
|
||||
break;
|
||||
|
||||
case noMemory:
|
||||
s = TRANS ("there was not enough memory");
|
||||
break;
|
||||
|
||||
case noMoreData:
|
||||
s = TRANS ("the end of data was reached");
|
||||
break;
|
||||
|
||||
case invalidData:
|
||||
s = TRANS ("the data is corrupt or invalid");
|
||||
break;
|
||||
|
||||
case bufferSpace:
|
||||
s = TRANS ("the buffer is too small");
|
||||
break;
|
||||
|
||||
case badParameter:
|
||||
s = TRANS ("one or more parameters were invalid");
|
||||
break;
|
||||
|
||||
case assertFailed:
|
||||
s = TRANS ("an assertion failed");
|
||||
break;
|
||||
|
||||
case fileInUse:
|
||||
s = TRANS ("the file is in use");
|
||||
break;
|
||||
|
||||
case fileExists:
|
||||
s = TRANS ("the file exists");
|
||||
break;
|
||||
|
||||
case fileNoPerm:
|
||||
s = TRANS ("permission was denied");
|
||||
break;
|
||||
|
||||
case fileIOError:
|
||||
s = TRANS ("an I/O or device error occurred");
|
||||
break;
|
||||
|
||||
case fileNoSpace:
|
||||
s = TRANS ("there is no space left on the device");
|
||||
break;
|
||||
|
||||
case fileNotFound:
|
||||
s = TRANS ("the file was not found");
|
||||
break;
|
||||
|
||||
case fileNameInvalid:
|
||||
s = TRANS ("the file name was illegal or malformed");
|
||||
break;
|
||||
|
||||
default:
|
||||
s = TRANS ("an unknown error code was received");
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
122
modules/beast_core/diagnostic/beast_Error.h
Normal file
122
modules/beast_core/diagnostic/beast_Error.h
Normal file
@@ -0,0 +1,122 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ERROR_BEASTHEADER
|
||||
#define BEAST_ERROR_BEASTHEADER
|
||||
|
||||
/** A concise error report.
|
||||
|
||||
This lightweight but flexible class records lets you record the file and
|
||||
line where a recoverable error occurred, along with some optional human
|
||||
readable text.
|
||||
|
||||
A recoverable error can be passed along and turned into a non recoverable
|
||||
error by throwing the object: it's derivation from std::exception is
|
||||
fully compliant with the C++ exception interface.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
class BEAST_API Error
|
||||
: public std::exception
|
||||
, public SafeBool <Error>
|
||||
{
|
||||
public:
|
||||
/** Numeric code.
|
||||
|
||||
This enumeration is useful when the caller needs to take different
|
||||
actions depending on the failure. For example, trying again later if
|
||||
a file is locked.
|
||||
*/
|
||||
enum Code
|
||||
{
|
||||
success, //!< "the operation was successful"
|
||||
|
||||
general, //!< "a general error occurred"
|
||||
|
||||
canceled, //!< "the operation was canceled"
|
||||
exception, //!< "an exception was thrown"
|
||||
unexpected, //!< "an unexpected result was encountered"
|
||||
platform, //!< "a system exception was signaled"
|
||||
|
||||
noMemory, //!< "there was not enough memory"
|
||||
noMoreData, //!< "the end of data was reached"
|
||||
invalidData, //!< "the data is corrupt or invalid"
|
||||
bufferSpace, //!< "the buffer is too small"
|
||||
badParameter, //!< "one or more parameters were invalid"
|
||||
assertFailed, //!< "an assertion failed"
|
||||
|
||||
fileInUse, //!< "the file is in use"
|
||||
fileExists, //!< "the file exists"
|
||||
fileNoPerm, //!< "permission was denied" (file attributes conflict)
|
||||
fileIOError, //!< "an I/O or device error occurred"
|
||||
fileNoSpace, //!< "there is no space left on the device"
|
||||
fileNotFound, //!< "the file was not found"
|
||||
fileNameInvalid //!< "the file name was illegal or malformed"
|
||||
};
|
||||
|
||||
Error ();
|
||||
Error (Error const& other);
|
||||
Error& operator= (Error const& other);
|
||||
|
||||
virtual ~Error () noexcept;
|
||||
|
||||
Code code () const;
|
||||
bool failed () const;
|
||||
|
||||
bool asBoolean () const;
|
||||
|
||||
String const getReasonText () const;
|
||||
String const getSourceFilename () const;
|
||||
int getLineNumber () const;
|
||||
|
||||
Error& fail (char const* sourceFileName,
|
||||
int lineNumber,
|
||||
String const reasonText,
|
||||
Code errorCode = general);
|
||||
|
||||
Error& fail (char const* sourceFileName,
|
||||
int lineNumber,
|
||||
Code errorCode = general);
|
||||
|
||||
// A function that is capable of recovering from an error (for
|
||||
// example, by performing a different action) can reset the
|
||||
// object so it can be passed up.
|
||||
void reset ();
|
||||
|
||||
// Call this when reporting the error to clear the "checked" flag
|
||||
void willBeReported () const;
|
||||
|
||||
// for std::exception. This lets you throw an Error that should
|
||||
// terminate the application. The what() message will be less
|
||||
// descriptive so ideally you should catch the Error object instead.
|
||||
char const* what () const noexcept;
|
||||
|
||||
static String const getReasonTextForCode (Code code);
|
||||
|
||||
private:
|
||||
Code m_code;
|
||||
String m_reasonText;
|
||||
String m_sourceFileName;
|
||||
int m_lineNumber;
|
||||
mutable bool m_needsToBeChecked;
|
||||
mutable String m_what; // created on demand
|
||||
mutable char const* m_szWhat;
|
||||
};
|
||||
|
||||
#endif
|
||||
40
modules/beast_core/diagnostic/beast_FPUFlags.cpp
Normal file
40
modules/beast_core/diagnostic/beast_FPUFlags.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
void FPUFlags::clearUnsetFlagsFrom (const FPUFlags& flags)
|
||||
{
|
||||
if (!flags.getMaskNaNs ().is_set ()) m_maskNaNs.clear ();
|
||||
|
||||
if (!flags.getMaskDenormals ().is_set ()) m_maskDenormals.clear ();
|
||||
|
||||
if (!flags.getMaskZeroDivides ().is_set ()) m_maskZeroDivides.clear ();
|
||||
|
||||
if (!flags.getMaskOverflows ().is_set ()) m_maskOverflows.clear ();
|
||||
|
||||
if (!flags.getMaskUnderflows ().is_set ()) m_maskUnderflows.clear ();
|
||||
|
||||
//if (!flags.getMaskInexacts().is_set ()) m_maskInexacts.clear ();
|
||||
if (!flags.getFlushDenormals ().is_set ()) m_flushDenormals.clear ();
|
||||
|
||||
if (!flags.getInfinitySigned ().is_set ()) m_infinitySigned.clear ();
|
||||
|
||||
if (!flags.getRounding ().is_set ()) m_rounding.clear ();
|
||||
|
||||
if (!flags.getPrecision ().is_set ()) m_precision.clear ();
|
||||
}
|
||||
335
modules/beast_core/diagnostic/beast_FPUFlags.h
Normal file
335
modules/beast_core/diagnostic/beast_FPUFlags.h
Normal file
@@ -0,0 +1,335 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_FPUFLAGS_BEASTHEADER
|
||||
#define BEAST_FPUFLAGS_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A set of IEEE FPU flags.
|
||||
|
||||
Description.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
class BEAST_API FPUFlags
|
||||
{
|
||||
public:
|
||||
/** An individual FPU flag */
|
||||
struct Flag
|
||||
{
|
||||
Flag () : m_set (false) { }
|
||||
Flag (Flag const& flag) : m_set (flag.m_set), m_value (flag.m_value) { }
|
||||
Flag& operator= (Flag const& flag)
|
||||
{
|
||||
m_set = flag.m_set;
|
||||
m_value = flag.m_value;
|
||||
return *this;
|
||||
}
|
||||
bool is_set () const
|
||||
{
|
||||
return m_set;
|
||||
}
|
||||
bool value () const
|
||||
{
|
||||
assert (m_set);
|
||||
return m_value;
|
||||
}
|
||||
void set_value (bool value)
|
||||
{
|
||||
m_set = true;
|
||||
m_value = value;
|
||||
}
|
||||
void clear ()
|
||||
{
|
||||
m_set = false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_set : 1;
|
||||
bool m_value : 1;
|
||||
};
|
||||
|
||||
/** A multi-valued FPU setting */
|
||||
template <typename Constants>
|
||||
struct Enum
|
||||
{
|
||||
Enum () : m_set (false) { }
|
||||
Enum (Enum const& value) : m_set (value.m_set), m_value (value.m_value) { }
|
||||
Enum& operator= (Enum const& value)
|
||||
{
|
||||
m_set = value.m_set;
|
||||
m_value = value.m_value;
|
||||
return *this;
|
||||
}
|
||||
bool is_set () const
|
||||
{
|
||||
return m_set;
|
||||
}
|
||||
Constants value () const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
void set_value (Constants value)
|
||||
{
|
||||
m_set = true;
|
||||
m_value = value;
|
||||
}
|
||||
void clear ()
|
||||
{
|
||||
m_set = false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_set : 1;
|
||||
Constants m_value;
|
||||
};
|
||||
|
||||
public:
|
||||
//
|
||||
// Exception masks
|
||||
//
|
||||
|
||||
void setMaskNaNs (bool mask = true)
|
||||
{
|
||||
m_maskNaNs.set_value (mask);
|
||||
}
|
||||
void setMaskDenormals (bool mask = true)
|
||||
{
|
||||
m_maskDenormals.set_value (mask);
|
||||
}
|
||||
void setMaskZeroDivides (bool mask = true)
|
||||
{
|
||||
m_maskZeroDivides.set_value (mask);
|
||||
}
|
||||
void setMaskOverflows (bool mask = true)
|
||||
{
|
||||
m_maskOverflows.set_value (mask);
|
||||
}
|
||||
void setMaskUnderflows (bool mask = true)
|
||||
{
|
||||
m_maskUnderflows.set_value (mask);
|
||||
}
|
||||
//void setMaskInexacts (bool mask = true) { m_maskInexacts.set_value (mask); }
|
||||
|
||||
void setUnmaskAllExceptions (bool unmask = true)
|
||||
{
|
||||
setMaskNaNs (!unmask);
|
||||
setMaskDenormals (!unmask);
|
||||
setMaskZeroDivides (!unmask);
|
||||
setMaskOverflows (!unmask);
|
||||
setMaskUnderflows (!unmask);
|
||||
//setMaskInexacts (!unmask);
|
||||
}
|
||||
|
||||
//
|
||||
// Denormal control
|
||||
//
|
||||
|
||||
void setFlushDenormals (bool flush = true)
|
||||
{
|
||||
m_flushDenormals.set_value (flush);
|
||||
}
|
||||
|
||||
//
|
||||
// Infinity control
|
||||
//
|
||||
|
||||
void setInfinitySigned (bool is_signed = true)
|
||||
{
|
||||
m_infinitySigned.set_value (is_signed);
|
||||
}
|
||||
|
||||
//
|
||||
// Rounding control
|
||||
//
|
||||
|
||||
enum Rounding
|
||||
{
|
||||
roundChop,
|
||||
roundUp,
|
||||
roundDown,
|
||||
roundNear
|
||||
};
|
||||
|
||||
void setRounding (Rounding rounding)
|
||||
{
|
||||
m_rounding.set_value (rounding);
|
||||
}
|
||||
|
||||
//
|
||||
// Precision control
|
||||
//
|
||||
|
||||
enum Precision
|
||||
{
|
||||
bits24,
|
||||
bits53,
|
||||
bits64
|
||||
};
|
||||
|
||||
void setPrecision (Precision precision)
|
||||
{
|
||||
m_precision.set_value (precision);
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieval
|
||||
//
|
||||
|
||||
const Flag getMaskNaNs () const
|
||||
{
|
||||
return m_maskNaNs;
|
||||
}
|
||||
const Flag getMaskDenormals () const
|
||||
{
|
||||
return m_maskDenormals;
|
||||
}
|
||||
const Flag getMaskZeroDivides () const
|
||||
{
|
||||
return m_maskZeroDivides;
|
||||
}
|
||||
const Flag getMaskOverflows () const
|
||||
{
|
||||
return m_maskOverflows;
|
||||
}
|
||||
const Flag getMaskUnderflows () const
|
||||
{
|
||||
return m_maskUnderflows;
|
||||
}
|
||||
//const Flag getMaskInexacts () const { return m_maskInexacts; }
|
||||
const Flag getFlushDenormals () const
|
||||
{
|
||||
return m_flushDenormals;
|
||||
}
|
||||
const Flag getInfinitySigned () const
|
||||
{
|
||||
return m_infinitySigned;
|
||||
}
|
||||
const Enum <Rounding> getRounding () const
|
||||
{
|
||||
return m_rounding;
|
||||
}
|
||||
const Enum <Precision> getPrecision () const
|
||||
{
|
||||
return m_precision;
|
||||
}
|
||||
|
||||
Flag& getMaskNaNs ()
|
||||
{
|
||||
return m_maskNaNs;
|
||||
}
|
||||
Flag& getMaskDenormals ()
|
||||
{
|
||||
return m_maskDenormals;
|
||||
}
|
||||
Flag& getMaskZeroDivides ()
|
||||
{
|
||||
return m_maskZeroDivides;
|
||||
}
|
||||
Flag& getMaskOverflows ()
|
||||
{
|
||||
return m_maskOverflows;
|
||||
}
|
||||
Flag& getMaskUnderflows ()
|
||||
{
|
||||
return m_maskUnderflows;
|
||||
}
|
||||
//Flag& getMaskInexacts () { return m_maskInexacts; }
|
||||
Flag& getFlushDenormals ()
|
||||
{
|
||||
return m_flushDenormals;
|
||||
}
|
||||
Flag& getInfinitySigned ()
|
||||
{
|
||||
return m_infinitySigned;
|
||||
}
|
||||
Enum <Rounding>& getRounding ()
|
||||
{
|
||||
return m_rounding;
|
||||
}
|
||||
Enum <Precision>& getPrecision ()
|
||||
{
|
||||
return m_precision;
|
||||
}
|
||||
|
||||
// Clears our flags if they are not set in another object
|
||||
void clearUnsetFlagsFrom (FPUFlags const& flags);
|
||||
|
||||
// Retrieve the current flags fron the FPU
|
||||
static FPUFlags getCurrent ();
|
||||
|
||||
// Change the current FPU flags based on what is set in flags
|
||||
static void setCurrent (FPUFlags const& flags);
|
||||
|
||||
private:
|
||||
Flag m_maskNaNs;
|
||||
Flag m_maskDenormals;
|
||||
Flag m_maskZeroDivides;
|
||||
Flag m_maskOverflows;
|
||||
Flag m_maskUnderflows;
|
||||
//Flag m_maskInexacts;
|
||||
Flag m_flushDenormals;
|
||||
Flag m_infinitySigned;
|
||||
Enum <Rounding> m_rounding;
|
||||
Enum <Precision> m_precision;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
IEEE FPU flag modifications with scoped lifetime.
|
||||
|
||||
An instance of the class saves the FPU flags and updates
|
||||
|
||||
FPUFlags flags;
|
||||
flags.setUnmaskAllExceptions ();
|
||||
|
||||
{
|
||||
ScopedFPUFlags fpu (flags);
|
||||
|
||||
// Perform floating point calculations
|
||||
}
|
||||
|
||||
// FPU flags are back to what they were now
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
class ScopedFPUFlags
|
||||
{
|
||||
public:
|
||||
ScopedFPUFlags (FPUFlags const& flagsToSet)
|
||||
{
|
||||
m_savedFlags = FPUFlags::getCurrent ();
|
||||
m_savedFlags.clearUnsetFlagsFrom (flagsToSet);
|
||||
FPUFlags::setCurrent (flagsToSet);
|
||||
}
|
||||
|
||||
~ScopedFPUFlags ()
|
||||
{
|
||||
FPUFlags::setCurrent (m_savedFlags);
|
||||
}
|
||||
|
||||
private:
|
||||
FPUFlags m_savedFlags;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
91
modules/beast_core/diagnostic/beast_LeakChecked.cpp
Normal file
91
modules/beast_core/diagnostic/beast_LeakChecked.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#if BEAST_USE_LEAKCHECKED
|
||||
|
||||
/*============================================================================*/
|
||||
// Type-independent portion of Counter
|
||||
class LeakCheckedBase::CounterBase::Singleton
|
||||
{
|
||||
public:
|
||||
void push_back (CounterBase* counter)
|
||||
{
|
||||
m_list.push_front (counter);
|
||||
}
|
||||
|
||||
void detectAllLeaks ()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
CounterBase* counter = m_list.pop_front ();
|
||||
|
||||
if (!counter)
|
||||
break;
|
||||
|
||||
counter->detectLeaks ();
|
||||
}
|
||||
}
|
||||
|
||||
static Singleton& getInstance ()
|
||||
{
|
||||
static Singleton instance;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private:
|
||||
LockFreeStack <CounterBase> m_list;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
LeakCheckedBase::CounterBase::CounterBase ()
|
||||
{
|
||||
Singleton::getInstance ().push_back (this);
|
||||
}
|
||||
|
||||
void LeakCheckedBase::CounterBase::detectAllLeaks ()
|
||||
{
|
||||
Singleton::getInstance ().detectAllLeaks ();
|
||||
}
|
||||
|
||||
void LeakCheckedBase::CounterBase::detectLeaks ()
|
||||
{
|
||||
// If there's a runtime error from this line, it means there's
|
||||
// an order of destruction problem between different translation units!
|
||||
//
|
||||
this->checkPureVirtual ();
|
||||
|
||||
int const count = m_count.get ();
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
bassertfalse;
|
||||
DBG ("[LEAK] " << count << " of " << getClassName ());
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void LeakCheckedBase::detectAllLeaks ()
|
||||
{
|
||||
CounterBase::detectAllLeaks ();
|
||||
}
|
||||
|
||||
#endif
|
||||
166
modules/beast_core/diagnostic/beast_LeakChecked.h
Normal file
166
modules/beast_core/diagnostic/beast_LeakChecked.h
Normal file
@@ -0,0 +1,166 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_LEAKCHECKED_BEASTHEADER
|
||||
#define BEAST_LEAKCHECKED_BEASTHEADER
|
||||
|
||||
//
|
||||
// Derived classes are automatically leak-checked on exit
|
||||
//
|
||||
|
||||
#if BEAST_USE_LEAKCHECKED
|
||||
|
||||
class BEAST_API LeakCheckedBase
|
||||
{
|
||||
public:
|
||||
static void detectAllLeaks ();
|
||||
|
||||
protected:
|
||||
class CounterBase : public LockFreeStack <CounterBase>::Node
|
||||
{
|
||||
public:
|
||||
CounterBase ();
|
||||
|
||||
virtual ~CounterBase () { }
|
||||
|
||||
inline int increment ()
|
||||
{
|
||||
return ++m_count;
|
||||
}
|
||||
|
||||
inline int decrement ()
|
||||
{
|
||||
return --m_count;
|
||||
}
|
||||
|
||||
virtual char const* getClassName () const = 0;
|
||||
|
||||
static void detectAllLeaks ();
|
||||
|
||||
private:
|
||||
void detectLeaks ();
|
||||
|
||||
virtual void checkPureVirtual () const = 0;
|
||||
|
||||
protected:
|
||||
class Singleton;
|
||||
|
||||
Atomic <int> m_count;
|
||||
};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Detects leaks at program exit.
|
||||
|
||||
To use this, derive your class from this template using CRTP (curiously
|
||||
recurring template pattern).
|
||||
*/
|
||||
template <class Object>
|
||||
class LeakChecked : private LeakCheckedBase
|
||||
{
|
||||
protected:
|
||||
LeakChecked () noexcept
|
||||
{
|
||||
if (getLeakCheckedCounter ().increment () == 0)
|
||||
{
|
||||
DBG ("[LOGIC] " << getLeakCheckedName ());
|
||||
Throw (Error ().fail (__FILE__, __LINE__));
|
||||
}
|
||||
}
|
||||
|
||||
LeakChecked (const LeakChecked&) noexcept
|
||||
{
|
||||
if (getLeakCheckedCounter ().increment () == 0)
|
||||
{
|
||||
DBG ("[LOGIC] " << getLeakCheckedName ());
|
||||
Throw (Error ().fail (__FILE__, __LINE__));
|
||||
}
|
||||
}
|
||||
|
||||
~LeakChecked ()
|
||||
{
|
||||
if (getLeakCheckedCounter ().decrement () < 0)
|
||||
{
|
||||
DBG ("[LOGIC] " << getLeakCheckedName ());
|
||||
Throw (Error ().fail (__FILE__, __LINE__));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
class Counter : public CounterBase
|
||||
{
|
||||
public:
|
||||
Counter () noexcept
|
||||
{
|
||||
}
|
||||
|
||||
char const* getClassName () const
|
||||
{
|
||||
return getLeakCheckedName ();
|
||||
}
|
||||
|
||||
void checkPureVirtual () const { }
|
||||
};
|
||||
|
||||
private:
|
||||
/* Due to a bug in Visual Studio 10 and earlier, the string returned by
|
||||
typeid().name() will appear to leak on exit. Therefore, we should
|
||||
only call this function when there's an actual leak, or else there
|
||||
will be spurious leak notices at exit.
|
||||
*/
|
||||
static const char* getLeakCheckedName ()
|
||||
{
|
||||
return typeid (Object).name ();
|
||||
}
|
||||
|
||||
static Counter& getLeakCheckedCounter () noexcept
|
||||
{
|
||||
static Counter* volatile s_instance;
|
||||
static Static::Initializer s_initializer;
|
||||
|
||||
if (s_initializer.begin ())
|
||||
{
|
||||
static char s_storage [sizeof (Counter)];
|
||||
s_instance = new (s_storage) Counter;
|
||||
s_initializer.end ();
|
||||
}
|
||||
|
||||
return *s_instance;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class BEAST_API LeakCheckedBase
|
||||
{
|
||||
private:
|
||||
friend class PerformedAtExit;
|
||||
|
||||
static void detectAllLeaks () { }
|
||||
};
|
||||
|
||||
template <class Object>
|
||||
struct LeakChecked : LeakCheckedBase
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
91
modules/beast_core/diagnostic/beast_SafeBool.h
Normal file
91
modules/beast_core/diagnostic/beast_SafeBool.h
Normal file
@@ -0,0 +1,91 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SAFEBOOL_BEASTHEADER
|
||||
#define BEAST_SAFEBOOL_BEASTHEADER
|
||||
|
||||
/**
|
||||
Safe evaluation of class as `bool`.
|
||||
|
||||
This allows a class to be safely evaluated as a bool without the usual harmful
|
||||
side effects of the straightforward operator conversion approach. To use it,
|
||||
derive your class from SafeBool and implement `asBoolean()` as:
|
||||
|
||||
@code
|
||||
|
||||
bool asBoolean () const;
|
||||
|
||||
@endcode
|
||||
|
||||
Ideas from http://www.artima.com/cppsource/safebool.html
|
||||
|
||||
@class SafeBool
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
|
||||
class BEAST_API SafeBoolBase
|
||||
{
|
||||
private:
|
||||
void disallowed () const { }
|
||||
|
||||
public:
|
||||
void allowed () const { }
|
||||
|
||||
protected:
|
||||
typedef void (SafeBoolBase::*boolean_t) () const;
|
||||
|
||||
SafeBoolBase () { }
|
||||
SafeBoolBase (SafeBoolBase const&) { }
|
||||
SafeBoolBase& operator= (SafeBoolBase const&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
~SafeBoolBase () { }
|
||||
};
|
||||
|
||||
template <typename T = void>
|
||||
class SafeBool : public SafeBoolBase
|
||||
{
|
||||
public:
|
||||
operator boolean_t () const
|
||||
{
|
||||
return (static_cast <T const*> (this))->asBoolean ()
|
||||
? &SafeBoolBase::allowed : 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
~SafeBool () { }
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
void operator== (SafeBool <T> const& lhs, SafeBool <U> const& rhs)
|
||||
{
|
||||
lhs.disallowed ();
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void operator!= (SafeBool <T> const& lhs, SafeBool <U> const& rhs)
|
||||
{
|
||||
lhs.disallowed ();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
39
modules/beast_core/diagnostic/beast_Throw.h
Normal file
39
modules/beast_core/diagnostic/beast_Throw.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_THROW_BEASTHEADER
|
||||
#define BEAST_THROW_BEASTHEADER
|
||||
|
||||
#include "beast_Debug.h"
|
||||
|
||||
/** Throw an exception, with a debugger hook.
|
||||
|
||||
This provides an opportunity to utilize the debugger before
|
||||
the stack is unwound.
|
||||
*/
|
||||
template <class Exception>
|
||||
inline void Throw (Exception const& e)
|
||||
{
|
||||
// VFALCO TODO Replace with straight JUCE equivalent
|
||||
Debug::breakPoint ();
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
#endif
|
||||
331
modules/beast_core/functional/beast_Bind.h
Normal file
331
modules/beast_core/functional/beast_Bind.h
Normal file
@@ -0,0 +1,331 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_BIND_BEASTHEADER
|
||||
#define BEAST_BIND_BEASTHEADER
|
||||
|
||||
// VFALCO TODO Rename this file to beast_Functional.h
|
||||
|
||||
/* Brings functional support into our namespace, based on environment.
|
||||
|
||||
Notes on bind
|
||||
|
||||
Difference between boost::bind and std::bind
|
||||
http://stackoverflow.com/questions/10555566/is-there-any-difference-between-c11-stdbind-and-boostbind
|
||||
|
||||
Resolving conflict between boost::shared_ptr and std::shared_ptr
|
||||
http://stackoverflow.com/questions/4682343/how-to-resolve-conflict-between-boostshared-ptr-and-using-stdshared-ptr
|
||||
*/
|
||||
|
||||
#ifndef BEAST_BIND_PLACEHOLDERS_N
|
||||
# if BEAST_MSVC && BEAST_BIND_USES_STD
|
||||
# define BEAST_BIND_PLACEHOLDERS_N 20 // Visual Studio 2012
|
||||
# else
|
||||
# define BEAST_BIND_PLACEHOLDERS_N 8 // Seems a reasonable number
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/** Max number of arguments to bind, total.
|
||||
*/
|
||||
#if BEAST_MSVC
|
||||
# ifdef _VARIADIC_MAX
|
||||
# define BEAST_VARIADIC_MAX _VARIADIC_MAX
|
||||
# else
|
||||
# define BEAST_VARIADIC_MAX 9
|
||||
# endif
|
||||
#else
|
||||
# define BEAST_VARIADIC_MAX 9
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if BEAST_BIND_USES_STD
|
||||
|
||||
using std::ref;
|
||||
using std::cref;
|
||||
using std::bind;
|
||||
using std::function;
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 1
|
||||
using std::placeholders::_1;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 2
|
||||
using std::placeholders::_2;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 3
|
||||
using std::placeholders::_3;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 4
|
||||
using std::placeholders::_4;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 5
|
||||
using std::placeholders::_5;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 6
|
||||
using std::placeholders::_6;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 7
|
||||
using std::placeholders::_7;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 8
|
||||
using std::placeholders::_8;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 9
|
||||
using std::placeholders::_9;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 10
|
||||
using std::placeholders::_10;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 11
|
||||
using std::placeholders::_11;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 12
|
||||
using std::placeholders::_12;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 13
|
||||
using std::placeholders::_13;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 14
|
||||
using std::placeholders::_14;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 15
|
||||
using std::placeholders::_15;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 16
|
||||
using std::placeholders::_16;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 17
|
||||
using std::placeholders::_17;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 18
|
||||
using std::placeholders::_18;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 19
|
||||
using std::placeholders::_19;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 20
|
||||
using std::placeholders::_20;
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#elif BEAST_BIND_USES_TR1
|
||||
|
||||
using std::tr1::ref;
|
||||
using std::tr1::cref;
|
||||
using std::tr1::bind;
|
||||
using std::tr1::function;
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 1
|
||||
using std::tr1::placeholders::_1;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 2
|
||||
using std::tr1::placeholders::_2;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 3
|
||||
using std::tr1::placeholders::_3;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 4
|
||||
using std::tr1::placeholders::_4;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 5
|
||||
using std::tr1::placeholders::_5;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 6
|
||||
using std::tr1::placeholders::_6;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 7
|
||||
using std::tr1::placeholders::_7;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 8
|
||||
using std::tr1::placeholders::_8;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 9
|
||||
using std::tr1::placeholders::_9;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 10
|
||||
using std::tr1::placeholders::_10;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 11
|
||||
using std::tr1::placeholders::_11;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 12
|
||||
using std::tr1::placeholders::_12;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 13
|
||||
using std::tr1::placeholders::_13;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 14
|
||||
using std::tr1::placeholders::_14;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 15
|
||||
using std::tr1::placeholders::_15;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 16
|
||||
using std::tr1::placeholders::_16;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 17
|
||||
using std::tr1::placeholders::_17;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 18
|
||||
using std::tr1::placeholders::_18;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 19
|
||||
using std::tr1::placeholders::_19;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 20
|
||||
using std::tr1::placeholders::_20;
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#elif BEAST_BIND_USES_BOOST
|
||||
|
||||
using boost::ref;
|
||||
using boost::cref;
|
||||
using boost::bind;
|
||||
using boost::function;
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 1
|
||||
using boost::placeholders::_1;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 2
|
||||
using boost::placeholders::_2;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 3
|
||||
using boost::placeholders::_3;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 4
|
||||
using boost::placeholders::_4;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 5
|
||||
using boost::placeholders::_5;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 6
|
||||
using boost::placeholders::_6;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 7
|
||||
using boost::placeholders::_7;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 8
|
||||
using boost::placeholders::_8;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 9
|
||||
using boost::placeholders::_9;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 10
|
||||
using boost::placeholders::_10;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 11
|
||||
using boost::placeholders::_11;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 12
|
||||
using boost::placeholders::_12;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 13
|
||||
using boost::placeholders::_13;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 14
|
||||
using boost::placeholders::_14;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 15
|
||||
using boost::placeholders::_15;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 16
|
||||
using boost::placeholders::_16;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 17
|
||||
using boost::placeholders::_17;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 18
|
||||
using boost::placeholders::_18;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 19
|
||||
using boost::placeholders::_19;
|
||||
#endif
|
||||
|
||||
#if BEAST_BIND_PLACEHOLDERS_N >= 20
|
||||
using boost::placeholders::_20;
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#else
|
||||
|
||||
#error Unknown bind source in beast_Bind.h
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
83
modules/beast_core/memory/beast_AtomicCounter.h
Normal file
83
modules/beast_core/memory/beast_AtomicCounter.h
Normal file
@@ -0,0 +1,83 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ATOMICCOUNTER_BEASTHEADER
|
||||
#define BEAST_ATOMICCOUNTER_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A thread safe usage counter.
|
||||
|
||||
This provides a simplified interface to an atomic integer suitable for
|
||||
measuring reference or usage counts. The counter is signaled when the
|
||||
count is non zero.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
class BEAST_API AtomicCounter
|
||||
{
|
||||
public:
|
||||
/** Create a new counter.
|
||||
|
||||
@param initialValue An optional starting usage count (default is 0).
|
||||
*/
|
||||
AtomicCounter (int initialValue = 0) noexcept
|
||||
:
|
||||
m_value (initialValue)
|
||||
{
|
||||
}
|
||||
|
||||
/** Increment the usage count.
|
||||
|
||||
@return `true` if the counter became signaled.
|
||||
*/
|
||||
inline bool addref () noexcept
|
||||
{
|
||||
return (++m_value) == 1;
|
||||
}
|
||||
|
||||
/** Decrements the usage count.
|
||||
|
||||
@return `true` if the counter became non-signaled.
|
||||
*/
|
||||
inline bool release () noexcept
|
||||
{
|
||||
// Unfortunately, AllocatorWithoutTLS breaks this assert
|
||||
//bassert (isSignaled ());
|
||||
|
||||
return (--m_value) == 0;
|
||||
}
|
||||
|
||||
/** Determine if the counter is signaled.
|
||||
|
||||
Note that another thread can cause the counter to become reset after
|
||||
this function returns true.
|
||||
|
||||
@return `true` if the counter was signaled.
|
||||
*/
|
||||
inline bool isSignaled () const noexcept
|
||||
{
|
||||
return m_value.get () > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic <int> m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
102
modules/beast_core/memory/beast_AtomicFlag.h
Normal file
102
modules/beast_core/memory/beast_AtomicFlag.h
Normal file
@@ -0,0 +1,102 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ATOMICFLAG_BEASTHEADER
|
||||
#define BEAST_ATOMICFLAG_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A thread safe flag.
|
||||
|
||||
This provides a simplified interface to an atomic integer suitable for
|
||||
representing a flag. The flag is signaled when on, else it is considered
|
||||
reset.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
class BEAST_API AtomicFlag
|
||||
{
|
||||
public:
|
||||
/** Create an AtomicFlag in the reset state. */
|
||||
AtomicFlag () noexcept
|
||||
:
|
||||
m_value (0)
|
||||
{
|
||||
}
|
||||
|
||||
/** Signal the flag.
|
||||
|
||||
If two or more threads simultaneously attempt to signal the flag,
|
||||
only one will receive a true return value.
|
||||
|
||||
@return true if the flag was previously reset.
|
||||
*/
|
||||
inline bool trySignal () noexcept
|
||||
{
|
||||
return m_value.compareAndSetBool (1, 0);
|
||||
}
|
||||
|
||||
/** Signal the flag.
|
||||
|
||||
The flag must be in the reset state. Only one thread may
|
||||
call this at a time.
|
||||
*/
|
||||
inline void signal () noexcept
|
||||
{
|
||||
#if BEAST_DEBUG
|
||||
const bool success = m_value.compareAndSetBool (1, 0);
|
||||
bassert (success);
|
||||
#else
|
||||
m_value.set (1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Reset the flag.
|
||||
|
||||
The flag must be in the signaled state. Only one thread may
|
||||
call this at a time. Usually it is the thread that was successful
|
||||
in a previous call to trySignal().
|
||||
*/
|
||||
inline void reset () noexcept
|
||||
{
|
||||
#if BEAST_DEBUG
|
||||
const bool success = m_value.compareAndSetBool (0, 1);
|
||||
bassert (success);
|
||||
#else
|
||||
m_value.set (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Check if the AtomicFlag is signaled
|
||||
|
||||
The signaled status may change immediately after this call
|
||||
returns. The caller must synchronize.
|
||||
|
||||
@return true if the flag was signaled.
|
||||
*/
|
||||
inline bool isSignaled () const noexcept
|
||||
{
|
||||
return m_value.get () == 1;
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic <int> m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
133
modules/beast_core/memory/beast_AtomicPointer.h
Normal file
133
modules/beast_core/memory/beast_AtomicPointer.h
Normal file
@@ -0,0 +1,133 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ATOMICPOINTER_BEASTHEADER
|
||||
#define BEAST_ATOMICPOINTER_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A thread safe pointer.
|
||||
|
||||
This provides a simplified interface to an atomic pointer suitable
|
||||
for building containers or composite classes. Operator overloads
|
||||
allow access to the underlying pointer using natural C++ syntax.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
template <class P>
|
||||
class AtomicPointer
|
||||
{
|
||||
public:
|
||||
/** Create a pointer.
|
||||
|
||||
@param initialValue An optional starting value (default is null).
|
||||
*/
|
||||
explicit AtomicPointer (P* const initialValue = nullptr) noexcept
|
||||
:
|
||||
m_value (initialValue)
|
||||
{
|
||||
}
|
||||
|
||||
/** Retrieve the pointer value */
|
||||
inline P* get () const noexcept
|
||||
{
|
||||
return m_value.get ();
|
||||
}
|
||||
|
||||
/** Obtain a pointer to P through type conversion.
|
||||
|
||||
The caller must synchronize access to P.
|
||||
|
||||
@return A pointer to P.
|
||||
*/
|
||||
inline operator P* () const noexcept
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
|
||||
/** Dereference operator
|
||||
|
||||
The caller must synchronize access to P.
|
||||
|
||||
@return A reference to P.
|
||||
*/
|
||||
inline P& operator* () const noexcept
|
||||
{
|
||||
return &get ();
|
||||
}
|
||||
|
||||
/** Member selection
|
||||
|
||||
The caller must synchronize access to P.
|
||||
|
||||
@return A pointer to P.
|
||||
*/
|
||||
inline P* operator-> () const noexcept
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
|
||||
inline void set (P* p)
|
||||
{
|
||||
m_value.set (p);
|
||||
}
|
||||
|
||||
/** Atomically assign a new pointer
|
||||
|
||||
@param newValue The new value to assign.
|
||||
*/
|
||||
inline void operator= (P* newValue) noexcept
|
||||
{
|
||||
set (newValue);
|
||||
}
|
||||
|
||||
/** Atomically assign a new pointer and return the old value.
|
||||
|
||||
@param newValue The new value to assign.
|
||||
|
||||
@return The previous value.
|
||||
*/
|
||||
inline P* exchange (P* newValue)
|
||||
{
|
||||
return m_value.exchange (newValue);
|
||||
}
|
||||
|
||||
/** Conditionally perform an atomic assignment.
|
||||
|
||||
The current value is compared with oldValue and atomically
|
||||
set to newValue if the comparison is equal.
|
||||
|
||||
The caller is responsible for handling the ABA problem.
|
||||
|
||||
@param newValue The new value to assign.
|
||||
|
||||
@param oldValue The matching old value.
|
||||
|
||||
@return true if the assignment was performed.
|
||||
*/
|
||||
inline bool compareAndSet (P* newValue, P* oldValue)
|
||||
{
|
||||
return m_value.compareAndSetBool (newValue, oldValue);
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic <P*> m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
101
modules/beast_core/memory/beast_AtomicState.h
Normal file
101
modules/beast_core/memory/beast_AtomicState.h
Normal file
@@ -0,0 +1,101 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ATOMICSTATE_BEASTHEADER
|
||||
#define BEAST_ATOMICSTATE_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A thread safe state variable.
|
||||
|
||||
This provides a simplified interface to an integer used to control atomic
|
||||
state transitions. A state is distinguished by a single integer value.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
class BEAST_API AtomicState
|
||||
{
|
||||
public:
|
||||
/** Create a new state with an optional starting value.
|
||||
|
||||
@param initialState The initial state.
|
||||
*/
|
||||
|
||||
|
||||
explicit AtomicState (const int initialState = 0) noexcept
|
||||
:
|
||||
m_value (initialState)
|
||||
{
|
||||
}
|
||||
|
||||
/** Retrieve the current state.
|
||||
|
||||
This converts the object to an integer reflecting the current state.
|
||||
|
||||
Note that other threads may change the value immediately after this
|
||||
function returns. The caller is responsible for synchronizing.
|
||||
|
||||
@return The state at the time of the call.
|
||||
*/
|
||||
inline operator int () const
|
||||
{
|
||||
return m_value.get ();
|
||||
}
|
||||
|
||||
/** Attempt a state transition.
|
||||
|
||||
The current state is compared to `from`, and if the comparison is
|
||||
successful the state becomes `to`. The entire operation is atomic.
|
||||
|
||||
@param from The current state, for comparison.
|
||||
|
||||
@param to The desired new state.
|
||||
|
||||
@return true if the state transition succeeded.
|
||||
*/
|
||||
inline bool tryChangeState (const int from, const int to) noexcept
|
||||
{
|
||||
return m_value.compareAndSetBool (to, from);
|
||||
}
|
||||
|
||||
/** Perform a state transition.
|
||||
|
||||
This attempts to change the state and generates a diagnostic on
|
||||
failure. This routine can be used instead of tryChangeState()
|
||||
when program logic requires that the state change must succeed.
|
||||
|
||||
@param from The required current state.
|
||||
|
||||
@param to The new state.
|
||||
*/
|
||||
inline void changeState (const int from, const int to) noexcept
|
||||
{
|
||||
#if BEAST_DEBUG
|
||||
const bool success = tryChangeState (from, to);
|
||||
bassert (success);
|
||||
#else
|
||||
tryChangeState (from, to);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic <int> m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
476
modules/beast_core/memory/beast_CacheLine.h
Normal file
476
modules/beast_core/memory/beast_CacheLine.h
Normal file
@@ -0,0 +1,476 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CACHELINE_BEASTHEADER
|
||||
#define BEAST_CACHELINE_BEASTHEADER
|
||||
|
||||
// Allows turning off of all padding,
|
||||
// e.g. for memory-constrained systems or testing.
|
||||
//
|
||||
#define GLOBAL_PADDING_ENABLED 0
|
||||
|
||||
namespace CacheLine
|
||||
{
|
||||
|
||||
#if GLOBAL_PADDING_ENABLED
|
||||
|
||||
// Pads an object so that it starts on a cache line boundary.
|
||||
//
|
||||
template <typename T>
|
||||
class Aligned
|
||||
{
|
||||
public:
|
||||
~Aligned ()
|
||||
{
|
||||
ptr ()->~T ();
|
||||
}
|
||||
|
||||
Aligned ()
|
||||
{
|
||||
new (ptr ()) T;
|
||||
}
|
||||
|
||||
template <class T1>
|
||||
explicit Aligned (const T1& t1)
|
||||
{
|
||||
new (ptr ()) T (t1);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
Aligned (const T1& t1, const T2& t2)
|
||||
{
|
||||
new (ptr ()) T (t1, t2);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5, const T6& t6)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5, t6);
|
||||
}
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7 >
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5, t6, t7);
|
||||
}
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7, class T8 >
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7, const T8& t8)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
}
|
||||
|
||||
void operator= (T const& other)
|
||||
{
|
||||
*ptr () = other;
|
||||
}
|
||||
|
||||
inline T& operator* () noexcept { return *ptr (); }
|
||||
inline T* operator-> () noexcept { return ptr (); }
|
||||
inline operator T& () noexcept { return *ptr (); }
|
||||
inline operator T* () noexcept { return ptr (); }
|
||||
|
||||
inline const T& operator* () const noexcept
|
||||
{
|
||||
return *ptr ();
|
||||
}
|
||||
inline const T* operator-> () const noexcept
|
||||
{
|
||||
return ptr ();
|
||||
}
|
||||
inline operator const T& () const noexcept
|
||||
{
|
||||
return *ptr ();
|
||||
}
|
||||
inline operator const T* () const noexcept
|
||||
{
|
||||
return ptr ();
|
||||
}
|
||||
|
||||
private:
|
||||
inline T* ptr () noexcept
|
||||
{
|
||||
return (T*) ((uintptr_t (m_storage) + Memory::cacheLineAlignMask)
|
||||
& ~Memory::cacheLineAlignMask);
|
||||
/*
|
||||
return reinterpret_cast <T*> (Memory::pointerAdjustedForAlignment (
|
||||
m_storage, Memory::cacheLineBytes));
|
||||
*/
|
||||
}
|
||||
|
||||
char m_storage [ (sizeof (T) + Memory::cacheLineAlignMask)
|
||||
& ~Memory::cacheLineAlignMask];
|
||||
};
|
||||
|
||||
// Holds an object padded it to completely fill a CPU cache line.
|
||||
// The caller must ensure that this object starts at the beginning
|
||||
// of a cache line.
|
||||
//
|
||||
template <typename T>
|
||||
class Padded
|
||||
{
|
||||
public:
|
||||
Padded ()
|
||||
{ }
|
||||
|
||||
template <class T1>
|
||||
explicit Padded (const T1& t1)
|
||||
: m_t (t1) { }
|
||||
|
||||
template <class T1, class T2>
|
||||
Padded (const T1& t1, const T2& t2)
|
||||
: m_t (t1, t2) { }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3)
|
||||
: m_t (t1, t2, t3) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
: m_t (t1, t2, t3, t4) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5)
|
||||
: m_t (t1, t2, t3, t4, t5) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5, const T6& t6)
|
||||
: m_t (t1, t2, t3, t4, t5, t6) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7 >
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7, class T8 >
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7, const T8& t8)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7, t8) { }
|
||||
|
||||
void operator= (const T& other)
|
||||
{
|
||||
m_t = other;
|
||||
}
|
||||
|
||||
T& operator* () noexcept { return m_t; }
|
||||
T* operator-> () noexcept { return &m_t; }
|
||||
operator T& () noexcept { return m_t; }
|
||||
operator T* () noexcept { return &m_t; }
|
||||
|
||||
const T& operator* () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
const T* operator-> () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
operator const T& () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
operator const T* () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
char pad [Memory::cacheLineAlignBytes - sizeof (T)];
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template <typename T>
|
||||
class Aligned
|
||||
{
|
||||
public:
|
||||
Aligned ()
|
||||
{ }
|
||||
|
||||
template <class T1>
|
||||
explicit Aligned (const T1& t1)
|
||||
: m_t (t1) { }
|
||||
|
||||
template <class T1, class T2>
|
||||
Aligned (const T1& t1, const T2& t2)
|
||||
: m_t (t1, t2) { }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3)
|
||||
: m_t (t1, t2, t3) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
: m_t (t1, t2, t3, t4) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5)
|
||||
: m_t (t1, t2, t3, t4, t5) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5, const T6& t6)
|
||||
: m_t (t1, t2, t3, t4, t5, t6) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7 >
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7, class T8 >
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7, const T8& t8)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7, t8) { }
|
||||
|
||||
void operator= (const T& other)
|
||||
{
|
||||
m_t = other;
|
||||
}
|
||||
|
||||
T& operator* () noexcept { return m_t; }
|
||||
T* operator-> () noexcept { return &m_t; }
|
||||
operator T& () noexcept { return m_t; }
|
||||
operator T* () noexcept { return &m_t; }
|
||||
|
||||
const T& operator* () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
const T* operator-> () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
operator const T& () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
operator const T* () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Padded
|
||||
{
|
||||
public:
|
||||
Padded ()
|
||||
{ }
|
||||
|
||||
template <class T1>
|
||||
explicit Padded (const T1& t1)
|
||||
: m_t (t1) { }
|
||||
|
||||
template <class T1, class T2>
|
||||
Padded (const T1& t1, const T2& t2)
|
||||
: m_t (t1, t2) { }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3)
|
||||
: m_t (t1, t2, t3) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
: m_t (t1, t2, t3, t4) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5)
|
||||
: m_t (t1, t2, t3, t4, t5) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5, const T6& t6)
|
||||
: m_t (t1, t2, t3, t4, t5, t6) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7 >
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7, class T8 >
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7, const T8& t8)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7, t8) { }
|
||||
|
||||
void operator= (const T& other)
|
||||
{
|
||||
m_t = other;
|
||||
}
|
||||
|
||||
T& operator* () noexcept { return m_t; }
|
||||
T* operator-> () noexcept { return &m_t; }
|
||||
operator T& () noexcept { return m_t; }
|
||||
operator T* () noexcept { return &m_t; }
|
||||
|
||||
const T& operator* () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
const T* operator-> () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
operator const T& () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
operator const T* () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// Used to remove padding without changing code
|
||||
//
|
||||
|
||||
template <typename T>
|
||||
class Unpadded
|
||||
{
|
||||
public:
|
||||
Unpadded ()
|
||||
{ }
|
||||
|
||||
template <class T1>
|
||||
explicit Unpadded (const T1& t1)
|
||||
: m_t (t1) { }
|
||||
|
||||
template <class T1, class T2>
|
||||
Unpadded (const T1& t1, const T2& t2)
|
||||
: m_t (t1, t2) { }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3)
|
||||
: m_t (t1, t2, t3) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
: m_t (t1, t2, t3, t4) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5)
|
||||
: m_t (t1, t2, t3, t4, t5) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5, const T6& t6)
|
||||
: m_t (t1, t2, t3, t4, t5, t6) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7 >
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7, class T8 >
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7, const T8& t8)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7, t8) { }
|
||||
|
||||
void operator= (const T& other)
|
||||
{
|
||||
m_t = other;
|
||||
}
|
||||
|
||||
T& operator* ()
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
T* operator-> ()
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
operator T& ()
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
operator T* ()
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
|
||||
const T& operator* () const
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
const T* operator-> () const
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
operator const T& () const
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
operator const T* () const
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
67
modules/beast_core/memory/beast_MemoryAlignment.h
Normal file
67
modules/beast_core/memory/beast_MemoryAlignment.h
Normal file
@@ -0,0 +1,67 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_MEMORYALIGNMENT_BEASTHEADER
|
||||
#define BEAST_MEMORYALIGNMENT_BEASTHEADER
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constants
|
||||
//
|
||||
// These need to be set based on the target CPU
|
||||
//
|
||||
|
||||
const int cacheLineAlignBits = 6; // 64 bytes
|
||||
const int cacheLineAlignBytes = 1 << cacheLineAlignBits;
|
||||
const int cacheLineAlignMask = cacheLineAlignBytes - 1;
|
||||
|
||||
const int allocAlignBits = 3; // 8 bytes
|
||||
const int allocAlignBytes = 1 << allocAlignBits;
|
||||
const int allocAlignMask = allocAlignBytes - 1;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Returns the number of bytes needed to advance p to the correct alignment
|
||||
template <typename P>
|
||||
inline size_t bytesNeededForAlignment (P const* const p)
|
||||
{
|
||||
return (allocAlignBytes - (uintptr_t (p) & allocAlignMask))
|
||||
& allocAlignMask;
|
||||
}
|
||||
|
||||
// Returns the number of bytes to make "bytes" an aligned size
|
||||
inline size_t sizeAdjustedForAlignment (const size_t bytes)
|
||||
{
|
||||
return (bytes + allocAlignMask) & ~allocAlignMask;
|
||||
}
|
||||
|
||||
// Returns a pointer with alignment added.
|
||||
template <typename P>
|
||||
inline P* pointerAdjustedForAlignment (P* const p)
|
||||
{
|
||||
return reinterpret_cast <P*> (reinterpret_cast <char*> (p) +
|
||||
bytesNeededForAlignment (p));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
185
modules/beast_core/memory/beast_StaticObject.h
Normal file
185
modules/beast_core/memory/beast_StaticObject.h
Normal file
@@ -0,0 +1,185 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_STATICOBJECT_BEASTHEADER
|
||||
#define BEAST_STATICOBJECT_BEASTHEADER
|
||||
|
||||
//
|
||||
// A full suite of thread-safe objects designed for static storage duration.
|
||||
//
|
||||
// Wraps an object with a thread-safe initialization preamble so that it can
|
||||
// properly exist with static storage duration.
|
||||
//
|
||||
// Implementation notes:
|
||||
//
|
||||
// This is accomplished by omitting the constructor and relying on the C++
|
||||
// specification that plain data types with static storage duration are filled
|
||||
// with zeroes before any other initialization code executes.
|
||||
//
|
||||
// Spec: N2914=09-0104
|
||||
//
|
||||
// [3.6.2] Initialization of non-local objects
|
||||
//
|
||||
// Objects with static storage duration (3.7.1) or thread storage
|
||||
// duration (3.7.2) shall be zero-initialized (8.5) before any
|
||||
// other initialization takes place.
|
||||
//
|
||||
// Requirements:
|
||||
//
|
||||
// Object must be constructible without parameters.
|
||||
// The StaticObject must be declared with static storage duration or
|
||||
// the behavior is undefined.
|
||||
//
|
||||
// Usage example:
|
||||
//
|
||||
// Object* getInstance ()
|
||||
// {
|
||||
// static StaticObject <Object> instance;
|
||||
// return instance->getObject ();
|
||||
// }
|
||||
//
|
||||
|
||||
namespace Static
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Holds an object with static storage duration.
|
||||
// The owner determines if and when the object is constructed and destroyed.
|
||||
// Caller is responsible for synchronization.
|
||||
//
|
||||
template <class ObjectType, class Tag>
|
||||
class Storage
|
||||
{
|
||||
public:
|
||||
static inline void construct ()
|
||||
{
|
||||
new (getObjectPtr ()) ObjectType;
|
||||
}
|
||||
|
||||
static inline void destroy ()
|
||||
{
|
||||
getObjectPtr ()->~ObjectType ();
|
||||
}
|
||||
|
||||
static inline ObjectType* getObjectPtr ()
|
||||
{
|
||||
return reinterpret_cast <ObjectType*> (s_storage);
|
||||
}
|
||||
|
||||
static inline ObjectType& getObject ()
|
||||
{
|
||||
return *getObjectPtr ();
|
||||
}
|
||||
|
||||
inline ObjectType* operator-> () const
|
||||
{
|
||||
return getObjectPtr ();
|
||||
}
|
||||
|
||||
inline ObjectType& operator* () const
|
||||
{
|
||||
return getObject ();
|
||||
}
|
||||
|
||||
inline operator ObjectType* () const
|
||||
{
|
||||
return getObjectPtr ();
|
||||
}
|
||||
|
||||
// TODO: Crashes on iOS if not accessed before usage
|
||||
static char s_storage [sizeof (ObjectType)];
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
template <class ObjectType, class Tag>
|
||||
char Storage <ObjectType, Tag>::s_storage [sizeof (ObjectType)];
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Provides a thread safe flag for indicating if and when
|
||||
// initialization is required for an object with static storage duration.
|
||||
//
|
||||
class Initializer
|
||||
{
|
||||
public:
|
||||
/*
|
||||
bool inited () const
|
||||
{
|
||||
return m_state.get () == stateInitialized;
|
||||
}
|
||||
*/
|
||||
|
||||
// If the condition is not initialized, the first caller will
|
||||
// receive true, while concurrent callers get blocked until
|
||||
// initialization completes.
|
||||
//
|
||||
bool begin ()
|
||||
{
|
||||
bool shouldInitialize;
|
||||
|
||||
if (m_state.get () == stateUninitialized)
|
||||
{
|
||||
if (m_state.compareAndSetBool (stateInitializing, stateUninitialized))
|
||||
{
|
||||
shouldInitialize = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SpinDelay delay;
|
||||
|
||||
do
|
||||
{
|
||||
delay.pause ();
|
||||
}
|
||||
while (m_state.get () != stateInitialized);
|
||||
|
||||
shouldInitialize = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldInitialize = false;
|
||||
}
|
||||
|
||||
return shouldInitialize;
|
||||
}
|
||||
|
||||
// Called to signal that the initialization is complete
|
||||
//
|
||||
void end ()
|
||||
{
|
||||
m_state.set (stateInitialized);
|
||||
}
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
stateUninitialized = 0, // must be zero
|
||||
stateInitializing,
|
||||
stateInitialized
|
||||
};
|
||||
|
||||
Atomic <int> m_state;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
38
modules/beast_core/memory/beast_Uncopyable.h
Normal file
38
modules/beast_core/memory/beast_Uncopyable.h
Normal file
@@ -0,0 +1,38 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_UNCOPYABLE_BEASTHEADER
|
||||
#define BEAST_UNCOPYABLE_BEASTHEADER
|
||||
|
||||
// Prevents warnings about missing copy
|
||||
// constructors and assignment operators.
|
||||
|
||||
// Ideas based on boost
|
||||
class Uncopyable
|
||||
{
|
||||
protected:
|
||||
inline Uncopyable () { }
|
||||
inline ~Uncopyable () { }
|
||||
|
||||
private:
|
||||
Uncopyable (Uncopyable const&);
|
||||
Uncopyable const& operator= (Uncopyable const&);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -81,7 +81,7 @@ namespace SocketHelpers
|
||||
servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
servTmpAddr.sin_port = htons ((uint16) port);
|
||||
|
||||
return bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0;
|
||||
return ::bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0;
|
||||
}
|
||||
|
||||
static int readSocket (const SocketHandle handle,
|
||||
@@ -415,7 +415,7 @@ bool StreamingSocket::createListener (const int newPortNumber, const String& loc
|
||||
const int reuse = 1;
|
||||
setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse));
|
||||
|
||||
if (bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) < 0
|
||||
if (::bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) < 0
|
||||
|| listen (handle, SOMAXCONN) < 0)
|
||||
{
|
||||
close();
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
#ifndef BEAST_STANDARDHEADER_BEASTHEADER
|
||||
#define BEAST_STANDARDHEADER_BEASTHEADER
|
||||
|
||||
//==============================================================================
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Current BEAST version number.
|
||||
|
||||
See also SystemStats::getBeastVersion() for a string version.
|
||||
@@ -43,57 +44,80 @@
|
||||
*/
|
||||
#define BEAST_VERSION ((BEAST_MAJOR_VERSION << 16) + (BEAST_MINOR_VERSION << 8) + BEAST_BUILDNUMBER)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//==============================================================================
|
||||
#include "beast_TargetPlatform.h" // (sets up the various BEAST_WINDOWS, BEAST_MAC, etc flags)
|
||||
#include "beast_PlatformDefs.h"
|
||||
|
||||
//==============================================================================
|
||||
// Now we'll include some common OS headers..
|
||||
#if BEAST_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4514 4245 4100)
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4514 4245 4100)
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include <cwchar>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <new>
|
||||
#include <numeric>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <locale.h>
|
||||
#include <math.h>
|
||||
#include <memory.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if BEAST_USE_INTRINSICS
|
||||
#include <intrin.h>
|
||||
# include <intrin.h>
|
||||
#endif
|
||||
|
||||
#if BEAST_MAC || BEAST_IOS
|
||||
#include <libkern/OSAtomic.h>
|
||||
# include <libkern/OSAtomic.h>
|
||||
#endif
|
||||
|
||||
#if BEAST_LINUX
|
||||
#include <signal.h>
|
||||
|
||||
#if __INTEL_COMPILER
|
||||
#if __ia64__
|
||||
#include <ia64intrin.h>
|
||||
#else
|
||||
#include <ia32intrin.h>
|
||||
#endif
|
||||
#endif
|
||||
# include <signal.h>
|
||||
# if __INTEL_COMPILER
|
||||
# if __ia64__
|
||||
# include <ia64intrin.h>
|
||||
# else
|
||||
# include <ia32intrin.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if BEAST_MSVC && BEAST_DEBUG
|
||||
#include <crtdbg.h>
|
||||
# include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#if BEAST_MSVC
|
||||
#pragma warning (pop)
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#if BEAST_ANDROID
|
||||
@@ -107,8 +131,12 @@
|
||||
#undef max
|
||||
#undef min
|
||||
|
||||
//==============================================================================
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// DLL building settings on Windows
|
||||
//
|
||||
// VFALCO TODO Deprecate this
|
||||
//
|
||||
#if BEAST_MSVC
|
||||
#ifdef BEAST_DLL_BUILD
|
||||
#define BEAST_API __declspec (dllexport)
|
||||
@@ -124,43 +152,38 @@
|
||||
#define BEAST_API __attribute__ ((visibility("default")))
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef BEAST_API
|
||||
#define BEAST_API /**< This macro is added to all beast public class declarations. */
|
||||
#define BEAST_API /**< This macro is added to all beast public class declarations. */
|
||||
#endif
|
||||
|
||||
#if BEAST_MSVC && BEAST_DLL_BUILD
|
||||
#define BEAST_PUBLIC_IN_DLL_BUILD(declaration) public: declaration; private:
|
||||
#define BEAST_PUBLIC_IN_DLL_BUILD(decl) public: decl; private:
|
||||
#else
|
||||
#define BEAST_PUBLIC_IN_DLL_BUILD(declaration) declaration;
|
||||
#define BEAST_PUBLIC_IN_DLL_BUILD(decl) decl;
|
||||
#endif
|
||||
|
||||
/** This macro is added to all beast public function declarations. */
|
||||
#define BEAST_PUBLIC_FUNCTION BEAST_API BEAST_CALLTYPE
|
||||
|
||||
#if (! defined (BEAST_CATCH_DEPRECATED_CODE_MISUSE)) && BEAST_DEBUG && ! DOXYGEN
|
||||
/** This turns on some non-essential bits of code that should prevent old code from compiling
|
||||
in cases where method signatures have changed, etc.
|
||||
*/
|
||||
#define BEAST_CATCH_DEPRECATED_CODE_MISUSE 1
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef DOXYGEN
|
||||
#define BEAST_NAMESPACE beast // This old macro is deprecated: you should just use the beast namespace directly.
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
// Now include some common headers...
|
||||
namespace beast
|
||||
{
|
||||
extern BEAST_API bool BEAST_CALLTYPE beast_isRunningUnderDebugger();
|
||||
extern BEAST_API void BEAST_CALLTYPE logAssertion (const char* file, int line) noexcept;
|
||||
|
||||
#include "../memory/beast_Memory.h"
|
||||
#include "../maths/beast_MathsFunctions.h"
|
||||
#include "../memory/beast_ByteOrder.h"
|
||||
#include "../logging/beast_Logger.h"
|
||||
#include "../memory/beast_LeakedObjectDetector.h"
|
||||
extern BEAST_API bool BEAST_CALLTYPE beast_isRunningUnderDebugger();
|
||||
extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) noexcept;
|
||||
|
||||
// These are so common that we include them early
|
||||
|
||||
#include "../memory/beast_Uncopyable.h"
|
||||
#include "../memory/beast_Memory.h"
|
||||
#include "../maths/beast_MathsFunctions.h"
|
||||
#include "../memory/beast_ByteOrder.h"
|
||||
#include "../logging/beast_Logger.h"
|
||||
#include "../memory/beast_LeakedObjectDetector.h"
|
||||
|
||||
}
|
||||
|
||||
#endif // BEAST_STANDARDHEADER_BEASTHEADER
|
||||
#endif
|
||||
|
||||
44
modules/beast_core/threads/beast_SpinDelay.h
Normal file
44
modules/beast_core/threads/beast_SpinDelay.h
Normal file
@@ -0,0 +1,44 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SPINDELAY_BEASTHEADER
|
||||
#define BEAST_SPINDELAY_BEASTHEADER
|
||||
|
||||
//
|
||||
// Synchronization element
|
||||
//
|
||||
|
||||
class BEAST_API SpinDelay
|
||||
{
|
||||
public:
|
||||
SpinDelay () : m_count (0)
|
||||
{
|
||||
}
|
||||
|
||||
inline void pause ()
|
||||
{
|
||||
if (++m_count > 20)
|
||||
Thread::yield ();
|
||||
}
|
||||
|
||||
private:
|
||||
int m_count;
|
||||
};
|
||||
|
||||
#endif
|
||||
70
modules/beast_core/time/beast_PerformedAtExit.cpp
Normal file
70
modules/beast_core/time/beast_PerformedAtExit.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
class PerformedAtExit::ExitHook
|
||||
{
|
||||
public:
|
||||
typedef Static::Storage <LockFreeStack <PerformedAtExit>, PerformedAtExit> StackType;
|
||||
|
||||
private:
|
||||
~ExitHook ()
|
||||
{
|
||||
PerformedAtExit* object = s_list->pop_front ();
|
||||
|
||||
while (object != nullptr)
|
||||
{
|
||||
object->performAtExit ();
|
||||
|
||||
object = s_list->pop_front ();
|
||||
}
|
||||
|
||||
LeakCheckedBase::detectAllLeaks ();
|
||||
}
|
||||
|
||||
public:
|
||||
static void push_front (PerformedAtExit* object)
|
||||
{
|
||||
s_list->push_front (object);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class PerformedAtExit;
|
||||
|
||||
static StackType s_list;
|
||||
|
||||
static ExitHook s_performer;
|
||||
};
|
||||
|
||||
PerformedAtExit::ExitHook PerformedAtExit::ExitHook::s_performer;
|
||||
PerformedAtExit::ExitHook::StackType PerformedAtExit::ExitHook::s_list;
|
||||
|
||||
PerformedAtExit::PerformedAtExit ()
|
||||
{
|
||||
#if BEAST_IOS
|
||||
// Patrick Dehne:
|
||||
// PerformedAtExit::ExitHook::push_front crashes on iOS
|
||||
// if s_storage is not accessed before used
|
||||
//
|
||||
// VFALCO TODO Figure out why and fix it cleanly if needed.
|
||||
//
|
||||
char* hack = PerformedAtExit::ExitHook::s_list.s_storage;
|
||||
#endif
|
||||
|
||||
ExitHook::push_front (this);
|
||||
}
|
||||
52
modules/beast_core/time/beast_PerformedAtExit.h
Normal file
52
modules/beast_core/time/beast_PerformedAtExit.h
Normal file
@@ -0,0 +1,52 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_PERFORMEDATEXIT_BEASTHEADER
|
||||
#define BEAST_PERFORMEDATEXIT_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
Perform an action at program exit
|
||||
|
||||
To use, derive your class from PerformedAtExit, and override `performAtExit()`.
|
||||
The call will be made during the destruction of objects with static storage
|
||||
duration, before LeakChecked performs its diagnostics.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
// VFALCO TODO Make the linked list element a private type and use composition
|
||||
// instead of inheritance, so that PerformedAtExit doesn't expose
|
||||
// lock free stack node interfaces.
|
||||
//
|
||||
class BEAST_API PerformedAtExit : public LockFreeStack <PerformedAtExit>::Node
|
||||
{
|
||||
protected:
|
||||
PerformedAtExit ();
|
||||
virtual ~PerformedAtExit () { }
|
||||
|
||||
protected:
|
||||
/** Called at program exit.
|
||||
*/
|
||||
virtual void performAtExit () = 0;
|
||||
|
||||
private:
|
||||
class ExitHook;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user