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:
Vinnie Falco
2013-06-29 13:02:41 -07:00
parent 6dcf61669c
commit e7bda30506
63 changed files with 1145 additions and 1145 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View 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

View 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

View 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
//------------------------------------------------------------------------------

View 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

View 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;
}
}

View 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

View 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;
}

View 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

View 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 ();
}

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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();

View File

@@ -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

View 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

View 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);
}

View 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