Squashed 'Subtrees/leveldb/' changes from ab82e57..ae6c262

ae6c262 Merge branch 'leveldb' into ripple-fork
28fa222 Looks like a bit more delay is needed to smooth the latency.
a18f3e6 Tidy up JobQueue, add ripple_core module
18b245c Added GNU/kFreeBSD kernel name (TARGET_OS)

git-subtree-dir: Subtrees/leveldb
git-subtree-split: ae6c2620b2ef3d5c69e63dc0eda865d6a39fa061
This commit is contained in:
Vinnie Falco
2013-07-01 10:25:46 -07:00
parent fcb4c35fce
commit 4090fbf0b7
1490 changed files with 19 additions and 544886 deletions

View File

@@ -1,52 +0,0 @@
# Subtrees
These directories come from entire outside repositories
brought in using git-subtree.
About git-subtree:
https://github.com/apenwarr/git-subtree <br>
http://blogs.atlassian.com/2013/05/alternatives-to-git-submodule-git-subtree/ <br>
## LevelDB
Repository <br>
```
git@github.com:vinniefalco/LevelDB.git
```
Branch
```
ripple-fork
```
## websocket
Repository
```
git@github.com:vinniefalco/websocketpp.git
```
Branch
```
ripple-fork
```
## protobuf
Repository
```
git@github.com:vinniefalco/protobuf.git
```
Branch
```
master
```
**NOTE** Linux builds use the protobuf installed in /usr/lib. This will be
fixed in a future revision.
## SQLite
Not technically a subtree but included here because it is a direct
copy of the official SQLite distributions available here:
http://sqlite.org/download.html

View File

@@ -1,12 +0,0 @@
# Set default behaviour, in case users don't have core.autocrlf set.
* text=auto
# Github
.md text eol=lf
# Visual Studio
*.sln text eol=crlf
*.vcproj text eol=crlf
*.vcxproj text eol=crlf
*.props text eol=crlf
*.filters text eol=crlf

View File

@@ -1,26 +0,0 @@
Docs
._*
*.mode1v3
*.pbxuser
*.perspectivev3
*.user
*.ncb
*.suo
*.obj
*.ilk
*.pch
*.pdb
*.dep
*.idb
*.manifest
*.manifest.res
*.o
*.d
*.sdf
xcuserdata
contents.xcworkspacedata
.DS_Store
.svn
profile
Builds/VisualStudio2012/Debug
Builds/VisualStudio2012/Release

View File

@@ -1,59 +0,0 @@
//------------------------------------------------------------------------------
/*
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_BEASTCONFIG_HEADER
#define BEAST_BEASTCONFIG_HEADER
// beast_core flags:
#ifndef BEAST_FORCE_DEBUG
//#define BEAST_FORCE_DEBUG
#endif
#ifndef BEAST_LOG_ASSERTIONS
//#define BEAST_LOG_ASSERTIONS 1
#endif
#ifndef BEAST_CHECK_MEMORY_LEAKS
//#define BEAST_CHECK_MEMORY_LEAKS
#endif
#ifndef BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
//#define BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
#endif
// beast_basics flags
#ifndef BEAST_USE_BOOST
#define BEAST_USE_BOOST 0
#endif
#ifndef BEAST_USE_BZIP2
#define BEAST_USE_BZIP2 0
#endif
#ifndef BEAST_USE_NATIVE_SQLITE
#define BEAST_USE_NATIVE_SQLITE 1
#endif
#ifndef BEAST_USE_LEAKCHECKED
#define BEAST_USE_LEAKCHECKED BEAST_CHECK_MEMORY_LEAKS
#endif
#endif

View File

@@ -1,716 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<None Include="..\..\.gitattributes" />
<None Include="..\..\.gitignore" />
<None Include="..\..\CodingStyle.md" />
<None Include="..\..\Doxyfile" />
<None Include="..\..\modules\beast_core\beast_core.mm" />
<None Include="..\..\modules\beast_core\native\beast_mac_Files.mm">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</None>
<None Include="..\..\modules\beast_core\native\beast_mac_Network.mm">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</None>
<None Include="..\..\modules\beast_core\native\beast_mac_Strings.mm">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</None>
<None Include="..\..\modules\beast_core\native\beast_mac_SystemStats.mm">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</None>
<None Include="..\..\modules\beast_core\native\beast_mac_Threads.mm">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</None>
<None Include="..\..\modules\beast_core\native\java\BeastAppActivity.java">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</None>
<None Include="..\..\modules\beast_core\zip\zlib\README" />
<None Include="..\..\README.md" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\modules\beast_basics\beast_basics.h" />
<ClInclude Include="..\..\modules\beast_basics\containers\beast_List.h" />
<ClInclude Include="..\..\modules\beast_basics\containers\beast_LockFreeQueue.h" />
<ClInclude Include="..\..\modules\beast_basics\containers\beast_LockFreeStack.h" />
<ClInclude Include="..\..\modules\beast_basics\containers\beast_SharedTable.h" />
<ClInclude Include="..\..\modules\beast_basics\containers\beast_SortedLookupTable.h" />
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_CatchAny.h" />
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_Debug.h" />
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_Error.h" />
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_FPUFlags.h" />
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_LeakChecked.h" />
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_SafeBool.h" />
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_Throw.h" />
<ClInclude Include="..\..\modules\beast_basics\events\beast_OncePerSecond.h" />
<ClInclude Include="..\..\modules\beast_basics\events\beast_PerformedAtExit.h" />
<ClInclude Include="..\..\modules\beast_basics\functor\beast_Bind.h" />
<ClInclude Include="..\..\modules\beast_basics\functor\beast_Function.h" />
<ClInclude Include="..\..\modules\beast_basics\math\beast_Interval.h" />
<ClInclude Include="..\..\modules\beast_basics\math\beast_Math.h" />
<ClInclude Include="..\..\modules\beast_basics\math\beast_MurmurHash.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_AllocatedBy.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_AtomicCounter.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_AtomicFlag.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_AtomicPointer.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_AtomicState.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_CacheLine.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_FifoFreeStore.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_FifoFreeStoreWithoutTLS.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_FifoFreeStoreWithTLS.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_GlobalFifoFreeStore.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_GlobalPagedFreeStore.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_MemoryAlignment.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_PagedFreeStore.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_RefCountedSingleton.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_StaticObject.h" />
<ClInclude Include="..\..\modules\beast_basics\memory\beast_Uncopyable.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_CallQueue.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ConcurrentObject.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ConcurrentState.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_GlobalThreadGroup.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_InterruptibleThread.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_Listeners.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ParallelFor.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ReadWriteMutex.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_Semaphore.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_SerialFor.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_SharedObject.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_SpinDelay.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ThreadGroup.h" />
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ThreadWithCallQueue.h" />
<ClInclude Include="..\..\modules\beast_core\beast_core.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_AbstractFifo.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_Array.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_ArrayAllocationBase.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_DynamicObject.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_ElementComparator.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_HashMap.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_LinkedListPointer.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_NamedValueSet.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_OwnedArray.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_PropertySet.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_ReferenceCountedArray.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_ScopedValueSetter.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_SortedSet.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_SparseSet.h" />
<ClInclude Include="..\..\modules\beast_core\containers\beast_Variant.h" />
<ClInclude Include="..\..\modules\beast_core\files\beast_DirectoryIterator.h" />
<ClInclude Include="..\..\modules\beast_core\files\beast_File.h" />
<ClInclude Include="..\..\modules\beast_core\files\beast_FileInputStream.h" />
<ClInclude Include="..\..\modules\beast_core\files\beast_FileOutputStream.h" />
<ClInclude Include="..\..\modules\beast_core\files\beast_FileSearchPath.h" />
<ClInclude Include="..\..\modules\beast_core\files\beast_MemoryMappedFile.h" />
<ClInclude Include="..\..\modules\beast_core\files\beast_TemporaryFile.h" />
<ClInclude Include="..\..\modules\beast_core\json\beast_JSON.h" />
<ClInclude Include="..\..\modules\beast_core\logging\beast_FileLogger.h" />
<ClInclude Include="..\..\modules\beast_core\logging\beast_Logger.h" />
<ClInclude Include="..\..\modules\beast_core\maths\beast_BigInteger.h" />
<ClInclude Include="..\..\modules\beast_core\maths\beast_Expression.h" />
<ClInclude Include="..\..\modules\beast_core\maths\beast_MathsFunctions.h" />
<ClInclude Include="..\..\modules\beast_core\maths\beast_Random.h" />
<ClInclude Include="..\..\modules\beast_core\maths\beast_Range.h" />
<ClInclude Include="..\..\modules\beast_core\memory\beast_Atomic.h" />
<ClInclude Include="..\..\modules\beast_core\memory\beast_ByteOrder.h" />
<ClInclude Include="..\..\modules\beast_core\memory\beast_HeapBlock.h" />
<ClInclude Include="..\..\modules\beast_core\memory\beast_LeakedObjectDetector.h" />
<ClInclude Include="..\..\modules\beast_core\memory\beast_Memory.h" />
<ClInclude Include="..\..\modules\beast_core\memory\beast_MemoryBlock.h" />
<ClInclude Include="..\..\modules\beast_core\memory\beast_OptionalScopedPointer.h" />
<ClInclude Include="..\..\modules\beast_core\memory\beast_ReferenceCountedObject.h" />
<ClInclude Include="..\..\modules\beast_core\memory\beast_ScopedPointer.h" />
<ClInclude Include="..\..\modules\beast_core\memory\beast_Singleton.h" />
<ClInclude Include="..\..\modules\beast_core\memory\beast_WeakReference.h" />
<ClInclude Include="..\..\modules\beast_core\misc\beast_Result.h" />
<ClInclude Include="..\..\modules\beast_core\misc\beast_Uuid.h" />
<ClInclude Include="..\..\modules\beast_core\misc\beast_WindowsRegistry.h" />
<ClInclude Include="..\..\modules\beast_core\native\beast_android_JNIHelpers.h" />
<ClInclude Include="..\..\modules\beast_core\native\beast_BasicNativeHeaders.h" />
<ClInclude Include="..\..\modules\beast_core\native\beast_osx_ObjCHelpers.h" />
<ClInclude Include="..\..\modules\beast_core\native\beast_posix_SharedCode.h" />
<ClInclude Include="..\..\modules\beast_core\native\beast_win32_ComSmartPtr.h" />
<ClInclude Include="..\..\modules\beast_core\network\beast_IPAddress.h" />
<ClInclude Include="..\..\modules\beast_core\network\beast_MACAddress.h" />
<ClInclude Include="..\..\modules\beast_core\network\beast_NamedPipe.h" />
<ClInclude Include="..\..\modules\beast_core\network\beast_Socket.h" />
<ClInclude Include="..\..\modules\beast_core\network\beast_URL.h" />
<ClInclude Include="..\..\modules\beast_core\streams\beast_BufferedInputStream.h" />
<ClInclude Include="..\..\modules\beast_core\streams\beast_FileInputSource.h" />
<ClInclude Include="..\..\modules\beast_core\streams\beast_InputSource.h" />
<ClInclude Include="..\..\modules\beast_core\streams\beast_InputStream.h" />
<ClInclude Include="..\..\modules\beast_core\streams\beast_MemoryInputStream.h" />
<ClInclude Include="..\..\modules\beast_core\streams\beast_MemoryOutputStream.h" />
<ClInclude Include="..\..\modules\beast_core\streams\beast_OutputStream.h" />
<ClInclude Include="..\..\modules\beast_core\streams\beast_SubregionStream.h" />
<ClInclude Include="..\..\modules\beast_core\system\beast_PlatformDefs.h" />
<ClInclude Include="..\..\modules\beast_core\system\beast_StandardHeader.h" />
<ClInclude Include="..\..\modules\beast_core\system\beast_SystemStats.h" />
<ClInclude Include="..\..\modules\beast_core\system\beast_TargetPlatform.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_CharacterFunctions.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_CharPointer_ASCII.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_CharPointer_UTF16.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_CharPointer_UTF32.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_CharPointer_UTF8.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_Identifier.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_LocalisedStrings.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_NewLine.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_String.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_StringArray.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_StringPairArray.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_StringPool.h" />
<ClInclude Include="..\..\modules\beast_core\text\beast_TextDiff.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_ChildProcess.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_CriticalSection.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_DynamicLibrary.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_HighResolutionTimer.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_InterProcessLock.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_Process.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_ReadWriteLock.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_ScopedLock.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_ScopedReadLock.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_ScopedWriteLock.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_SpinLock.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_Thread.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_ThreadLocalValue.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_ThreadPool.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_TimeSliceThread.h" />
<ClInclude Include="..\..\modules\beast_core\threads\beast_WaitableEvent.h" />
<ClInclude Include="..\..\modules\beast_core\time\beast_PerformanceCounter.h" />
<ClInclude Include="..\..\modules\beast_core\time\beast_RelativeTime.h" />
<ClInclude Include="..\..\modules\beast_core\time\beast_Time.h" />
<ClInclude Include="..\..\modules\beast_core\unit_tests\beast_UnitTest.h" />
<ClInclude Include="..\..\modules\beast_core\xml\beast_XmlDocument.h" />
<ClInclude Include="..\..\modules\beast_core\xml\beast_XmlElement.h" />
<ClInclude Include="..\..\modules\beast_core\zip\beast_GZIPCompressorOutputStream.h" />
<ClInclude Include="..\..\modules\beast_core\zip\beast_GZIPDecompressorInputStream.h" />
<ClInclude Include="..\..\modules\beast_core\zip\beast_ZipFile.h" />
<ClInclude Include="..\..\modules\beast_core\zip\zlib\crc32.h" />
<ClInclude Include="..\..\modules\beast_core\zip\zlib\deflate.h" />
<ClInclude Include="..\..\modules\beast_core\zip\zlib\inffast.h" />
<ClInclude Include="..\..\modules\beast_core\zip\zlib\inffixed.h" />
<ClInclude Include="..\..\modules\beast_core\zip\zlib\inflate.h" />
<ClInclude Include="..\..\modules\beast_core\zip\zlib\inftrees.h" />
<ClInclude Include="..\..\modules\beast_core\zip\zlib\trees.h" />
<ClInclude Include="..\..\modules\beast_core\zip\zlib\zconf.h" />
<ClInclude Include="..\..\modules\beast_core\zip\zlib\zconf.in.h" />
<ClInclude Include="..\..\modules\beast_core\zip\zlib\zlib.h" />
<ClInclude Include="..\..\modules\beast_core\zip\zlib\zutil.h" />
<ClInclude Include="BeastConfig.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\modules\beast_basics\beast_basics.cpp" />
<ClCompile Include="..\..\modules\beast_basics\diagnostic\beast_CatchAny.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\diagnostic\beast_Debug.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\diagnostic\beast_Error.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\diagnostic\beast_FPUFlags.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\diagnostic\beast_LeakChecked.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\events\beast_OncePerSecond.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\events\beast_PerformedAtExit.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\math\beast_MurmurHash.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\memory\beast_FifoFreeStoreWithoutTLS.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\memory\beast_FifoFreeStoreWithTLS.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\memory\beast_GlobalPagedFreeStore.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\memory\beast_PagedFreeStore.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\native\beast_posix_FPUFlags.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\native\beast_posix_Threads.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\native\beast_win32_FPUFlags.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\native\beast_win32_Threads.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_CallQueue.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_ConcurrentObject.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_InterruptibleThread.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_Listeners.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_ParallelFor.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_ReadWriteMutex.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_Semaphore.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_SharedObject.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_ThreadGroup.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_ThreadWithCallQueue.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\beast_core.cpp" />
<ClCompile Include="..\..\modules\beast_core\containers\beast_AbstractFifo.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\containers\beast_DynamicObject.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\containers\beast_NamedValueSet.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\containers\beast_PropertySet.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\containers\beast_Variant.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_DirectoryIterator.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_File.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_FileInputStream.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_FileOutputStream.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_FileSearchPath.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_TemporaryFile.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\json\beast_JSON.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\logging\beast_FileLogger.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\logging\beast_Logger.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\maths\beast_BigInteger.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\maths\beast_Expression.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\maths\beast_Random.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\memory\beast_MemoryBlock.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\misc\beast_Result.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\misc\beast_Uuid.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_android_Files.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_android_Misc.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_android_Network.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_android_SystemStats.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_android_Threads.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_linux_Files.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_linux_Network.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_linux_SystemStats.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_linux_Threads.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_posix_NamedPipe.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_win32_Files.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_win32_Network.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_win32_Registry.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_win32_SystemStats.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_win32_Threads.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\network\beast_IPAddress.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\network\beast_MACAddress.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\network\beast_NamedPipe.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\network\beast_Socket.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\network\beast_URL.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_BufferedInputStream.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_FileInputSource.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_InputStream.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_MemoryInputStream.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_MemoryOutputStream.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_OutputStream.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_SubregionStream.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\system\beast_SystemStats.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_CharacterFunctions.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_Identifier.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_LocalisedStrings.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_String.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_StringArray.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_StringPairArray.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_StringPool.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_TextDiff.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_ChildProcess.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_HighResolutionTimer.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_ReadWriteLock.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_Thread.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_ThreadPool.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_TimeSliceThread.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\time\beast_PerformanceCounter.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\time\beast_RelativeTime.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\time\beast_Time.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\unit_tests\beast_UnitTest.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\xml\beast_XmlDocument.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\xml\beast_XmlElement.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\beast_GZIPCompressorOutputStream.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\beast_GZIPDecompressorInputStream.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\beast_ZipFile.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\adler32.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\compress.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\crc32.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\deflate.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\infback.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\inffast.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\inflate.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\inftrees.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\trees.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\uncompr.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\zutil.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>beast</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -1,956 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="..\..\README.md" />
<None Include="..\..\CodingStyle.md" />
<None Include="..\..\modules\beast_core\beast_core.mm">
<Filter>beast_core</Filter>
</None>
<None Include="..\..\modules\beast_core\native\beast_mac_Files.mm">
<Filter>beast_core\native</Filter>
</None>
<None Include="..\..\modules\beast_core\native\beast_mac_Network.mm">
<Filter>beast_core\native</Filter>
</None>
<None Include="..\..\modules\beast_core\native\beast_mac_Strings.mm">
<Filter>beast_core\native</Filter>
</None>
<None Include="..\..\modules\beast_core\native\beast_mac_SystemStats.mm">
<Filter>beast_core\native</Filter>
</None>
<None Include="..\..\modules\beast_core\native\beast_mac_Threads.mm">
<Filter>beast_core\native</Filter>
</None>
<None Include="..\..\modules\beast_core\zip\zlib\README">
<Filter>beast_core\zip\zlib</Filter>
</None>
<None Include="..\..\modules\beast_core\native\java\BeastAppActivity.java">
<Filter>beast_core\native\java</Filter>
</None>
<None Include="..\..\Doxyfile" />
<None Include="..\..\.gitattributes" />
<None Include="..\..\.gitignore" />
</ItemGroup>
<ItemGroup>
<Filter Include="beast_core">
<UniqueIdentifier>{6dafd8d5-2901-4b41-85b7-52f6e86baacc}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\containers">
<UniqueIdentifier>{7cc041c8-fdf4-4e98-a56a-df516c2a9aa2}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\files">
<UniqueIdentifier>{3b7d8d7e-eabc-423c-a631-2ff37bf9b9eb}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\json">
<UniqueIdentifier>{abe24d69-c1d1-49e2-98a1-1e7bf760b97a}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\logging">
<UniqueIdentifier>{0fa6b76b-305f-473c-9b94-c1028a3af3fc}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\maths">
<UniqueIdentifier>{e2339099-bb8e-4437-ae8b-d4f64ef1e3f3}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\memory">
<UniqueIdentifier>{a89aa17e-4e01-4c2d-ba7e-196e9e0b67bb}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\misc">
<UniqueIdentifier>{64a314e1-0361-428a-a294-0615d8140f58}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\native">
<UniqueIdentifier>{1d018a70-71b3-4d70-9280-02efd4f348de}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\network">
<UniqueIdentifier>{ad675f57-9303-4712-9ff2-c7f59f959e7b}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\streams">
<UniqueIdentifier>{016d839c-4860-4bc3-8f6c-e965f50c2bfa}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\system">
<UniqueIdentifier>{7fb77af6-ce16-4f53-823e-906963b42985}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\text">
<UniqueIdentifier>{4603580c-5668-4e70-bed8-77f00f03f0ff}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\threads">
<UniqueIdentifier>{3409dc7a-92b5-43aa-b678-fde9f82ced55}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\time">
<UniqueIdentifier>{d3ea4af5-ae48-4144-a2ef-a212342d72ee}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\unit_tests">
<UniqueIdentifier>{0a8a6870-87a4-4f19-bbd3-b277f94bb83e}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\xml">
<UniqueIdentifier>{a1a38659-7779-41d6-8a3c-068433c4deaf}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\zip">
<UniqueIdentifier>{df5f5a69-5919-4a24-bbce-b3f87e4903cf}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\native\java">
<UniqueIdentifier>{b0d206d9-c002-4be1-b503-4ad16aca838a}</UniqueIdentifier>
</Filter>
<Filter Include="beast_core\zip\zlib">
<UniqueIdentifier>{31038502-9139-4c19-bd67-8f90f08a70ca}</UniqueIdentifier>
</Filter>
<Filter Include="beast_basics">
<UniqueIdentifier>{e3a8f3eb-7f0f-4b81-b978-0dd0823f583b}</UniqueIdentifier>
</Filter>
<Filter Include="beast_basics\containers">
<UniqueIdentifier>{3e9389c0-c8f0-4657-ab11-cbbea889d3be}</UniqueIdentifier>
</Filter>
<Filter Include="beast_basics\diagnostic">
<UniqueIdentifier>{ba11b980-76dd-49a4-b2c7-878e9f08f8ce}</UniqueIdentifier>
</Filter>
<Filter Include="beast_basics\events">
<UniqueIdentifier>{b8caa85d-f224-4e3a-966f-a19b65023869}</UniqueIdentifier>
</Filter>
<Filter Include="beast_basics\functor">
<UniqueIdentifier>{bb0bef46-51a6-4c26-8354-4df753c3bace}</UniqueIdentifier>
</Filter>
<Filter Include="beast_basics\math">
<UniqueIdentifier>{1d53386e-0732-4213-b45d-026ff3d14042}</UniqueIdentifier>
</Filter>
<Filter Include="beast_basics\memory">
<UniqueIdentifier>{9e850052-6ab7-4a65-911d-adfde81ceb5f}</UniqueIdentifier>
</Filter>
<Filter Include="beast_basics\native">
<UniqueIdentifier>{811c5374-8959-4df9-aba9-a7e27b85046e}</UniqueIdentifier>
</Filter>
<Filter Include="beast_basics\threads">
<UniqueIdentifier>{f58dddf7-fe43-49a2-8e57-91feba586119}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\modules\beast_core\beast_core.h">
<Filter>beast_core</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_AbstractFifo.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_Array.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_ArrayAllocationBase.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_DynamicObject.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_ElementComparator.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_HashMap.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_LinkedListPointer.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_NamedValueSet.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_OwnedArray.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_PropertySet.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_ReferenceCountedArray.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_ScopedValueSetter.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_SortedSet.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_SparseSet.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\containers\beast_Variant.h">
<Filter>beast_core\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\files\beast_DirectoryIterator.h">
<Filter>beast_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\files\beast_File.h">
<Filter>beast_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\files\beast_FileInputStream.h">
<Filter>beast_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\files\beast_FileOutputStream.h">
<Filter>beast_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\files\beast_FileSearchPath.h">
<Filter>beast_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\files\beast_MemoryMappedFile.h">
<Filter>beast_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\files\beast_TemporaryFile.h">
<Filter>beast_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\json\beast_JSON.h">
<Filter>beast_core\json</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\logging\beast_FileLogger.h">
<Filter>beast_core\logging</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\logging\beast_Logger.h">
<Filter>beast_core\logging</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\maths\beast_BigInteger.h">
<Filter>beast_core\maths</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\maths\beast_Expression.h">
<Filter>beast_core\maths</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\maths\beast_MathsFunctions.h">
<Filter>beast_core\maths</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\maths\beast_Random.h">
<Filter>beast_core\maths</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\maths\beast_Range.h">
<Filter>beast_core\maths</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\beast_Atomic.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\beast_ByteOrder.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\beast_HeapBlock.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\beast_LeakedObjectDetector.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\beast_Memory.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\beast_MemoryBlock.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\beast_OptionalScopedPointer.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\beast_ReferenceCountedObject.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\beast_ScopedPointer.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\beast_Singleton.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\beast_WeakReference.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\misc\beast_Result.h">
<Filter>beast_core\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\misc\beast_Uuid.h">
<Filter>beast_core\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\misc\beast_WindowsRegistry.h">
<Filter>beast_core\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\native\beast_android_JNIHelpers.h">
<Filter>beast_core\native</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\native\beast_BasicNativeHeaders.h">
<Filter>beast_core\native</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\native\beast_osx_ObjCHelpers.h">
<Filter>beast_core\native</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\native\beast_posix_SharedCode.h">
<Filter>beast_core\native</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\native\beast_win32_ComSmartPtr.h">
<Filter>beast_core\native</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\network\beast_IPAddress.h">
<Filter>beast_core\network</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\network\beast_MACAddress.h">
<Filter>beast_core\network</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\network\beast_NamedPipe.h">
<Filter>beast_core\network</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\network\beast_Socket.h">
<Filter>beast_core\network</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\network\beast_URL.h">
<Filter>beast_core\network</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\streams\beast_BufferedInputStream.h">
<Filter>beast_core\streams</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\streams\beast_FileInputSource.h">
<Filter>beast_core\streams</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\streams\beast_InputSource.h">
<Filter>beast_core\streams</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\streams\beast_InputStream.h">
<Filter>beast_core\streams</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\streams\beast_MemoryInputStream.h">
<Filter>beast_core\streams</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\streams\beast_MemoryOutputStream.h">
<Filter>beast_core\streams</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\streams\beast_OutputStream.h">
<Filter>beast_core\streams</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\streams\beast_SubregionStream.h">
<Filter>beast_core\streams</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\system\beast_PlatformDefs.h">
<Filter>beast_core\system</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\system\beast_StandardHeader.h">
<Filter>beast_core\system</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\system\beast_SystemStats.h">
<Filter>beast_core\system</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\system\beast_TargetPlatform.h">
<Filter>beast_core\system</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_CharacterFunctions.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_CharPointer_ASCII.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_CharPointer_UTF8.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_CharPointer_UTF16.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_CharPointer_UTF32.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_Identifier.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_LocalisedStrings.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_NewLine.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_String.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_StringArray.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_StringPairArray.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_StringPool.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\text\beast_TextDiff.h">
<Filter>beast_core\text</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_ChildProcess.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_CriticalSection.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_DynamicLibrary.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_HighResolutionTimer.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_InterProcessLock.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_Process.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_ReadWriteLock.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_ScopedLock.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_ScopedReadLock.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_ScopedWriteLock.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_SpinLock.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_Thread.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_ThreadLocalValue.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_ThreadPool.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_TimeSliceThread.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\beast_WaitableEvent.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\time\beast_PerformanceCounter.h">
<Filter>beast_core\time</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\time\beast_RelativeTime.h">
<Filter>beast_core\time</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\time\beast_Time.h">
<Filter>beast_core\time</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\unit_tests\beast_UnitTest.h">
<Filter>beast_core\unit_tests</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\xml\beast_XmlDocument.h">
<Filter>beast_core\xml</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\xml\beast_XmlElement.h">
<Filter>beast_core\xml</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\beast_GZIPCompressorOutputStream.h">
<Filter>beast_core\zip</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\beast_GZIPDecompressorInputStream.h">
<Filter>beast_core\zip</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\beast_ZipFile.h">
<Filter>beast_core\zip</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\zlib\crc32.h">
<Filter>beast_core\zip\zlib</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\zlib\deflate.h">
<Filter>beast_core\zip\zlib</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\zlib\inffast.h">
<Filter>beast_core\zip\zlib</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\zlib\inffixed.h">
<Filter>beast_core\zip\zlib</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\zlib\inflate.h">
<Filter>beast_core\zip\zlib</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\zlib\inftrees.h">
<Filter>beast_core\zip\zlib</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\zlib\trees.h">
<Filter>beast_core\zip\zlib</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\zlib\zconf.h">
<Filter>beast_core\zip\zlib</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\zlib\zconf.in.h">
<Filter>beast_core\zip\zlib</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\zlib\zlib.h">
<Filter>beast_core\zip\zlib</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\zip\zlib\zutil.h">
<Filter>beast_core\zip\zlib</Filter>
</ClInclude>
<ClInclude Include="BeastConfig.h" />
<ClInclude Include="..\..\modules\beast_basics\beast_basics.h">
<Filter>beast_basics</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\containers\beast_List.h">
<Filter>beast_basics\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\containers\beast_LockFreeQueue.h">
<Filter>beast_basics\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\containers\beast_LockFreeStack.h">
<Filter>beast_basics\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\containers\beast_SharedTable.h">
<Filter>beast_basics\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\containers\beast_SortedLookupTable.h">
<Filter>beast_basics\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_CatchAny.h">
<Filter>beast_basics\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_Debug.h">
<Filter>beast_basics\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_Error.h">
<Filter>beast_basics\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_FPUFlags.h">
<Filter>beast_basics\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_LeakChecked.h">
<Filter>beast_basics\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_SafeBool.h">
<Filter>beast_basics\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\diagnostic\beast_Throw.h">
<Filter>beast_basics\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\events\beast_OncePerSecond.h">
<Filter>beast_basics\events</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\events\beast_PerformedAtExit.h">
<Filter>beast_basics\events</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\functor\beast_Bind.h">
<Filter>beast_basics\functor</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\functor\beast_Function.h">
<Filter>beast_basics\functor</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\math\beast_Interval.h">
<Filter>beast_basics\math</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\math\beast_Math.h">
<Filter>beast_basics\math</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\math\beast_MurmurHash.h">
<Filter>beast_basics\math</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_AllocatedBy.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_AtomicCounter.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_AtomicFlag.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_AtomicPointer.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_AtomicState.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_CacheLine.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_FifoFreeStore.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_FifoFreeStoreWithoutTLS.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_FifoFreeStoreWithTLS.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_GlobalFifoFreeStore.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_GlobalPagedFreeStore.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_MemoryAlignment.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_PagedFreeStore.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_RefCountedSingleton.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_StaticObject.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\memory\beast_Uncopyable.h">
<Filter>beast_basics\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_CallQueue.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ConcurrentObject.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ConcurrentState.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_GlobalThreadGroup.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_InterruptibleThread.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_Listeners.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ParallelFor.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ReadWriteMutex.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_Semaphore.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_SerialFor.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_SharedObject.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_SpinDelay.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ThreadGroup.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_basics\threads\beast_ThreadWithCallQueue.h">
<Filter>beast_basics\threads</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\modules\beast_core\beast_core.cpp">
<Filter>beast_core</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\containers\beast_AbstractFifo.cpp">
<Filter>beast_core\containers</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\containers\beast_DynamicObject.cpp">
<Filter>beast_core\containers</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\containers\beast_NamedValueSet.cpp">
<Filter>beast_core\containers</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\containers\beast_PropertySet.cpp">
<Filter>beast_core\containers</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\containers\beast_Variant.cpp">
<Filter>beast_core\containers</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_DirectoryIterator.cpp">
<Filter>beast_core\files</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_File.cpp">
<Filter>beast_core\files</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_FileInputStream.cpp">
<Filter>beast_core\files</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_FileOutputStream.cpp">
<Filter>beast_core\files</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_FileSearchPath.cpp">
<Filter>beast_core\files</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\files\beast_TemporaryFile.cpp">
<Filter>beast_core\files</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\json\beast_JSON.cpp">
<Filter>beast_core\json</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\logging\beast_FileLogger.cpp">
<Filter>beast_core\logging</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\logging\beast_Logger.cpp">
<Filter>beast_core\logging</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\maths\beast_BigInteger.cpp">
<Filter>beast_core\maths</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\maths\beast_Expression.cpp">
<Filter>beast_core\maths</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\maths\beast_Random.cpp">
<Filter>beast_core\maths</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\memory\beast_MemoryBlock.cpp">
<Filter>beast_core\memory</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\misc\beast_Result.cpp">
<Filter>beast_core\misc</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\misc\beast_Uuid.cpp">
<Filter>beast_core\misc</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_android_Files.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_android_Misc.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_android_Network.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_android_SystemStats.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_android_Threads.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_linux_Files.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_linux_Network.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_linux_SystemStats.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_linux_Threads.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_posix_NamedPipe.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_win32_Files.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_win32_Network.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_win32_Registry.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_win32_SystemStats.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\native\beast_win32_Threads.cpp">
<Filter>beast_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\network\beast_IPAddress.cpp">
<Filter>beast_core\network</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\network\beast_MACAddress.cpp">
<Filter>beast_core\network</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\network\beast_NamedPipe.cpp">
<Filter>beast_core\network</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\network\beast_Socket.cpp">
<Filter>beast_core\network</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\network\beast_URL.cpp">
<Filter>beast_core\network</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_BufferedInputStream.cpp">
<Filter>beast_core\streams</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_FileInputSource.cpp">
<Filter>beast_core\streams</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_InputStream.cpp">
<Filter>beast_core\streams</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_MemoryInputStream.cpp">
<Filter>beast_core\streams</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_MemoryOutputStream.cpp">
<Filter>beast_core\streams</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_OutputStream.cpp">
<Filter>beast_core\streams</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\streams\beast_SubregionStream.cpp">
<Filter>beast_core\streams</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\system\beast_SystemStats.cpp">
<Filter>beast_core\system</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_CharacterFunctions.cpp">
<Filter>beast_core\text</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_Identifier.cpp">
<Filter>beast_core\text</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_LocalisedStrings.cpp">
<Filter>beast_core\text</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_String.cpp">
<Filter>beast_core\text</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_StringArray.cpp">
<Filter>beast_core\text</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_StringPairArray.cpp">
<Filter>beast_core\text</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_StringPool.cpp">
<Filter>beast_core\text</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\text\beast_TextDiff.cpp">
<Filter>beast_core\text</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_ChildProcess.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_HighResolutionTimer.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_ReadWriteLock.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_Thread.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_ThreadPool.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\beast_TimeSliceThread.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\time\beast_PerformanceCounter.cpp">
<Filter>beast_core\time</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\time\beast_RelativeTime.cpp">
<Filter>beast_core\time</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\time\beast_Time.cpp">
<Filter>beast_core\time</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\unit_tests\beast_UnitTest.cpp">
<Filter>beast_core\unit_tests</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\xml\beast_XmlDocument.cpp">
<Filter>beast_core\xml</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\xml\beast_XmlElement.cpp">
<Filter>beast_core\xml</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\beast_GZIPCompressorOutputStream.cpp">
<Filter>beast_core\zip</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\beast_GZIPDecompressorInputStream.cpp">
<Filter>beast_core\zip</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\beast_ZipFile.cpp">
<Filter>beast_core\zip</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\adler32.c">
<Filter>beast_core\zip\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\compress.c">
<Filter>beast_core\zip\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\crc32.c">
<Filter>beast_core\zip\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\deflate.c">
<Filter>beast_core\zip\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\infback.c">
<Filter>beast_core\zip\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\inffast.c">
<Filter>beast_core\zip\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\inflate.c">
<Filter>beast_core\zip\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\inftrees.c">
<Filter>beast_core\zip\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\trees.c">
<Filter>beast_core\zip\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\uncompr.c">
<Filter>beast_core\zip\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\zip\zlib\zutil.c">
<Filter>beast_core\zip\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\beast_basics.cpp">
<Filter>beast_basics</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\diagnostic\beast_CatchAny.cpp">
<Filter>beast_basics\diagnostic</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\diagnostic\beast_Debug.cpp">
<Filter>beast_basics\diagnostic</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\diagnostic\beast_Error.cpp">
<Filter>beast_basics\diagnostic</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\diagnostic\beast_FPUFlags.cpp">
<Filter>beast_basics\diagnostic</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\diagnostic\beast_LeakChecked.cpp">
<Filter>beast_basics\diagnostic</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\events\beast_OncePerSecond.cpp">
<Filter>beast_basics\events</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\events\beast_PerformedAtExit.cpp">
<Filter>beast_basics\events</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\math\beast_MurmurHash.cpp">
<Filter>beast_basics\math</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\memory\beast_FifoFreeStoreWithoutTLS.cpp">
<Filter>beast_basics\memory</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\memory\beast_FifoFreeStoreWithTLS.cpp">
<Filter>beast_basics\memory</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\memory\beast_GlobalPagedFreeStore.cpp">
<Filter>beast_basics\memory</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\memory\beast_PagedFreeStore.cpp">
<Filter>beast_basics\memory</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\native\beast_posix_FPUFlags.cpp">
<Filter>beast_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\native\beast_posix_Threads.cpp">
<Filter>beast_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\native\beast_win32_FPUFlags.cpp">
<Filter>beast_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\native\beast_win32_Threads.cpp">
<Filter>beast_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_CallQueue.cpp">
<Filter>beast_basics\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_ConcurrentObject.cpp">
<Filter>beast_basics\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_InterruptibleThread.cpp">
<Filter>beast_basics\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_Listeners.cpp">
<Filter>beast_basics\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_ParallelFor.cpp">
<Filter>beast_basics\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_ReadWriteMutex.cpp">
<Filter>beast_basics\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_Semaphore.cpp">
<Filter>beast_basics\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_SharedObject.cpp">
<Filter>beast_basics\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_ThreadGroup.cpp">
<Filter>beast_basics\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\threads\beast_ThreadWithCallQueue.cpp">
<Filter>beast_basics\threads</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -1,217 +0,0 @@
--------------------------------------------------------------------------------
# Coding Standards
Coding standards used here are extreme strict and consistent. The style
evolved gradually over the years, incorporating generally acknowledged
best-practice C++ advice, experience, and personal preference.
## Don't Repeat Yourself!
The [Don't Repeat Yourself][1] principle summarises the essence of what it
means to write good code, in all languages, at all levels.
## Formatting
The goal of source code formatting should always be to make things as easy to
read as possible. White space is used to guide the eye so that details are not
overlooked. Blank lines are used to separate code into "paragraphs."
* No tab characters please.
* Tab stops are set to 4 spaces.
* Braces are indented in the [Allman style][2].
* Always place a space before and after all binary operators,
especially assignments (`operator=`).
* The `!` operator should always be followed by a space.
* The `~` operator should be preceded by a space, but not followed by one.
* The `++` and `--` operators should have no spaces between the operator and
the operand.
* A space never appears before a comma, and always appears after a comma.
* Always place a space before an opening parenthesis. One exception is if
the parentheses are empty.
* Don't put spaces after a parenthesis. A typical member function call might
look like this: `foobar (1, 2, 3);`
* In general, leave a blank line before an `if` statement.
* In general, leave a blank line after a closing brace `}`.
* Do not place code or comments on the same line as any opening or
closing brace.
* Do not write `if` statements all-on-one-line. The exception to this is when
you've got a sequence of similar `if` statements, and are aligning them all
vertically to highlight their similarities.
* In an `if-else` statement, if you surround one half of the statement with
braces, you also need to put braces around the other half, to match.
* When writing a pointer type, use this spacing: `SomeObject* myObject`.
Technically, a more correct spacing would be `SomeObject *myObject`, but
it makes more sense for the asterisk to be grouped with the type name,
since being a pointer is part of the type, not the variable name. The only
time that this can lead to any problems is when you're declaring multiple
pointers of the same type in the same statement - which leads on to the next
rule:
* When declaring multiple pointers, never do so in a single statement, e.g.
`SomeObject* p1, *p2;` - instead, always split them out onto separate lines
and write the type name again, to make it quite clear what's going on, and
avoid the danger of missing out any vital asterisks.
* The previous point also applies to references, so always put the `&` next to
the type rather than the variable, e.g. `void foo (Thing const& thing)`. And
don't put a space on both sides of the `*` or `&` - always put a space after
it, but never before it.
* The word `const` should be placed to the right of the thing that it modifies,
for consistency. For example `int const` refers to an int which is const.
`int const*` is a pointer to an int which is const. `int *const` is a const
pointer to an int.
* Always place a space in between the template angle brackets and the type
name. Template code is already hard enough to read!
## Naming conventions
* Member variables and method names are written with camel-case, and never
begin with a capital letter.
* Class names are also written in camel-case, but always begin with a capital
letter.
* For global variables... well, you shouldn't have any, so it doesn't matter.
* Class data members begin with `m_`, static data members begin with `s_`.
Global variables begin with `g_`. This is so the scope of the corresponding
declaration can be easily determined.
* Avoid underscores in your names, especially leading or trailing underscores.
In particular, leading underscores should be avoided, as these are often used
in standard library code, so to use them in your own code looks quite jarring.
* If you really have to write a macro for some reason, then make it all caps,
with underscores to separate the words. And obviously make sure that its name
is unlikely to clash with symbols used in other libraries or 3rd party code.
## Types, const-correctness
* If a method can (and should!) be const, make it const!
* If a method definitely doesn't throw an exception (be careful!), mark it as
`noexcept`
* When returning a temporary object, e.g. a String, the returned object should
be non-const, so that if the class has a C++11 move operator, it can be used.
* If a local variable can be const, then make it const!
* Remember that pointers can be const as well as primitives; For example, if
you have a `char*` whose contents are going to be altered, you may still be
able to make the pointer itself const, e.g. `char* const foobar = getFoobar();`.
* Do not declare all your local variables at the top of a function or method
(i.e. in the old-fashioned C-style). Declare them at the last possible moment,
and give them as small a scope as possible.
* Object parameters should be passed as `const&` wherever possible. Only
pass a parameter as a copy-by-value object if you really need to mutate
a local copy inside the method, and if making a local copy inside the method
would be difficult.
* Use portable `for()` loop variable scoping (i.e. do not have multiple for
loops in the same scope that each re-declare the same variable name, as
this fails on older compilers)
* When you're testing a pointer to see if it's null, never write
`if (myPointer)`. Always avoid that implicit cast-to-bool by writing it more
fully: `if (myPointer != nullptr)`. And likewise, never ever write
`if (! myPointer)`, instead always write `if (myPointer == nullptr)`.
It is more readable that way.
* Avoid C-style casts except when converting between primitive numeric types.
Some people would say "avoid C-style casts altogether", but `static_cast` is
a bit unreadable when you just want to cast an `int` to a `float`. But
whenever a pointer is involved, or a non-primitive object, always use
`static_cast`. And when you're reinterpreting data, always use
`reinterpret_cast`.
* Until C++ gets a universal 64-bit primitive type (part of the C++11
standard), it's best to stick to the `int64` and `uint64` typedefs.
## Object lifetime and ownership
* Absolutely do NOT use `delete`, `deleteAndZero`, etc. There are very very few
situations where you can't use a `ScopedPointer` or some other automatic
lifetime management class.
* Do not use `new` unless there's no alternative. Whenever you type `new`, always
treat it as a failure to find a better solution. If a local variable can be
allocated on the stack rather than the heap, then always do so.
* Do not ever use `new` or `malloc` to allocate a C++ array. Always use a
`HeapBlock` instead.
* And just to make it doubly clear: Never use `malloc` or `calloc`.
* If a parent object needs to create and own some kind of child object, always
use composition as your first choice. If that's not possible (e.g. if the
child needs a pointer to the parent for its constructor), then use a
`ScopedPointer`.
* If possible, pass an object as a reference rather than a pointer. If possible,
make it a `const` reference.
* Obviously avoid static and global values. Sometimes there's no alternative,
but if there is an alternative, then use it, no matter how much effort it
involves.
* If allocating a local POD structure (e.g. an operating-system structure in
native code), and you need to initialise it with zeros, use the `= { 0 };`
syntax as your first choice for doing this. If for some reason that's not
appropriate, use the `zerostruct()` function, or in case that isn't suitable,
use `zeromem()`. Don't use `memset()`.
## Classes
* Declare a class's public section first, and put its constructors and
destructor first. Any protected items come next, and then private ones.
* Use the most restrictive access-specifier possible for each member. Prefer
`private` over `protected`, and `protected` over `public`. Don't expose
things unnecessarily.
* Preferred positioning for any inherited classes is to put them to the right
of the class name, vertically aligned, e.g.:
class Thing : public Foo,
private Bar
{
}
* Put a class's member variables (which should almost always be private, of course),
after all the public and protected method declarations.
* Any private methods can go towards the end of the class, after the member
variables.
* If your class does not have copy-by-value semantics, derive the class from
`Uncopyable`.
* If your class is likely to be leaked, then derive your class from
`LeakChecked<>`.
* Constructors that take a single parameter should be default be marked
`explicit`. Obviously there are cases where you do want implicit conversion,
but always think about it carefully before writing a non-explicit constructor.
* Do not use `NULL`, `null`, or 0 for a null-pointer. And especially never use
'0L', which is particulary burdensome. Use `nullptr` instead - this is the
C++2011 standard, so get used to it. There's a fallback definition for `nullptr`
in Beast, so it's always possible to use it even if your compiler isn't yet
C++2011 compliant.
* All the C++ 'guru' books and articles are full of excellent and detailed advice
on when it's best to use inheritance vs composition. If you're not already
familiar with the received wisdom in these matters, then do some reading!
## Miscellaneous
* `goto` statements should not be used at all, even if the alternative is
more verbose code. The only exception is when implementing an algorithm in
a function as a state machine.
* Don't use macros! OK, obviously there are many situations where they're the
right tool for the job, but treat them as a last resort. Certainly don't ever
use a macro just to hold a constant value or to perform any kind of function
that could have been done as a real inline function. And it goes without saying
that you should give them names which aren't going to clash with other code.
And `#undef` them after you've used them, if possible.
* When using the `++` or `--` operators, never use post-increment if
pre-increment could be used instead. Although it doesn't matter for
primitive types, it's good practice to pre-increment since this can be
much more efficient for more complex objects. In particular, if you're
writing a for loop, always use pre-increment,
e.g. `for (int = 0; i < 10; ++i)`
* Never put an "else" statement after a "return"! This is well-explained in the
LLVM coding standards...and a couple of other very good pieces of advice from
the LLVM standards are in there as well.
* When getting a possibly-null pointer and using it only if it's non-null, limit
the scope of the pointer as much as possible - e.g. Do NOT do this:
Foo* f = getFoo ();
if (f != nullptr)
f->doSomething ();
// other code
f->doSomething (); // oops! f may be null!
..instead, prefer to write it like this, which reduces the scope of the
pointer, making it impossible to write code that accidentally uses a null
pointer:
if (Foo* f = getFoo ())
f->doSomethingElse ();
// f is out-of-scope here, so impossible to use it if it's null
(This also results in smaller, cleaner code)
[1]: http://en.wikipedia.org/wiki/Don%27t_repeat_yourself
[2]: http://en.wikipedia.org/wiki/Indent_style#Allman_style

View File

@@ -1,303 +0,0 @@
# Doxyfile 1.8.3.1
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "Beast"
PROJECT_NUMBER =
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = Docs
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 4
ALIASES =
TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
SYMBOL_CACHE_SIZE = 0
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = modules
INPUT_ENCODING = UTF-8
FILE_PATTERNS =
RECURSIVE = YES
EXCLUDE = modules/beast_core/beast_core.h \
modules/beast_core/beast_core.cpp \
modules/beast_basics/beast_basics.h \
modules/beast_basics/beast_basics.cpp \
modules/beast_basics/native \
modules/beast_basics/zip/zlib
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = .
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
MATHJAX_EXTENSIONS =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
MSCGEN_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES

View File

@@ -1,14 +0,0 @@
# Beast: An amazing cross platform library
Contains cross platform objects to do a variety of useful things.
No external dependencies, no complicated build steps.
Things people need for building peer to peer, concurrent, cryptographic systems.
The hope is that this will replace the use of boost and other cumbersome jalopies.
## JUCE
Beast is based on the beast_core module which is provided under the ISC
license. More information about JUCE is available at
http://www.juce.com

View File

@@ -1,89 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
/** Add this to get the @ref beast_basics module.
@file beast_basics.cpp
@ingroup beast_basics
*/
#include "BeastConfig.h"
#include "beast_basics.h"
#if BEAST_MSVC && _DEBUG
#include <crtdbg.h>
#endif
#if BEAST_MSVC
#pragma warning (push)
#pragma warning (disable: 4100) // unreferenced formal parmaeter
#pragma warning (disable: 4355) // 'this' used in base member
#endif
namespace beast
{
#include "diagnostic/beast_CatchAny.cpp"
#include "diagnostic/beast_Debug.cpp"
#include "diagnostic/beast_Error.cpp"
#include "diagnostic/beast_FPUFlags.cpp"
#include "diagnostic/beast_LeakChecked.cpp"
#include "events/beast_OncePerSecond.cpp"
#include "events/beast_PerformedAtExit.cpp"
#include "math/beast_MurmurHash.cpp"
#include "threads/beast_InterruptibleThread.cpp"
#include "threads/beast_Semaphore.cpp"
#if BEAST_WINDOWS
#include "native/beast_win32_FPUFlags.cpp"
#include "native/beast_win32_Threads.cpp"
#else
#include "native/beast_posix_FPUFlags.cpp"
#include "native/beast_posix_Threads.cpp"
#endif
#if BEAST_USE_BOOST
#include "memory/beast_FifoFreeStoreWithTLS.cpp"
#else
#include "memory/beast_FifoFreeStoreWithoutTLS.cpp"
#endif
#include "memory/beast_GlobalPagedFreeStore.cpp"
#include "memory/beast_PagedFreeStore.cpp"
#include "threads/beast_CallQueue.cpp"
#include "threads/beast_ConcurrentObject.cpp"
#include "threads/beast_Listeners.cpp"
#include "threads/beast_ManualCallQueue.cpp"
#include "threads/beast_ParallelFor.cpp"
#include "threads/beast_ReadWriteMutex.cpp"
#include "threads/beast_SharedObject.cpp"
#include "threads/beast_ThreadGroup.cpp"
#include "threads/beast_ThreadWithCallQueue.cpp"
}
#if BEAST_MSVC
#pragma warning (pop)
#endif

View File

@@ -1,470 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
/** Include this to get the @ref beast_basics module.
@file beast_basics.h
@ingroup beast_basics
*/
#ifndef BEAST_BASICS_BEASTHEADER
#define BEAST_BASICS_BEASTHEADER
//==============================================================================
/**
@mainpage Beast: A multipurpose library using parts of JUCE.
### Version 1.1
Copyright (C) 2008 by Vinnie Falco \<vinnie.falco@gmail.com\> ([e-mail][0])
Beast is a source code collection of individual modules containing
functionality for a variety of applications, with an emphasis on building
concurrent systems. Beast requires [JUCE][3] (Jules' Utility Class
Extensions), available from [Raw Material Software][4]. JUCE is available
under both the [GNU General Public License][5] and a [commercial license][6].
Other than JUCE, Beast has no external dependencies.
Beast is hosted on Github at [https://github.com/vinniefalco/Beast][1]
The online documentation is at [http://vinniefalco.github.com/Beast][2]
## Platforms
All platforms supported by JUCE are also supported by Beast. Currently these
platforms include:
- **Windows**: Applications and VST/RTAS/NPAPI/ActiveX plugins can be built
using MS Visual Studio. The results are all fully compatible with Windows
XP, Vista or Windows 7.
- **Mac OS X**: Applications and VST/AudioUnit/RTAS/NPAPI plugins with Xcode.
- **GNU/Linux**: Applications and plugins can be built for any kernel 2.6 or
later.
- **iOS**: Native iPhone and iPad apps.
- **Android**: Supported.
## Prerequisites
This documentation assumes that the reader has a working knowledge of JUCE.
Some modules built on external libraries assume that the reader understands
the operation of those external libraries. Certain modules assume that the
reader understands additional domain-specific information. Modules with
additional prerequisites are marked in the documentation.
## External Modules
Some modules bring in functionality provided by external libraries. For
example, the @ref beast_bzip2 module provides the compression and decompression
algorithms in [bZip2][7]. Usage of these external library modules is optional.
They come with complete source code, as well as options for using either
system or user provided variants of the external libraries: it is not
necessary to download additional source code packages to use these modules.
External code incorporated into Beast is covered by separate licenses. See
the licensing information and notes in the corresponding source files for
copyright information and terms of use.
## Integration
Beast requires recent versions of JUCE. It won't work with versions 1.53 or
earlier. To use the library it is necessary to first download JUCE to a
location where your development environment can find it. Or, you can use your
existing installation of JUCE.
This library uses the same modularized organizational structure as JUCE. To
use a module, first add a path to the list of includes searched by your
development environment or project, which points to the Beast directory. Then,
add the single corresponding .c or .cpp file to your existing project which
already uses JUCE. For example, to use the @ref beast_core module, add the file
beast_core.cpp to your project. Some modules depend on other modules.
To use a module, include the appropriate header from within your source code.
For example, to access classes in the @ref beast_concurrent module, use this:
@code
#include "modules/beast_concurrent/beast_concurrent.h"
@endcode
Then add the corresponding file beast_concurrent.cpp to your build.
## AppConfig
Some Beast features can be controlled at compilation time through
preprocessor directives. The available choices of compilation options are
described in AppConfig.h, located in the AppConfigTemplate directory. Copy
the provided settings into your existing AppConfig.h (a file used by JUCE
convention).
## License
This library contains portions of other open source products covered by
separate licenses. Please see the corresponding source files for specific
terms.
Beast is provided under the terms of The MIT License (MIT):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
Some files contain portions of these external projects, licensed separately:
- [bZip2][7] is Copyright (C) 1996-2010 Julian R Seward. All rights
reserved. See the corresponding file LICENSE for licensing terms.
- Portions of the software are Copyright (C) 1996-2001, 2006 by [The FreeType
Project][8]. All rights reserved. [FreeType][8] is distributed
under both the [GNU General Public License][5], or the
[FreeType License][9].
- Portions of this software are Copyright (C) 1994-2012 [Lua.org][10], PUC-Rio.
Lua is distributed under the terms of the [MIT License][11].
- [Luabridge][12] is Copyright (C) 2012 by Vinnie Falco and Copyrighted (C)
2007 by Nathan Reed. [Luabridge][12] is distributed under the terms of the
[MIT License][11].
- [Soci][13] is Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton, and
various others noted in the corresponding source files. Soci is distributed
under the [Boost Software License, Version 1.0][14].
- [SQLite][15], placed in the public domain.
- [TagLib][16] is distributed under both the [GNU Lesser General Public License,
Version 2.1][17] and the [Mozilla Public License][18].
[0]: mailto:vinnie.falco@gmail.com "Vinnie Falco (Email)"
[1]: https://github.com/vinniefalco/Beast "Beast Project"
[2]: http://vinniefalco.github.com/Beast/ "Beast Documentation"
[3]: http://rawmaterialsoftware.com/juce.php "JUCE"
[4]: http://rawmaterialsoftware.com/ "Raw Material Software"
[5]: http://www.gnu.org/licenses/gpl-2.0.html "GNU General Public License, version 2"
[6]: http://rawmaterialsoftware.com/jucelicense.php "JUCE Licenses"
[7]: http://www.bzip.org/ "bZip2: Home"
[8]: http://freetype.org/ "The FreeType Project"
[9]: http://www.freetype.org/FTL.TXT "The FreeType Project License"
[10]: http://www.lua.org/ "The Programming Language Lua"
[11]: http://www.opensource.org/licenses/mit-license.html "The MIT License"
[12]: https://github.com/vinniefalco/LuaBridge
[13]: http://soci.sourceforge.net/ "SOCI"
[14]: http://www.boost.org/LICENSE_1_0.txt "Boost Software License, Version 1.0"
[15]: http://sqlite.org/ "SQLite Home Page"
[16]: http://developer.kde.org/~wheeler/taglib.html "TagLib"
[17]: http://www.gnu.org/licenses/lgpl-2.1.html "Gnu Lesser General Public License, version 2.1"
[18]: http://www.mozilla.org/MPL/1.1/ "Mozilla Public License"
@copyright Copyright (C) 2008 by Vinnie Falco \<vinnie.falco@gmail.com\> ([e-mail][0])
@copyright Provided under the [MIT License][11]
*/
/*============================================================================*/
/**
@internal
Implementation classes.
Thase classes are used internally.
@defgroup internal internal
*/
/*============================================================================*/
/**
External modules.
These modules bring in functionality from third party or system libraries.
@defgroup external external
*/
/*============================================================================*/
/**
Core classes.
This module provides core required functionality, and classes useful for
general development. All other modules require this module.
@todo Discuss the treatment of exceptions versus Error objects in the library.
@todo Discuss the additions to AppConfig.h
@defgroup beast_core beast_core
*/
/* See the Juce notes regarding AppConfig.h
This file must always be included before any Juce headers.
There are some Beast specific build options that may be placed
into this file. See the AppConfig.h provided with Beast.
*/
/* BeastConfig.h must be included before this file */
/* Use sensible default configurations if they forgot
to append the necessary macros into their AppConfig.h.
*/
#ifndef BEAST_USE_BOOST
#define BEAST_USE_BOOST 0
#endif
#ifndef BEAST_USE_BZIP2
#define BEAST_USE_BZIP2 0
#endif
#ifndef BEAST_USE_NATIVE_SQLITE
#define BEAST_USE_NATIVE_SQLITE 1
#endif
#ifndef BEAST_USE_LEAKCHECKED
#define BEAST_USE_LEAKCHECKED BEAST_CHECK_MEMORY_LEAKS
#endif
/* Get this early so we can use it. */
#include "../beast_core/system/beast_TargetPlatform.h"
#if BEAST_USE_BOOST
#include <boost/thread/tss.hpp>
#endif
#if BEAST_MSVC
# include <crtdbg.h>
# include <functional>
#elif BEAST_IOS
# if BEAST_USE_BOOST
# include <boost/bind.hpp>
# include <boost/function.hpp>
# else
# include <ciso646> // detect std::lib
# if _LIBCPP_VERSION // libc++
# include <functional>
# else // libstdc++ (GNU)
# include <tr1/functional>
# endif
# endif
#elif BEAST_MAC
# include <ciso646> // detect std::lib
# if _LIBCPP_VERSION // libc++
# include <functional>
# else // libstdc++ (GNU)
# include <tr1/functional>
# endif
#elif BEAST_LINUX
# include <tr1/functional>
#else
# error Unnkown platform!
#endif
#include <algorithm>
#include <cfloat>
#include <cmath>
#include <cstdarg>
#include <cstddef>
#include <exception>
#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>
#ifdef _CRTDBG_MAP_ALLOC
#error "MSVC C Runtime Debug Macros not supported"
#endif
// If the MSVC debug heap headers were included, disable
// the macros during the juce include since they conflict.
#ifdef _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <stdlib.h>
#include <malloc.h>
#pragma push_macro("calloc")
#pragma push_macro("free")
#pragma push_macro("malloc")
#pragma push_macro("realloc")
#pragma push_macro("_recalloc")
#pragma push_macro("_aligned_free")
#pragma push_macro("_aligned_malloc")
#pragma push_macro("_aligned_offset_malloc")
#pragma push_macro("_aligned_realloc")
#pragma push_macro("_aligned_recalloc")
#pragma push_macro("_aligned_offset_realloc")
#pragma push_macro("_aligned_offset_recalloc")
#pragma push_macro("_aligned_msize")
#undef calloc
#undef free
#undef malloc
#undef realloc
#undef _recalloc
#undef _aligned_free
#undef _aligned_malloc
#undef _aligned_offset_malloc
#undef _aligned_realloc
#undef _aligned_recalloc
#undef _aligned_offset_realloc
#undef _aligned_offset_recalloc
#undef _aligned_msize
#endif
#include "../beast_core/beast_core.h"
#ifdef _CRTDBG_MAP_ALLOC
#pragma pop_macro("_aligned_msize")
#pragma pop_macro("_aligned_offset_recalloc")
#pragma pop_macro("_aligned_offset_realloc")
#pragma pop_macro("_aligned_recalloc")
#pragma pop_macro("_aligned_realloc")
#pragma pop_macro("_aligned_offset_malloc")
#pragma pop_macro("_aligned_malloc")
#pragma pop_macro("_aligned_free")
#pragma pop_macro("_recalloc")
#pragma pop_macro("realloc")
#pragma pop_macro("malloc")
#pragma pop_macro("free")
#pragma pop_macro("calloc")
#endif
/** The Beast namespace.
This namespace contains all Beast symbols.
*/
namespace beast
{
// This group must come first since other files need it
#include "memory/beast_Uncopyable.h"
#include "diagnostic/beast_CatchAny.h"
#include "diagnostic/beast_Debug.h"
#include "diagnostic/beast_Error.h"
#include "diagnostic/beast_FPUFlags.h"
#include "diagnostic/beast_LeakChecked.h"
#include "diagnostic/beast_SafeBool.h"
#include "diagnostic/beast_Throw.h"
#include "containers/beast_List.h"
#include "containers/beast_LockFreeStack.h"
#include "containers/beast_LockFreeQueue.h"
#include "containers/beast_SharedTable.h"
#include "containers/beast_SortedLookupTable.h"
#include "events/beast_OncePerSecond.h"
#include "events/beast_PerformedAtExit.h"
#include "functor/beast_Bind.h"
#include "functor/beast_Function.h"
#include "math/beast_Interval.h"
#include "math/beast_Math.h"
#include "math/beast_MurmurHash.h"
#include "memory/beast_MemoryAlignment.h"
#include "memory/beast_StaticObject.h"
#include "memory/beast_AtomicCounter.h"
#include "memory/beast_AtomicFlag.h"
#include "memory/beast_AtomicPointer.h"
#include "memory/beast_AtomicState.h"
#include "memory/beast_AllocatedBy.h"
#include "memory/beast_RefCountedSingleton.h"
#include "memory/beast_FifoFreeStore.h"
#if BEAST_USE_BOOST
#include "memory/beast_FifoFreeStoreWithTLS.h"
#else
#include "memory/beast_FifoFreeStoreWithoutTLS.h"
#endif
#include "memory/beast_GlobalFifoFreeStore.h"
#include "memory/beast_GlobalPagedFreeStore.h"
#include "memory/beast_PagedFreeStore.h"
#if BEAST_MSVC
#pragma warning (push)
#pragma warning (disable: 4100) // unreferenced formal parmaeter
#pragma warning (disable: 4355) // 'this' used in base member
#endif
#include "memory/beast_CacheLine.h"
#if BEAST_MSVC
#pragma warning (pop)
#endif
#include "threads/beast_Semaphore.h"
#include "threads/beast_SerialFor.h"
#include "threads/beast_SpinDelay.h"
#include "threads/beast_InterruptibleThread.h"
#include "threads/beast_ReadWriteMutex.h"
#include "threads/beast_ThreadGroup.h"
#include "threads/beast_CallQueue.h"
#include "threads/beast_ConcurrentObject.h"
#include "threads/beast_ConcurrentState.h"
#include "threads/beast_GlobalThreadGroup.h"
#include "threads/beast_Listeners.h"
#include "threads/beast_ManualCallQueue.h"
#include "threads/beast_ParallelFor.h"
#include "threads/beast_ThreadWithCallQueue.h"
#include "threads/beast_SharedObject.h"
}
#endif

View File

@@ -1,796 +0,0 @@
//------------------------------------------------------------------------------
/*
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

@@ -1,226 +0,0 @@
//------------------------------------------------------------------------------
/*
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
#include "../memory/beast_CacheLine.h"
#include "../memory/beast_AtomicPointer.h"
#include "../threads/beast_SpinDelay.h"
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;
};
/*============================================================================*/
/** Default tag for LockFreeQueue
@ingroup beast_core intrusive
*/
struct LockFreeQueueDefaultTag { };
#endif

View File

@@ -1,166 +0,0 @@
//------------------------------------------------------------------------------
/*
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
#include "../memory/beast_AtomicPointer.h"
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;
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

@@ -1,213 +0,0 @@
//------------------------------------------------------------------------------
/*
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_gui
*/
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

@@ -1,156 +0,0 @@
//------------------------------------------------------------------------------
/*
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;
values_t m_values;
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;
}
};
#endif

View File

@@ -1,276 +0,0 @@
//------------------------------------------------------------------------------
/*
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 0
#include <iostream>
//------------------------------------------------------------------------------
//
// Windows structured exception handling
//
#if BEAST_MSVC
#include <windows.h>
namespace vf
{
namespace
{
//
// While this object is in scope, any Windows SEH
// exceptions will be caught and re-thrown as an Error object.
//
class ScopedPlatformExceptionCatcher : Uncopyable
{
public:
ScopedPlatformExceptionCatcher ()
{
//s_mutex.enter ();
if (++s_count == 1)
s_sehPrev = ::SetUnhandledExceptionFilter (sehFilter);
//s_mutex.exit ();
}
~ScopedPlatformExceptionCatcher ()
{
//s_mutex.enter ();
if (--s_count == 0)
SetUnhandledExceptionFilter (s_sehPrev);
//s_mutex.exit ();
}
static LONG WINAPI sehFilter (_EXCEPTION_POINTERS* ei)
{
EXCEPTION_RECORD* er = ei->ExceptionRecord;
if (er->ExceptionCode == EXCEPTION_BREAKPOINT ||
er->ExceptionCode == EXCEPTION_SINGLE_STEP)
{
// pass through
}
else
{
String s;
switch (er->ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
s = TRANS ("an access violation occurred");
break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
s = TRANS ("array bounds were exceeded");
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
s = TRANS ("memory access was unaligned");
break;
case EXCEPTION_FLT_DENORMAL_OPERAND:
s = TRANS ("a floating point operation produced a denormal");
break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
s = TRANS ("a floating point divide by zero was attempted");
break;
case EXCEPTION_FLT_INEXACT_RESULT:
s = TRANS ("the floating point operation was unrepresentable");
break;
case EXCEPTION_FLT_INVALID_OPERATION:
s = TRANS ("the floating point operation was invalid");
break;
case EXCEPTION_FLT_OVERFLOW:
s = TRANS ("the floating point operation overflowed");
break;
case EXCEPTION_FLT_STACK_CHECK:
s = TRANS ("a stack check resulted from a floating point operation");
break;
case EXCEPTION_FLT_UNDERFLOW:
s = TRANS ("the floating point operation underflowed");
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
s = TRANS ("an invalid instruction was received");
break;
case EXCEPTION_IN_PAGE_ERROR:
s = TRANS ("a virtual paging error occurred");
break;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
s = TRANS ("an integer divide by zero was attempted");
break;
case EXCEPTION_INT_OVERFLOW:
s = TRANS ("an integer operation overflowed");
break;
case EXCEPTION_INVALID_DISPOSITION:
s = TRANS ("the exception handler returned an invalid disposition");
break;
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
s = TRANS ("a non-continuable exception occurred");
break;
case EXCEPTION_PRIV_INSTRUCTION:
s = TRANS ("a privileged instruction was attempted");
break;
case EXCEPTION_STACK_OVERFLOW:
s = TRANS ("the stack overflowed");
break;
default:
s = TRANS ("an unknown system exception of code ");
s << String ((unsigned int)er->ExceptionCode);
s << " " << TRANS ("occurred");
break;
}
Throw (Error ().fail (__FILE__, __LINE__, s, Error::platform));
}
return s_sehPrev (ei);
}
private:
static int s_count;
static CriticalSection s_mutex;
static LPTOP_LEVEL_EXCEPTION_FILTER s_sehPrev;
};
CriticalSection ScopedPlatformExceptionCatcher::s_mutex;
int ScopedPlatformExceptionCatcher::s_count = 0;
LPTOP_LEVEL_EXCEPTION_FILTER ScopedPlatformExceptionCatcher::s_sehPrev = 0;
}
}
//------------------------------------------------------------------------------
#else
// TODO: POSIX SIGNAL HANDLER
#pragma message(BEAST_FILEANDLINE_ "Missing class ScopedPlatformExceptionCatcher")
namespace vf
{
namespace
{
class ScopedPlatformExceptionCatcher
{
public:
// Missing
};
}
END_BEAST_NAMESPACE
#endif
#endif
//------------------------------------------------------------------------------
bool CatchAny (Function <void (void)> f, bool returnFromException)
{
bool caughtException = true; // assume the worst
#if 0
try
{
//ScopedPlatformExceptionCatcher platformExceptionCatcher;
f ();
caughtException = false;
}
catch (Error& e)
{
if (!returnFromException)
{
JUCEApplication* app = JUCEApplication::getInstance ();
if (app)
{
app->unhandledException (
&e,
e.getSourceFilename (),
e.getLineNumber ());
}
else
{
std::cout << e.what ();
std::unexpected ();
}
}
}
catch (std::exception& e)
{
if (!returnFromException)
{
JUCEApplication* app = JUCEApplication::getInstance ();
if (app)
{
app->unhandledException (&e, __FILE__, __LINE__);
}
else
{
std::cout << e.what ();
std::unexpected ();
}
}
}
catch (...)
{
if (!returnFromException)
{
JUCEApplication* app = JUCEApplication::getInstance ();
if (app)
{
app->unhandledException (0, __FILE__, __LINE__);
}
else
{
std::unexpected ();
}
}
}
#endif
return caughtException;
}

View File

@@ -1,56 +0,0 @@
//------------------------------------------------------------------------------
/*
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_CATCHANY_BEASTHEADER
#define BEAST_CATCHANY_BEASTHEADER
#include "../functor/beast_Function.h"
/**
Exception catcher.
Executes the function and catches any exception.
In addition to C++ exceptions, this will also catch
any platform-specific exceptions. For example, SEH
(Structured Exception Handling) on Windows, or POSIX
signals if they are available.
If returnFromException is false then a framework
specific unhandled exception handler will be called.
Otherwise, this function will return true if it
catches something or else false.
The return value approach is useful for detecting
when outside code fails (for example, a VST plugin),
and disabling its future use for example.
@todo Remove dependence on the JUCEApplication object and remove beast_gui_basics.h from beast_core.cpp
@param f The function to call.
@param returnFromException `false` if exceptions should terminate the app.
@return `true` if an exception was caught.
@ingroup beast_core
*/
extern bool CatchAny (Function <void (void)> f,
bool returnFromException = false);
#endif

View File

@@ -1,255 +0,0 @@
//------------------------------------------------------------------------------
/*
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

@@ -1,56 +0,0 @@
//------------------------------------------------------------------------------
/*
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 ();
// VF: 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

@@ -1,243 +0,0 @@
//------------------------------------------------------------------------------
/*
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 (const Error& 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= (const Error& 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;
}
const String Error::getReasonText () const
{
return m_reasonText;
}
const String Error::getSourceFilename () const
{
return m_sourceFileName;
}
int Error::getLineNumber () const
{
return m_lineNumber;
}
Error& Error::fail (const char* sourceFileName,
int lineNumber,
const String 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 (const char* 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;
}
const char* 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;
}
const String 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

@@ -1,126 +0,0 @@
//------------------------------------------------------------------------------
/*
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
#include "beast_SafeBool.h"
/**
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 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 (const Error& other);
Error& operator= (const Error& other);
virtual ~Error () noexcept;
Code code () const;
bool failed () const;
bool asBoolean () const;
const String getReasonText () const;
const String getSourceFilename () const;
int getLineNumber () const;
Error& fail (const char* sourceFileName,
int lineNumber,
const String reasonText,
Code errorCode = general);
Error& fail (const char* 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.
const char* what () const noexcept;
static const String 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 const char* m_szWhat;
};
#endif

View File

@@ -1,40 +0,0 @@
//------------------------------------------------------------------------------
/*
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

@@ -1,335 +0,0 @@
//------------------------------------------------------------------------------
/*
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 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

@@ -1,91 +0,0 @@
//------------------------------------------------------------------------------
/*
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

@@ -1,171 +0,0 @@
//------------------------------------------------------------------------------
/*
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
#include "beast_Error.h"
#include "beast_Throw.h"
#include "../memory/beast_StaticObject.h"
#include "../containers/beast_LockFreeStack.h"
//
// Derived classes are automatically leak-checked on exit
//
#if BEAST_USE_LEAKCHECKED
class 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 LeakCheckedBase
{
private:
friend class PerformedAtExit;
static void detectAllLeaks () { }
};
template <class Object>
struct LeakChecked : LeakCheckedBase
{
};
#endif
#endif

View File

@@ -1,91 +0,0 @@
//------------------------------------------------------------------------------
/*
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 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

@@ -1,38 +0,0 @@
//------------------------------------------------------------------------------
/*
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 the opportunity to get a
// breakpoint with the call stack before the throw.
//
template <class Exception>
inline void Throw (Exception const& e)
{
Debug::breakPoint ();
throw e;
}
#endif

View File

@@ -1,111 +0,0 @@
//------------------------------------------------------------------------------
/*
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 OncePerSecond::TimerSingleton
: public RefCountedSingleton <OncePerSecond::TimerSingleton>
, private InterruptibleThread::EntryPoint
{
private:
TimerSingleton ()
: RefCountedSingleton <OncePerSecond::TimerSingleton> (
SingletonLifetime::persistAfterCreation)
, m_thread ("Once Per Second")
{
m_thread.start (this);
}
~TimerSingleton ()
{
m_thread.join ();
bassert (m_list.empty ());
}
void threadRun ()
{
for (;;)
{
const bool interrupted = m_thread.wait (1000);
if (interrupted)
break;
notify ();
}
}
void notify ()
{
CriticalSection::ScopedLockType lock (m_mutex);
for (List <Elem>::iterator iter = m_list.begin (); iter != m_list.end ();)
{
OncePerSecond* object = iter->object;
++iter;
object->doOncePerSecond ();
}
}
public:
void insert (Elem* elem)
{
CriticalSection::ScopedLockType lock (m_mutex);
m_list.push_back (*elem);
}
void remove (Elem* elem)
{
CriticalSection::ScopedLockType lock (m_mutex);
m_list.erase (m_list.iterator_to (*elem));
}
static TimerSingleton* createInstance ()
{
return new TimerSingleton;
}
private:
InterruptibleThread m_thread;
CriticalSection m_mutex;
List <Elem> m_list;
};
//------------------------------------------------------------------------------
OncePerSecond::OncePerSecond ()
{
m_elem.instance = TimerSingleton::getInstance ();
m_elem.object = this;
}
OncePerSecond::~OncePerSecond ()
{
}
void OncePerSecond::startOncePerSecond ()
{
m_elem.instance->insert (&m_elem);
}
void OncePerSecond::endOncePerSecond ()
{
m_elem.instance->remove (&m_elem);
}

View File

@@ -1,64 +0,0 @@
//------------------------------------------------------------------------------
/*
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_ONCEPERSECOND_BEASTHEADER
#define BEAST_ONCEPERSECOND_BEASTHEADER
#include "../containers/beast_List.h"
/*============================================================================*/
/**
Provides a once per second notification.
Derive your class from OncePerSecond and override doOncePerSecond(). Then,
call startOncePerSecond() to begin receiving the notifications. No clean-up
or other actions are required.
@ingroup beast_core
*/
class OncePerSecond : Uncopyable
{
public:
OncePerSecond ();
virtual ~OncePerSecond ();
/** Begin receiving notifications. */
void startOncePerSecond ();
/** Stop receiving notifications. */
void endOncePerSecond ();
protected:
/** Called once per second. */
virtual void doOncePerSecond () = 0;
private:
class TimerSingleton;
typedef ReferenceCountedObjectPtr <TimerSingleton> TimerPtr;
struct Elem : List <Elem>::Node
{
TimerPtr instance;
OncePerSecond* object;
};
Elem m_elem;
};
#endif

View File

@@ -1,66 +0,0 @@
//------------------------------------------------------------------------------
/*
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::Performer
{
public:
typedef Static::Storage <LockFreeStack <PerformedAtExit>, PerformedAtExit> StackType;
private:
~Performer ()
{
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 Performer s_performer;
};
PerformedAtExit::Performer PerformedAtExit::Performer::s_performer;
PerformedAtExit::Performer::StackType PerformedAtExit::Performer::s_list;
PerformedAtExit::PerformedAtExit ()
{
#if BEAST_IOS
// TODO: PerformedAtExit::Performer::push_front crashes on iOS if s_storage is not accessed before used
char* hack = PerformedAtExit::Performer::s_list.s_storage;
#endif
Performer::push_front (this);
}

View File

@@ -1,50 +0,0 @@
//------------------------------------------------------------------------------
/*
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
#include "../containers/beast_LockFreeStack.h"
/*============================================================================*/
/**
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
*/
class PerformedAtExit : public LockFreeStack <PerformedAtExit>::Node
{
protected:
PerformedAtExit ();
virtual ~PerformedAtExit () { }
protected:
/** Called at program exit.
*/
virtual void performAtExit () = 0;
private:
class Performer;
};
#endif

View File

@@ -1,96 +0,0 @@
//------------------------------------------------------------------------------
/*
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
/* Brings functional support into our namespace, based on environment.
*/
#if BEAST_MSVC
// Visual Studio has these in std.
using std::ref;
using std::bind;
using std::function;
using std::placeholders::_1;
using std::placeholders::_2;
#elif BEAST_IOS
#if BEAST_USE_BOOST
/* If boost is activated, use it. This works
around a bug with the iOS implementation of bind.
*/
using boost::ref
using boost::bind;
using boost::function;
using ::_1;
using ::_2;
#else
#if _LIBCPP_VERSION // libc++
using std::ref;
using std::bind;
using std::function;
using std::placeholders::_1;
using std::placeholders::_2;
#else // libstdc++ (GNU)
using std::tr1::ref;
using std::tr1::bind;
using std::tr1::function;
using std::tr1::placeholders::_1;
using std::tr1::placeholders::_2;
#endif
#endif
#elif BEAST_MAC
#if _LIBCPP_VERSION // libc++
using std::ref;
using std::bind;
using std::function;
using std::placeholders::_1;
using std::placeholders::_2;
#else // libstdc++ (GNU)
using std::tr1::ref;
using std::tr1::bind;
using std::tr1::function;
using std::tr1::placeholders::_1;
using std::tr1::placeholders::_2;
#endif
#elif BEAST_LINUX
using std::tr1::bind;
using std::tr1::placeholders::_1;
using std::tr1::placeholders::_2;
#else
#error Unknown platform in beast_Bind.h
#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
#endif

View File

@@ -1,266 +0,0 @@
//------------------------------------------------------------------------------
/*
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_FUNCTION_BEASTHEADER
#define BEAST_FUNCTION_BEASTHEADER
//
// Strong replacement for boost::function:
//
// #1 Bounded memory requirement, avoids the free store.
//
// #2 Always refers to a functor (i.e. is never invalid)
//
// #3 Default value (None) is a function that
// returns a default object (the result type
// constructed with a default constructor).
//
template <typename Signature, int Bytes = 128>
class Function;
//
// nullary function
//
template <typename R, int Bytes>
class Function <R (void), Bytes>
{
public:
typedef R result_type;
typedef Function self_type;
struct None
{
typedef R result_type;
result_type operator () () const
{
return result_type ();
}
};
Function ()
{
constructCopyOf (None ());
}
Function (Function const& f)
{
f.getCall ().constructCopyInto (m_storage);
}
template <class Functor>
Function (Functor const& f)
{
constructCopyOf (f);
}
~Function ()
{
getCall ().~Call ();
}
Function& operator= (Function const& f)
{
getCall ().~Call ();
f.getCall ().constructCopyInto (m_storage);
return *this;
}
template <class Functor>
Function& operator= (Functor const& f)
{
getCall ().~Call ();
constructCopyOf (f);
return *this;
}
result_type operator () ()
{
return getCall ().operator () ();
}
private:
template <class Functor>
void constructCopyOf (Functor const& f)
{
// If this generates a compile error it means that
// the functor is too large for the static buffer.
// Increase the storage template parameter until
// the error message goes away. This might cause
// changes throughout the application with other
// template classes that depend on the size.
static_bassert (sizeof (StoredCall <Functor>) <= Bytes);
new (m_storage) StoredCall <Functor> (f);
}
private:
struct Call
{
virtual ~Call () {}
virtual void constructCopyInto (void* p) const = 0;
virtual result_type operator () () = 0;
};
template <class Functor>
struct StoredCall : Call
{
explicit StoredCall (Functor const& f) : m_f (f) { }
StoredCall (const StoredCall& c) : m_f (c.m_f) { }
void constructCopyInto (void* p) const
{
new (p) StoredCall (m_f);
}
result_type operator () ()
{
return m_f ();
}
private:
Functor m_f;
};
Call& getCall ()
{
return *reinterpret_cast <Call*> (&m_storage[0]);
}
Call const& getCall () const
{
return *reinterpret_cast <Call const*> (&m_storage[0]);
}
char m_storage [Bytes]; // should be enough
};
//------------------------------------------------------------------------------
//
// unary function
//
template <typename R, typename T1, int Bytes>
class Function <R (T1 t1), Bytes>
{
public:
typedef R result_type;
typedef Function self_type;
struct None
{
typedef R result_type;
result_type operator () (T1) const
{
return result_type ();
}
};
Function ()
{
constructCopyOf (None ());
}
Function (const Function& f)
{
f.getCall ().constructCopyInto (m_storage);
}
template <class Functor>
Function (Functor const& f)
{
constructCopyOf (f);
}
~Function ()
{
getCall ().~Call ();
}
Function& operator= (const Function& f)
{
getCall ().~Call ();
f.getCall ().constructCopyInto (m_storage);
return *this;
}
template <class Functor>
Function& operator= (Functor const& f)
{
getCall ().~Call ();
constructCopyOf (f);
return *this;
}
result_type operator () (T1 t1)
{
return getCall ().operator () (t1);
}
private:
template <class Functor>
void constructCopyOf (Functor const& f)
{
// If this generates a compile error it means that
// the functor is too large for the static buffer.
// Increase the storage template parameter until
// the error message goes away. This might cause
// changes throughout the application with other
// template classes that depend on the size.
static_bassert (sizeof (StoredCall <Functor>) <= Bytes);
new (m_storage) StoredCall <Functor> (f);
}
private:
struct Call
{
virtual ~Call () {}
virtual void constructCopyInto (void* p) const = 0;
virtual result_type operator () (T1 t1) = 0;
};
template <class Functor>
struct StoredCall : Call
{
explicit StoredCall (Functor const& f) : m_f (f) { }
StoredCall (const StoredCall& c) : m_f (c.m_f) { }
void constructCopyInto (void* p) const
{
new (p) StoredCall (m_f);
}
result_type operator () (T1 t1)
{
return m_f (t1);
}
private:
Functor m_f;
};
Call& getCall ()
{
return *reinterpret_cast <Call*> (&m_storage[0]);
}
Call const& getCall () const
{
return *reinterpret_cast <Call const*> (&m_storage[0]);
}
char m_storage [Bytes]; // should be enough
};
#endif

View File

@@ -1,387 +0,0 @@
//------------------------------------------------------------------------------
/*
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_INTERVAL_BEASTHEADER
#define BEAST_INTERVAL_BEASTHEADER
/** A half-open interval.
This represents the half-open interval [begin, end) over the scalar
type of template parameter `Ty`. It may also be considered as the
specification of a subset of a 1-dimensional Euclidean space.
@tparam Ty A scalar numerical type.
*/
template <class Ty>
class Interval
{
public:
typedef Ty value_type;
/** The empty interval.
*/
static const Interval none;
/** Create an uninitialized interval.
*/
Interval ()
{
}
/** Create an interval with the specified values.
*/
Interval (Ty begin, Ty end)
: m_begin (begin)
, m_end (end)
{
}
/** Create an interval from another interval.
*/
Interval (Interval const& other)
: m_begin (other.m_begin)
, m_end (other.m_end)
{
}
/** Assign from another interval.
@param other The interval to assign from.
@return A reference to this interval.
*/
Interval& operator= (const Interval& other)
{
m_begin = other.m_begin;
m_end = other.m_end;
return *this;
}
/** Compare an interval for equality.
Empty intervals are always equal to other empty intervals.
@param rhs The other interval to compare.
@return `true` if this interval is equal to the specified interval.
*/
bool operator== (Interval const& rhs) const
{
return (empty () && rhs.empty ()) ||
(m_begin == rhs.m_begin && m_end == rhs.m_end);
}
/** Compare an interval for inequality.
@param rhs The other interval to compare.
@return `true` if this interval is not equal to the specified interval.
*/
bool operator!= (Interval const& rhs) const
{
return !this->operator== (rhs);
}
/** Get the starting value of the interval.
@return The starting point of the interval.
*/
Ty begin () const
{
return m_begin;
}
/** Get the ending value of the interval.
@return The ending point of the interval.
*/
Ty end () const
{
return m_end;
}
/** Get the Lebesque measure.
@return The Lebesque measure.
*/
Ty length () const
{
return empty () ? Ty () : (end () - begin ());
}
//Ty count () const { return length (); } // sugar
//Ty distance () const { return length (); } // sugar
/** Determine if the interval is empty.
@return `true` if the interval is empty.
*/
bool empty () const
{
return m_begin >= m_end;
}
/** Determine if the interval is non-empty.
@return `true` if the interval is not empty.
*/
bool notEmpty () const
{
return m_begin < m_end;
}
/** Set the starting point of the interval.
@param v The starting point.
*/
void setBegin (Ty v)
{
m_begin = v;
}
/** Set the ending point of the interval.
@param v The ending point.
*/
void setEnd (Ty v)
{
m_end = v;
}
/** Set the ending point relative to the starting point.
@param v The length of the resulting interval.
*/
void setLength (Ty v)
{
m_end = m_begin + v;
}
/** Determine if a value is contained in the interval.
@param v The value to check.
@return `true` if this interval contains `v`.
*/
bool contains (Ty v) const
{
return notEmpty () && v >= m_begin && v < m_end;
}
/** Determine if this interval intersects another interval.
@param other The other interval.
@return `true` if the intervals intersect.
*/
template <class To>
bool intersects (Interval <To> const& other) const
{
return notEmpty () && other.notEmpty () &&
end () > other.begin () && begin () < other.end ();
}
/** Determine if this interval adjoins another interval.
An interval is adjoint to another interval if and only if the union of the
intervals is a single non-empty half-open subset.
@param other The other interval.
@return `true` if the intervals are adjoint.
*/
template <class To>
bool adjoins (Interval <To> const& other) const
{
return (empty () != other.empty ()) ||
(notEmpty () && end () >= other.begin ()
&& begin () <= other.end ());
}
/** Determine if this interval is disjoint from another interval.
@param other The other interval.
@return `true` if the intervals are disjoint.
*/
bool disjoint (Interval const& other) const
{
return !intersects (other);
}
/** Determine if this interval is a superset of another interval.
An interval A is a superset of interval B if B is empty or if A fully
contains B.
@param other The other interval.
@return `true` if this is a superset of `other`.
*/
template <class To>
bool superset_of (Interval <To> const& other) const
{
return other.empty () ||
(notEmpty () && begin () <= other.begin ()
&& end () >= other.end ());
}
/** Determine if this interval is a proper superset of another interval.
An interval A is a proper superset of interval B if A is a superset of
B and A is not equal to B.
@param other The other interval.
@return `true` if this interval is a proper superset of `other`.
*/
template <class To>
bool proper_superset_of (Interval <To> const& other) const
{
return this->superset_of (other) && this->operator != (other);
}
/** Determine if this interval is a subset of another interval.
@param other The other interval.
@return `true` if this interval is a subset of `other`.
*/
template <class To>
bool subset_of (Interval <To> const& other) const
{
return other.superset_of (*this);
}
/** Determine if this interval is a proper subset of another interval.
@param other The other interval.
@return `true` if this interval is a proper subset of `other`.
*/
template <class To>
bool proper_subset_of (Interval <To> const& other) const
{
return other.proper_superset_of (*this);
}
/** Return the intersection of this interval with another interval.
@param other The other interval.
@return The intersection of the intervals.
*/
template <class To>
Interval intersection (Interval <To> const& other) const
{
return Interval (std::max (begin (), other.begin ()),
std::min (end (), other.end ()));
}
/** Determine the smallest interval that contains both intervals.
@param other The other interval.
@return The simple union of the intervals.
*/
template <class To>
Interval simple_union (Interval <To> const& other) const
{
return Interval (
std::min (other.normalized ().begin (), normalized ().begin ()),
std::max (other.normalized ().end (), normalized ().end ()));
}
/** Calculate the single-interval union.
The result is empty if the union cannot be represented as a
single half-open interval.
@param other The other interval.
@return The simple union of the intervals.
*/
template <class To>
Interval single_union (Interval <To> const& other) const
{
if (empty ())
return other;
else if (other.empty ())
return *this;
else if (end () < other.begin () || begin () > other.end ())
return none;
else
return Interval (std::min (begin (), other.begin ()),
std::max (end (), other.end ()));
}
/** Determine if the interval is correctly ordered.
@return `true` if the interval is correctly ordered.
*/
bool normal () const
{
return end () >= begin ();
}
/** Return a normalized interval.
@return The normalized interval.
*/
Interval normalized () const
{
if (normal ())
return *this;
else
return Interval (end (), begin ());
}
/** Clamp a value to the interval.
@param v The value to clamp.
@return The clamped result.
*/
template <typename Tv>
Ty clamp (Tv v) const
{
// These conditionals are carefully ordered so
// that if m_begin == m_end, value is assigned m_begin.
if (v > end ())
v = end () - (std::numeric_limits <Tv>::is_integer ? 1 :
std::numeric_limits <Tv>::epsilon ());
if (v < begin ())
v = begin ();
return v;
}
private:
Ty m_begin;
Ty m_end;
};
template <typename Ty>
const Interval<Ty> Interval<Ty>::none = Interval<Ty> (Ty (), Ty ());
#endif

View File

@@ -1,84 +0,0 @@
//------------------------------------------------------------------------------
/*
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_MATH_BEASTHEADER
#define BEAST_MATH_BEASTHEADER
//
// Miscellaneous mathematical calculations
//
// Calculate the bin for a value given the bin size.
// This correctly handles negative numbers. For example
// if value == -1 then calc_bin returns -1.
template <typename Ty>
inline Ty calc_bin (Ty value, int size)
{
if (value >= 0)
return value / size;
else
return (value - size + 1) / size;
}
// Given a number and a bin size, this returns the first
// corresponding value of the bin associated with the given number.
// It correctly handles negative numbers. For example,
// if value == -1 then calc_bin always returns -size
template <typename Ty>
inline Ty calc_bin_start (Ty value, int size)
{
return calc_bin (value, size) * size;
}
template <class T>
inline T pi () noexcept
{
return 3.14159265358979;
}
template <class T>
inline T twoPi () noexcept
{
return 6.28318530717958;
}
template <class T>
inline T oneOverTwoPi () noexcept
{
return 0.1591549430918955;
}
template <class T, class U>
inline T degreesToRadians (U degrees)
{
return T (degrees * 0.0174532925199433);
}
template <class T, class U>
inline T radiansToDegrees (U radians)
{
T deg = T (radians * U (57.29577951308238));
if (deg < 0)
deg += 360;
return deg;
}
#endif

View File

@@ -1,487 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
// http://code.google.com/p/smhasher/
namespace Murmur
{
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
// Microsoft Visual Studio
#if BEAST_MSVC
#define ROTL32(x,y) _rotl(x,y)
#define ROTL64(x,y) _rotl64(x,y)
#define BIG_CONSTANT(x) (x)
// Other compilers
#else
static inline uint32_t rotl32 ( uint32_t x, int8_t r )
{
return (x << r) | (x >> (32 - r));
}
static inline uint64_t rotl64 ( uint64_t x, int8_t r )
{
return (x << r) | (x >> (64 - r));
}
#define ROTL32(x,y) rotl32(x,y)
#define ROTL64(x,y) rotl64(x,y)
#define BIG_CONSTANT(x) (x##LLU)
#endif
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
static forcedinline uint32_t getblock ( const uint32_t* p, int i )
{
return p[i];
}
static forcedinline uint64_t getblock ( const uint64_t* p, int i )
{
return p[i];
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
static forcedinline uint32_t fmix ( uint32_t h )
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
//----------
static forcedinline uint64_t fmix ( uint64_t k )
{
k ^= k >> 33;
k *= BIG_CONSTANT (0xff51afd7ed558ccd);
k ^= k >> 33;
k *= BIG_CONSTANT (0xc4ceb9fe1a85ec53);
k ^= k >> 33;
return k;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x86_32 ( const void* key, int len,
uint32_t seed, void* out )
{
const uint8_t* data = (const uint8_t*)key;
const int nblocks = len / 4;
uint32_t h1 = seed;
uint32_t c1 = 0xcc9e2d51;
uint32_t c2 = 0x1b873593;
//----------
// body
const uint32_t* blocks = (const uint32_t*) (data + nblocks * 4);
for (int i = -nblocks; i; i++)
{
uint32_t k1 = getblock (blocks, i);
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32 (h1, 13);
h1 = h1 * 5 + 0xe6546b64;
}
//----------
// tail
const uint8_t* tail = (const uint8_t*) (data + nblocks * 4);
uint32_t k1 = 0;
switch (len & 3)
{
case 3:
k1 ^= tail[2] << 16;
case 2:
k1 ^= tail[1] << 8;
case 1:
k1 ^= tail[0];
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h1 = fmix (h1);
* (uint32_t*)out = h1;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x86_128 ( const void* key, const int len,
uint32_t seed, void* out )
{
const uint8_t* data = (const uint8_t*)key;
const int nblocks = len / 16;
uint32_t h1 = seed;
uint32_t h2 = seed;
uint32_t h3 = seed;
uint32_t h4 = seed;
uint32_t c1 = 0x239b961b;
uint32_t c2 = 0xab0e9789;
uint32_t c3 = 0x38b34ae5;
uint32_t c4 = 0xa1e38b93;
//----------
// body
const uint32_t* blocks = (const uint32_t*) (data + nblocks * 16);
for (int i = -nblocks; i; i++)
{
uint32_t k1 = getblock (blocks, i * 4 + 0);
uint32_t k2 = getblock (blocks, i * 4 + 1);
uint32_t k3 = getblock (blocks, i * 4 + 2);
uint32_t k4 = getblock (blocks, i * 4 + 3);
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32 (h1, 19);
h1 += h2;
h1 = h1 * 5 + 0x561ccd1b;
k2 *= c2;
k2 = ROTL32 (k2, 16);
k2 *= c3;
h2 ^= k2;
h2 = ROTL32 (h2, 17);
h2 += h3;
h2 = h2 * 5 + 0x0bcaa747;
k3 *= c3;
k3 = ROTL32 (k3, 17);
k3 *= c4;
h3 ^= k3;
h3 = ROTL32 (h3, 15);
h3 += h4;
h3 = h3 * 5 + 0x96cd1c35;
k4 *= c4;
k4 = ROTL32 (k4, 18);
k4 *= c1;
h4 ^= k4;
h4 = ROTL32 (h4, 13);
h4 += h1;
h4 = h4 * 5 + 0x32ac3b17;
}
//----------
// tail
const uint8_t* tail = (const uint8_t*) (data + nblocks * 16);
uint32_t k1 = 0;
uint32_t k2 = 0;
uint32_t k3 = 0;
uint32_t k4 = 0;
switch (len & 15)
{
case 15:
k4 ^= tail[14] << 16;
case 14:
k4 ^= tail[13] << 8;
case 13:
k4 ^= tail[12] << 0;
k4 *= c4;
k4 = ROTL32 (k4, 18);
k4 *= c1;
h4 ^= k4;
case 12:
k3 ^= tail[11] << 24;
case 11:
k3 ^= tail[10] << 16;
case 10:
k3 ^= tail[ 9] << 8;
case 9:
k3 ^= tail[ 8] << 0;
k3 *= c3;
k3 = ROTL32 (k3, 17);
k3 *= c4;
h3 ^= k3;
case 8:
k2 ^= tail[ 7] << 24;
case 7:
k2 ^= tail[ 6] << 16;
case 6:
k2 ^= tail[ 5] << 8;
case 5:
k2 ^= tail[ 4] << 0;
k2 *= c2;
k2 = ROTL32 (k2, 16);
k2 *= c3;
h2 ^= k2;
case 4:
k1 ^= tail[ 3] << 24;
case 3:
k1 ^= tail[ 2] << 16;
case 2:
k1 ^= tail[ 1] << 8;
case 1:
k1 ^= tail[ 0] << 0;
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h2 ^= len;
h3 ^= len;
h4 ^= len;
h1 += h2;
h1 += h3;
h1 += h4;
h2 += h1;
h3 += h1;
h4 += h1;
h1 = fmix (h1);
h2 = fmix (h2);
h3 = fmix (h3);
h4 = fmix (h4);
h1 += h2;
h1 += h3;
h1 += h4;
h2 += h1;
h3 += h1;
h4 += h1;
((uint32_t*)out)[0] = h1;
((uint32_t*)out)[1] = h2;
((uint32_t*)out)[2] = h3;
((uint32_t*)out)[3] = h4;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x64_128 ( const void* key, const int len,
const uint32_t seed, void* out )
{
const uint8_t* data = (const uint8_t*)key;
const int nblocks = len / 16;
uint64_t h1 = seed;
uint64_t h2 = seed;
uint64_t c1 = BIG_CONSTANT (0x87c37b91114253d5);
uint64_t c2 = BIG_CONSTANT (0x4cf5ad432745937f);
//----------
// body
const uint64_t* blocks = (const uint64_t*) (data);
for (int i = 0; i < nblocks; i++)
{
uint64_t k1 = getblock (blocks, i * 2 + 0);
uint64_t k2 = getblock (blocks, i * 2 + 1);
k1 *= c1;
k1 = ROTL64 (k1, 31);
k1 *= c2;
h1 ^= k1;
h1 = ROTL64 (h1, 27);
h1 += h2;
h1 = h1 * 5 + 0x52dce729;
k2 *= c2;
k2 = ROTL64 (k2, 33);
k2 *= c1;
h2 ^= k2;
h2 = ROTL64 (h2, 31);
h2 += h1;
h2 = h2 * 5 + 0x38495ab5;
}
//----------
// tail
const uint8_t* tail = (const uint8_t*) (data + nblocks * 16);
uint64_t k1 = 0;
uint64_t k2 = 0;
switch (len & 15)
{
case 15:
k2 ^= uint64_t (tail[14]) << 48;
case 14:
k2 ^= uint64_t (tail[13]) << 40;
case 13:
k2 ^= uint64_t (tail[12]) << 32;
case 12:
k2 ^= uint64_t (tail[11]) << 24;
case 11:
k2 ^= uint64_t (tail[10]) << 16;
case 10:
k2 ^= uint64_t (tail[ 9]) << 8;
case 9:
k2 ^= uint64_t (tail[ 8]) << 0;
k2 *= c2;
k2 = ROTL64 (k2, 33);
k2 *= c1;
h2 ^= k2;
case 8:
k1 ^= uint64_t (tail[ 7]) << 56;
case 7:
k1 ^= uint64_t (tail[ 6]) << 48;
case 6:
k1 ^= uint64_t (tail[ 5]) << 40;
case 5:
k1 ^= uint64_t (tail[ 4]) << 32;
case 4:
k1 ^= uint64_t (tail[ 3]) << 24;
case 3:
k1 ^= uint64_t (tail[ 2]) << 16;
case 2:
k1 ^= uint64_t (tail[ 1]) << 8;
case 1:
k1 ^= uint64_t (tail[ 0]) << 0;
k1 *= c1;
k1 = ROTL64 (k1, 31);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h2 ^= len;
h1 += h2;
h2 += h1;
h1 = fmix (h1);
h2 = fmix (h2);
h1 += h2;
h2 += h1;
((uint64_t*)out)[0] = h1;
((uint64_t*)out)[1] = h2;
}
}

View File

@@ -1,66 +0,0 @@
//------------------------------------------------------------------------------
/*
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_MURMURHASH_BEASTHEADER
#define BEAST_MURMURHASH_BEASTHEADER
// Original source code links in .cpp file
// This file depends on some Juce declarations and defines
namespace Murmur
{
extern void MurmurHash3_x86_32 (const void* key, int len, uint32 seed, void* out);
extern void MurmurHash3_x86_128 (const void* key, int len, uint32 seed, void* out);
extern void MurmurHash3_x64_128 (const void* key, int len, uint32 seed, void* out);
// Uses Juce to choose an appropriate routine
// This handy template deduces which size hash is desired
template <typename HashType>
inline void Hash (const void* key, int len, uint32 seed, HashType* out)
{
switch (8 * sizeof (HashType))
{
case 32:
MurmurHash3_x86_32 (key, len, seed, out);
break;
#if BEAST_64BIT
case 128:
MurmurHash3_x64_128 (key, len, seed, out);
break;
#else
case 128:
MurmurHash3_x86_128 (key, len, seed, out);
break;
#endif
default:
Throw (std::runtime_error ("invalid key size in MurmurHash"));
break;
};
}
}
#endif

View File

@@ -1,63 +0,0 @@
//------------------------------------------------------------------------------
/*
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_ALLOCATEDBY_BEASTHEADER
#define BEAST_ALLOCATEDBY_BEASTHEADER
/*============================================================================*/
/**
Customized allocation for heap objects.
Derived classes will use the specified allocator for new and delete.
@param AllocatorType The type of allocator to use.
@ingroup beast_concurrent
*/
template <class AllocatorType>
class AllocatedBy
{
public:
static inline void* operator new (size_t bytes, AllocatorType& allocator) noexcept
{
return allocator.allocate (bytes);
}
static inline void* operator new (size_t bytes, AllocatorType* allocator) noexcept
{
return allocator->allocate (bytes);
}
static inline void operator delete (void* p, AllocatorType&) noexcept
{
AllocatorType::deallocate (p);
}
static inline void operator delete (void* p, AllocatorType*) noexcept
{
AllocatorType::deallocate (p);
}
static inline void operator delete (void* p) noexcept
{
AllocatorType::deallocate (p);
}
};
#endif

View File

@@ -1,83 +0,0 @@
//------------------------------------------------------------------------------
/*
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 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

@@ -1,102 +0,0 @@
//------------------------------------------------------------------------------
/*
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 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

@@ -1,133 +0,0 @@
//------------------------------------------------------------------------------
/*
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

@@ -1,101 +0,0 @@
//------------------------------------------------------------------------------
/*
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 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

@@ -1,478 +0,0 @@
//------------------------------------------------------------------------------
/*
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
#include "beast_MemoryAlignment.h"
// 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

@@ -1,41 +0,0 @@
//------------------------------------------------------------------------------
/*
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_FIFOFREESTORE_BEASTHEADER
#define BEAST_FIFOFREESTORE_BEASTHEADER
#if BEAST_USE_BOOST
#include "beast_FifoFreeStoreWithTLS.h"
#else
#include "beast_FifoFreeStoreWithoutTLS.h"
#endif
/** Selected free store based on compilation settings.
@ingroup beast_concurrent
*/
#if BEAST_USE_BOOST
typedef FifoFreeStoreWithTLS FifoFreeStoreType;
#else
typedef FifoFreeStoreWithoutTLS FifoFreeStoreType;
#endif
#endif

View File

@@ -1,194 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
// Implementation notes
//
// - A Page is a large allocation from a global PageAllocator.
//
// - Each thread maintains an 'active' page from which it makes allocations.
//
// - When the active page is full, a new one takes it's place.
//
// - Page memory is deallocated when it is not active and no longer referenced.
//
// - Each instance of FifoFreeStoreWithTLS maintains its own set of per-thread active pages,
// but uses a global PageAllocator. This reduces memory consumption without
// affecting performance.
//
// This precedes every allocation
//
struct FifoFreeStoreWithTLS::Header
{
FifoFreeStoreWithTLS::Page* page;
};
//------------------------------------------------------------------------------
class FifoFreeStoreWithTLS::Page : LeakChecked <Page>, Uncopyable
{
public:
explicit Page (const size_t bytes) : m_refs (1)
{
m_end = reinterpret_cast <char*> (this) + bytes;
m_free = reinterpret_cast <char*> (
Memory::pointerAdjustedForAlignment (this + 1));
}
~Page ()
{
bassert (! m_refs.isSignaled ());
}
inline bool release ()
{
bassert (! m_refs.isSignaled ());
return m_refs.release ();
}
void* allocate (size_t bytes)
{
bassert (bytes > 0);
char* p = Memory::pointerAdjustedForAlignment (m_free);
char* free = p + bytes;
if (free <= m_end)
{
m_free = free;
m_refs.addref ();
}
else
{
p = 0;
}
return p;
}
private:
AtomicCounter m_refs; // reference count
char* m_free; // next free byte
char* m_end; // last free byte + 1
};
//------------------------------------------------------------------------------
class FifoFreeStoreWithTLS::PerThreadData : LeakChecked <PerThreadData>, Uncopyable
{
public:
explicit PerThreadData (FifoFreeStoreWithTLS* allocator)
: m_allocator (*allocator)
, m_active (m_allocator.newPage ())
{
}
~PerThreadData ()
{
if (m_active->release ())
m_allocator.deletePage (m_active);
}
inline void* allocate (const size_t bytes)
{
const size_t headerBytes = Memory::sizeAdjustedForAlignment (sizeof (Header));
const size_t bytesNeeded = headerBytes + bytes;
if (bytesNeeded > m_allocator.m_pages->getPageBytes ())
Throw (Error ().fail (__FILE__, __LINE__, TRANS ("the memory request was too large")));
Header* header;
header = reinterpret_cast <Header*> (m_active->allocate (bytesNeeded));
if (!header)
{
if (m_active->release ())
deletePage (m_active);
m_active = m_allocator.newPage ();
header = reinterpret_cast <Header*> (m_active->allocate (bytesNeeded));
}
header->page = m_active;
return reinterpret_cast <char*> (header) + headerBytes;
}
private:
FifoFreeStoreWithTLS& m_allocator;
Page* m_active;
};
//------------------------------------------------------------------------------
inline FifoFreeStoreWithTLS::Page* FifoFreeStoreWithTLS::newPage ()
{
return new (m_pages->allocate ()) Page (m_pages->getPageBytes ());
}
inline void FifoFreeStoreWithTLS::deletePage (Page* page)
{
// Safe, because each thread maintains its own active page.
page->~Page ();
PagedFreeStoreType::deallocate (page);
}
FifoFreeStoreWithTLS::FifoFreeStoreWithTLS ()
: m_pages (PagedFreeStoreType::getInstance ())
{
//bassert (m_pages->getPageBytes () >= sizeof (Page) + Memory::allocAlignBytes);
}
FifoFreeStoreWithTLS::~FifoFreeStoreWithTLS ()
{
// Clean up this thread's data before we release
// the reference to the global page allocator.
m_tsp.reset (0);
}
//------------------------------------------------------------------------------
void* FifoFreeStoreWithTLS::allocate (const size_t bytes)
{
PerThreadData* data = m_tsp.get ();
if (!data)
{
data = new PerThreadData (this);
m_tsp.reset (data);
}
return data->allocate (bytes);
}
//------------------------------------------------------------------------------
void FifoFreeStoreWithTLS::deallocate (void* p)
{
const size_t headerBytes = Memory::sizeAdjustedForAlignment (sizeof (Header));
Header* const header = reinterpret_cast <Header*> (reinterpret_cast <char*> (p) - headerBytes);
Page* const page = header->page;
if (page->release ())
deletePage (page);
}

View File

@@ -1,67 +0,0 @@
//------------------------------------------------------------------------------
/*
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_FIFOFREESTOREWITHTLS_BEASTHEADER
#define BEAST_FIFOFREESTOREWITHTLS_BEASTHEADER
#include "beast_GlobalPagedFreeStore.h"
/*============================================================================*/
/**
Lock-free and mostly wait-free FIFO memory allocator.
This allocator is suitable for use with CallQueue and Listeners. It is
expected that over time, deallocations will occur in roughly the same order
as allocations.
@note This implementation uses Thread Local Storage to further improve
performance. However, it requires boost style thread_specific_ptr.
@invariant allocate() and deallocate() are fully concurrent.
@invariant The ABA problem is handled automatically.
@ingroup beast_concurrent
*/
class FifoFreeStoreWithTLS
{
public:
FifoFreeStoreWithTLS ();
~FifoFreeStoreWithTLS ();
void* allocate (const size_t bytes);
static void deallocate (void* const p);
private:
typedef GlobalPagedFreeStore PagedFreeStoreType;
struct Header;
class Page;
inline Page* newPage ();
static inline void deletePage (Page* page);
private:
class PerThreadData;
boost::thread_specific_ptr <PerThreadData> m_tsp;
PagedFreeStoreType::Ptr m_pages;
};
#endif

View File

@@ -1,241 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
// This precedes every allocation
struct FifoFreeStoreWithoutTLS::Header
{
union
{
FifoFreeStoreWithoutTLS::Block* block; // backpointer to the page
char pad [Memory::allocAlignBytes];
};
};
//------------------------------------------------------------------------------
class FifoFreeStoreWithoutTLS::Block : Uncopyable
{
public:
explicit Block (const size_t bytes) : m_refs (1)
{
m_end = reinterpret_cast <char*> (this) + bytes;
m_free = reinterpret_cast <char*> (
Memory::pointerAdjustedForAlignment (this + 1));
}
~Block ()
{
bassert (!m_refs.isSignaled ());
}
inline void addref ()
{
m_refs.addref ();
}
inline bool release ()
{
return m_refs.release ();
}
enum Result
{
success, // successful allocation
ignore, // disregard the block
consumed // block is consumed (1 thread sees this)
};
Result allocate (size_t bytes, void* pBlock)
{
bassert (bytes > 0);
Result result;
for (;;)
{
char* base = m_free.get ();
if (base)
{
char* p = Memory::pointerAdjustedForAlignment (base);
char* free = p + bytes;
if (free <= m_end)
{
// Try to commit the allocation
if (m_free.compareAndSet (free, base))
{
* (reinterpret_cast <void**> (pBlock)) = p;
result = success;
break;
}
else
{
// Someone changed m_free, retry.
}
}
else
{
// Mark the block consumed.
if (m_free.compareAndSet (0, base))
{
// Only one caller sees this, the rest get 'ignore'
result = consumed;
break;
}
else
{
// Happens with another concurrent allocate(), retry.
}
}
}
else
{
// Block is consumed, ignore it.
result = ignore;
break;
}
}
return result;
}
private:
AtomicCounter m_refs; // reference count
AtomicPointer <char> m_free; // next free byte or 0 if inactive.
char* m_end; // last free byte + 1
};
//------------------------------------------------------------------------------
inline FifoFreeStoreWithoutTLS::Block* FifoFreeStoreWithoutTLS::newBlock ()
{
return new (m_pages->allocate ()) Block (m_pages->getPageBytes ());
}
inline void FifoFreeStoreWithoutTLS::deleteBlock (Block* b)
{
// It is critical that we do not call the destructor,
// because due to the lock-free implementation, a Block
// can be accessed for a short time after it is deleted.
/* b->~Block (); */ // DO NOT CALL!!!
PagedFreeStoreType::deallocate (b);
}
FifoFreeStoreWithoutTLS::FifoFreeStoreWithoutTLS ()
: m_pages (GlobalPagedFreeStore::getInstance ())
{
if (m_pages->getPageBytes () < sizeof (Block) + 256)
Throw (Error ().fail (__FILE__, __LINE__, TRANS ("the block size is too small")));
m_active = newBlock ();
}
FifoFreeStoreWithoutTLS::~FifoFreeStoreWithoutTLS ()
{
deleteBlock (m_active);
}
//------------------------------------------------------------------------------
void* FifoFreeStoreWithoutTLS::allocate (const size_t bytes)
{
const size_t actual = sizeof (Header) + bytes;
if (actual > m_pages->getPageBytes ())
Throw (Error ().fail (__FILE__, __LINE__, TRANS ("the memory request was too large")));
Header* h;
for (;;)
{
// Get an active block.
Block* b = m_active;
while (!b)
{
Thread::yield ();
b = m_active;
}
// (*) It is possible for the block to get a final release here
// In this case it will have been put in the garbage, and
// m_active will not match.
// Acquire a reference.
b->addref ();
// Is it still active?
if (m_active == b)
{
// Yes so try to allocate from it.
const Block::Result result = b->allocate (actual, &h);
if (result == Block::success)
{
// Keep the reference and return the allocation.
h->block = b;
break;
}
else if (result == Block::consumed)
{
// Remove block from active.
m_active = 0;
// Take away the reference we added
b->release ();
// Take away the original active reference.
if (b->release ())
deleteBlock (b);
// Install a fresh empty active block.
m_active = newBlock ();
}
else
{
if (b->release ())
deleteBlock (b);
}
// Try again.
}
else
{
// Block became inactive, so release our reference.
b->release ();
// (*) It is possible for this to be a duplicate final release.
}
}
return h + 1;
}
//------------------------------------------------------------------------------
void FifoFreeStoreWithoutTLS::deallocate (void* p)
{
Block* const b = (reinterpret_cast <Header*> (p) - 1)->block;
if (b->release ())
deleteBlock (b);
}

View File

@@ -1,67 +0,0 @@
//------------------------------------------------------------------------------
/*
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_FIFOFREESTOREWITHOUTTLS_BEASTHEADER
#define BEAST_FIFOFREESTOREWITHOUTTLS_BEASTHEADER
#include "beast_GlobalPagedFreeStore.h"
/*============================================================================*/
/**
Lock-free FIFO memory allocator.
This allocator is suitable for use with CallQueue and Listeners. It is
expected that over time, deallocations will occur in roughly the same order
as allocations.
@note This version of the fifo free store uses less memory and doesn't require
thread specific storage. However, it runs slower. The performance
differences are negligible for desktop class applications.
@invariant allocate() and deallocate() are fully concurrent.
@invariant The ABA problem is handled automatically.
@ingroup beast_concurrent
*/
class FifoFreeStoreWithoutTLS
{
public:
explicit FifoFreeStoreWithoutTLS ();
~FifoFreeStoreWithoutTLS ();
void* allocate (const size_t bytes);
static void deallocate (void* const p);
private:
typedef GlobalPagedFreeStore PagedFreeStoreType;
struct Header;
class Block;
inline Block* newBlock ();
static inline void deleteBlock (Block* b);
private:
Block* volatile m_active;
PagedFreeStoreType::Ptr m_pages;
};
#endif

View File

@@ -1,65 +0,0 @@
//------------------------------------------------------------------------------
/*
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_GLOBALFIFOFREESTORE_BEASTHEADER
#define BEAST_GLOBALFIFOFREESTORE_BEASTHEADER
#include "beast_FifoFreeStore.h"
/*============================================================================*/
/**
A @ref FifoFreeStoreType singleton.
@ingroup beast_concurrent
*/
template <class Tag>
class GlobalFifoFreeStore : public RefCountedSingleton <GlobalFifoFreeStore <Tag> >
{
public:
inline void* allocate (size_t bytes)
{
return m_allocator.allocate (bytes);
}
static inline void deallocate (void* const p)
{
FifoFreeStoreType::deallocate (p);
}
static GlobalFifoFreeStore* createInstance ()
{
return new GlobalFifoFreeStore;
}
private:
GlobalFifoFreeStore ()
: RefCountedSingleton <GlobalFifoFreeStore <Tag> >
(SingletonLifetime::persistAfterCreation)
{
}
~GlobalFifoFreeStore ()
{
}
private:
FifoFreeStoreType m_allocator;
};
#endif

View File

@@ -1,42 +0,0 @@
//------------------------------------------------------------------------------
/*
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
{
// Size of a page
//
static const size_t globalPageBytes = 8 * 1024;
}
GlobalPagedFreeStore::GlobalPagedFreeStore ()
: RefCountedSingleton <GlobalPagedFreeStore> (SingletonLifetime::persistAfterCreation)
, m_allocator (globalPageBytes)
{
}
GlobalPagedFreeStore::~GlobalPagedFreeStore ()
{
}
GlobalPagedFreeStore* GlobalPagedFreeStore::createInstance ()
{
return new GlobalPagedFreeStore;
}

View File

@@ -1,61 +0,0 @@
//------------------------------------------------------------------------------
/*
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_GLOBALPAGEDFREESTORE_BEASTHEADER
#define BEAST_GLOBALPAGEDFREESTORE_BEASTHEADER
#include "beast_PagedFreeStore.h"
/*============================================================================*/
/**
A PagedFreeStore singleton.
@ingroup beast_concurrent
*/
class GlobalPagedFreeStore
: public RefCountedSingleton <GlobalPagedFreeStore>
, LeakChecked <GlobalPagedFreeStore>
{
private:
GlobalPagedFreeStore ();
~GlobalPagedFreeStore ();
public:
inline size_t getPageBytes ()
{
return m_allocator.getPageBytes ();
}
inline void* allocate ()
{
return m_allocator.allocate ();
}
static inline void deallocate (void* const p)
{
PagedFreeStore::deallocate (p);
}
static GlobalPagedFreeStore* createInstance ();
private:
PagedFreeStore m_allocator;
};
#endif

View File

@@ -1,60 +0,0 @@
//------------------------------------------------------------------------------
/*
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
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

@@ -1,226 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#define LOG_GC 0
namespace
{
// This is the upper limit on the amount of physical memory an instance of the
// allocator will allow. Going over this limit means that consumers cannot keep
// up with producers, and application logic should be re-examined.
//
// TODO: ENFORCE THIS GLOBALLY? MEASURE IN KILOBYTES AND FORCE KILOBYTE PAGE SIZES
#define HARD_LIMIT 1
const size_t hardLimitMegaBytes = 256;
}
/*
Implementation notes
- There are two pools, the 'hot' pool and the 'cold' pool.
- When a new page is needed we pop from the 'fresh' stack of the hot pool.
- When a page is deallocated it is pushed to the 'garbage' stack of the hot pool.
- Every so often, a garbage collection is performed on a separate thread.
During collection, fresh and garbage are swapped in the cold pool.
Then, the hot and cold pools are atomically swapped.
*/
//------------------------------------------------------------------------------
struct PagedFreeStore::Page : Pages::Node, LeakChecked <Page>
{
explicit Page (PagedFreeStore* const allocator)
: m_allocator (*allocator)
{
}
PagedFreeStore& getAllocator () const
{
return m_allocator;
}
private:
PagedFreeStore& m_allocator;
};
inline void* PagedFreeStore::fromPage (Page* const p)
{
return reinterpret_cast <char*> (p) +
Memory::sizeAdjustedForAlignment (sizeof (Page));
}
inline PagedFreeStore::Page* PagedFreeStore::toPage (void* const p)
{
return reinterpret_cast <Page*> (
(reinterpret_cast <char*> (p) -
Memory::sizeAdjustedForAlignment (sizeof (Page))));
}
//------------------------------------------------------------------------------
PagedFreeStore::PagedFreeStore (const size_t pageBytes)
: m_pageBytes (pageBytes)
, m_pageBytesAvailable (pageBytes - Memory::sizeAdjustedForAlignment (sizeof (Page)))
, m_newPagesLeft (int ((hardLimitMegaBytes * 1024 * 1024) / m_pageBytes))
#if LOG_GC
, m_swaps (0)
#endif
{
m_hot = m_pool1;
m_cold = m_pool2;
startOncePerSecond ();
}
PagedFreeStore::~PagedFreeStore ()
{
endOncePerSecond ();
#if LOG_GC
bassert (!m_used.isSignaled ());
#endif
dispose (m_pool1);
dispose (m_pool2);
#if LOG_GC
bassert (!m_total.isSignaled ());
#endif
}
//------------------------------------------------------------------------------
void* PagedFreeStore::allocate ()
{
Page* page = m_hot->fresh->pop_front ();
if (!page)
{
#if HARD_LIMIT
const bool exhausted = m_newPagesLeft.release ();
if (exhausted)
Throw (Error ().fail (__FILE__, __LINE__,
TRANS ("the limit of memory allocations was reached")));
#endif
void* storage = ::malloc (m_pageBytes);
if (!storage)
Throw (Error ().fail (__FILE__, __LINE__,
TRANS ("a memory allocation failed")));
page = new (storage) Page (this);
#if LOG_GC
m_total.addref ();
#endif
}
#if LOG_GC
m_used.addref ();
#endif
return fromPage (page);
}
void PagedFreeStore::deallocate (void* const p)
{
Page* const page = toPage (p);
PagedFreeStore& allocator = page->getAllocator ();
allocator.m_hot->garbage->push_front (page);
#if LOG_GC
allocator.m_used.release ();
#endif
}
//
// Perform garbage collection.
//
void PagedFreeStore::doOncePerSecond ()
{
// Physically free one page.
// This will reduce the working set over time after a spike.
{
Page* page = m_cold->garbage->pop_front ();
if (page)
{
page->~Page ();
::free (page);
m_newPagesLeft.addref ();
#ifdef LOG_GC
m_total.release ();
#endif
}
}
m_cold->fresh->swap (m_cold->garbage);
// Swap atomically with respect to m_hot
Pool* temp = m_hot;
m_hot = m_cold; // atomic
m_cold = temp;
#if LOG_GC
String s;
s << "swap " << String (++m_swaps);
s << " (" << String (m_used.get ()) << "/"
<< String (m_total.get ()) << " of "
<< String (m_newPagesLeft.get ()) << ")";
Logger::outputDebugString (s);
#endif
}
void PagedFreeStore::dispose (Pages& pages)
{
for (;;)
{
Page* const page = pages.pop_front ();
if (page)
{
page->~Page ();
::free (page);
#if LOG_GC
m_total.release ();
#endif
}
else
{
break;
}
}
}
void PagedFreeStore::dispose (Pool& pool)
{
dispose (pool.fresh);
dispose (pool.garbage);
}

View File

@@ -1,93 +0,0 @@
//------------------------------------------------------------------------------
/*
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_PAGEDFREESTORE_BEASTHEADER
#define BEAST_PAGEDFREESTORE_BEASTHEADER
/*============================================================================*/
/**
Lock-free memory allocator for fixed size pages.
The ABA problem (http://en.wikipedia.org/wiki/ABA_problem) is avoided by
treating freed pages as garbage, and performing a collection every second.
@ingroup beast_concurrent
*/
class PagedFreeStore : private OncePerSecond
{
public:
explicit PagedFreeStore (const size_t pageBytes);
~PagedFreeStore ();
// The available bytes per page is a little bit less
// than requested in the constructor, due to overhead.
//
inline size_t getPageBytes () const
{
return m_pageBytesAvailable;
}
inline void* allocate (const size_t bytes)
{
if (bytes > m_pageBytes)
Throw (Error ().fail (__FILE__, __LINE__, "the size is too large"));
return allocate ();
}
void* allocate ();
static void deallocate (void* const p);
private:
void* newPage ();
void doOncePerSecond ();
private:
struct Page;
typedef LockFreeStack <Page> Pages;
struct Pool
{
CacheLine::Padded <Pages> fresh;
CacheLine::Padded <Pages> garbage;
};
static inline void* fromPage (Page* const p);
static inline Page* toPage (void* const p);
void dispose (Pages& pages);
void dispose (Pool& pool);
private:
const size_t m_pageBytes;
const size_t m_pageBytesAvailable;
CacheLine::Aligned <Pool> m_pool1; // pair of pools
CacheLine::Aligned <Pool> m_pool2;
Pool* volatile m_cold; // pool which is cooling down
Pool* volatile m_hot; // pool we are currently using
AtomicCounter m_newPagesLeft; // limit of system allocations
#if 1
int m_swaps;
AtomicCounter m_total;
AtomicCounter m_used;
#endif
};
#endif

View File

@@ -1,199 +0,0 @@
//------------------------------------------------------------------------------
/*
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_REFERENCECOUNTEDSINGLETON_BEASTHEADER
#define BEAST_REFERENCECOUNTEDSINGLETON_BEASTHEADER
#include "../events/beast_PerformedAtExit.h"
#include "../memory/beast_StaticObject.h"
/**
Thread-safe singleton which comes into existence on first use. Use this
instead of creating objects with static storage duration. These singletons
are automatically reference counted, so if you hold a pointer to it in every
object that depends on it, the order of destruction of objects is assured
to be correct.
class Object must provide the function `Object* Object::createInstance()`
@class RefCountedSingleton
@ingroup beast_core
*/
/** @{ */
class SingletonLifetime
{
// "base classes dependent on a template parameter
// aren't part of lookup." - ville
public:
/**
Construction options for RefCountedSingleton
@ingroup beast_core
*/
enum Lifetime
{
/** Singleton is created on first use and destroyed when
the last reference is removed.
*/
createOnDemand,
/** Like createOnDemand, but after the Singleton is destroyed an
exception will be thrown if an attempt is made to create it again.
*/
createOnDemandOnce,
/** The singleton is created on first use and persists until program exit.
*/
persistAfterCreation
};
};
template <class Object>
class RefCountedSingleton
: public SingletonLifetime
, private PerformedAtExit
{
protected:
typedef SpinLock LockType;
/** Create the singleton.
@param lifetime The lifetime management option.
*/
explicit RefCountedSingleton (Lifetime const lifetime)
: m_lifetime (lifetime)
{
bassert (s_instance == nullptr);
if (m_lifetime == persistAfterCreation)
{
incReferenceCount ();
}
else if (m_lifetime == createOnDemandOnce && *s_created)
{
Throw (Error ().fail (__FILE__, __LINE__));
}
*s_created = true;
}
virtual ~RefCountedSingleton ()
{
bassert (s_instance == nullptr);
}
public:
typedef ReferenceCountedObjectPtr <Object> Ptr;
/** Retrieve a reference to the singleton.
*/
static Ptr getInstance ()
{
Ptr instance;
instance = s_instance;
if (instance == nullptr)
{
LockType::ScopedLockType lock (*s_mutex);
instance = s_instance;
if (instance == nullptr)
{
s_instance = Object::createInstance ();
instance = s_instance;
}
}
return instance;
}
inline void incReferenceCount () noexcept
{
m_refs.addref ();
}
inline void decReferenceCount () noexcept
{
if (m_refs.release ())
destroySingleton ();
}
// Caller must synchronize.
inline bool isBeingReferenced () const
{
return m_refs.isSignaled ();
}
private:
void performAtExit ()
{
if (m_lifetime == SingletonLifetime::persistAfterCreation)
decReferenceCount ();
}
void destroySingleton ()
{
bool destroy;
{
LockType::ScopedLockType lock (*s_mutex);
if (isBeingReferenced ())
{
destroy = false;
}
else
{
destroy = true;
s_instance = 0;
}
}
if (destroy)
{
delete this;
}
}
private:
Lifetime const m_lifetime;
AtomicCounter m_refs;
private:
static Object* s_instance;
static Static::Storage <LockType, RefCountedSingleton <Object> > s_mutex;
static Static::Storage <bool, RefCountedSingleton <Object> > s_created;
};
/** @{ */
template <class Object>
Object* RefCountedSingleton <Object>::s_instance;
template <class Object>
Static::Storage <typename RefCountedSingleton <Object>::LockType, RefCountedSingleton <Object> >
RefCountedSingleton <Object>::s_mutex;
template <class Object>
Static::Storage <bool, RefCountedSingleton <Object> >
RefCountedSingleton <Object>::s_created;
#endif

View File

@@ -1,187 +0,0 @@
//------------------------------------------------------------------------------
/*
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
#include "../threads/beast_SpinDelay.h"
//
// 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

@@ -1,38 +0,0 @@
//------------------------------------------------------------------------------
/*
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

@@ -1,29 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
//#pragma message(BEAST_FILEANDLINE_ "Missing platform-specific implementation")
FPUFlags FPUFlags::getCurrent ()
{
return FPUFlags ();
}
void FPUFlags::setCurrent (const FPUFlags& flags)
{
}

View File

@@ -1,18 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================

View File

@@ -1,176 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
FPUFlags FPUFlags::getCurrent ()
{
unsigned int currentControl;
const unsigned int newControl = 0;
const unsigned int mask = 0;
errno_t result = _controlfp_s (&currentControl, newControl, mask);
if (result != 0)
Throw (std::runtime_error ("error in _controlfp_s"));
FPUFlags flags;
flags.setMaskNaNs ((currentControl & _EM_INVALID) == _EM_INVALID);
flags.setMaskDenormals ((currentControl & _EM_DENORMAL) == _EM_DENORMAL);
flags.setMaskZeroDivides ((currentControl & _EM_ZERODIVIDE) == _EM_ZERODIVIDE);
flags.setMaskOverflows ((currentControl & _EM_OVERFLOW) == _EM_OVERFLOW);
flags.setMaskUnderflows ((currentControl & _EM_UNDERFLOW) == _EM_UNDERFLOW);
//flags.setMaskInexacts ((currentControl & _EM_INEXACT) == _EM_INEXACT);
flags.setFlushDenormals ((currentControl & _DN_FLUSH) == _DN_FLUSH);
flags.setInfinitySigned ((currentControl & _IC_AFFINE) == _IC_AFFINE);
Rounding rounding = roundDown;
switch (currentControl & _MCW_RC)
{
case _RC_CHOP:
rounding = roundChop;
break;
case _RC_UP:
rounding = roundUp;
break;
case _RC_DOWN:
rounding = roundDown;
break;
case _RC_NEAR:
rounding = roundNear;
break;
default:
Throw (std::runtime_error ("unknown rounding in _controlfp_s"));
};
flags.setRounding (rounding);
Precision precision = bits64;
switch (currentControl & _MCW_PC )
{
case _PC_64:
precision = bits64;
break;
case _PC_53:
precision = bits53;
break;
case _PC_24:
precision = bits24;
break;
default:
Throw (std::runtime_error ("unknown precision in _controlfp_s"));
};
flags.setPrecision (precision);
return flags;
}
static void setControl (const FPUFlags::Flag& flag,
unsigned int& newControl,
unsigned int& mask,
unsigned int constant)
{
if (flag.is_set ())
{
mask |= constant;
if (flag.value ())
newControl |= constant;
}
}
void FPUFlags::setCurrent (const FPUFlags& flags)
{
unsigned int newControl = 0;
unsigned int mask = 0;
setControl (flags.getMaskNaNs (), newControl, mask, _EM_INVALID);
setControl (flags.getMaskDenormals (), newControl, mask, _EM_DENORMAL);
setControl (flags.getMaskZeroDivides (), newControl, mask, _EM_ZERODIVIDE);
setControl (flags.getMaskOverflows (), newControl, mask, _EM_OVERFLOW);
setControl (flags.getMaskUnderflows (), newControl, mask, _EM_UNDERFLOW);
//setControl (flags.getMaskInexacts(), newControl, mask, _EM_INEXACT);
setControl (flags.getFlushDenormals (), newControl, mask, _DN_FLUSH);
setControl (flags.getInfinitySigned (), newControl, mask, _IC_AFFINE);
if (flags.getRounding ().is_set ())
{
Rounding rounding = flags.getRounding ().value ();
switch (rounding)
{
case roundChop:
mask |= _MCW_RC;
newControl |= _RC_CHOP;
break;
case roundUp:
mask |= _MCW_RC;
newControl |= _RC_UP;
break;
case roundDown:
mask |= _MCW_RC;
newControl |= _RC_DOWN;
break;
case roundNear:
mask |= _MCW_RC;
newControl |= _RC_NEAR;
break;
}
}
if (flags.getPrecision ().is_set ())
{
switch (flags.getPrecision ().value ())
{
case bits64:
mask |= _MCW_PC;
newControl |= _PC_64;
break;
case bits53:
mask |= _MCW_PC;
newControl |= _PC_53;
break;
case bits24:
mask |= _MCW_PC;
newControl |= _PC_24;
break;
}
}
unsigned int currentControl;
errno_t result = _controlfp_s (&currentControl, newControl, mask);
if (result != 0)
Throw (std::runtime_error ("error in _controlfp_s"));
}

View File

@@ -1,18 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================

View File

@@ -1,153 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
CallQueue::CallQueue (String name)
: m_name (name)
{
}
CallQueue::~CallQueue ()
{
// Someone forget to close the queue.
bassert (m_closed.isSignaled ());
// Can't destroy queue with unprocessed calls.
bassert (m_queue.empty ());
}
bool CallQueue::isAssociatedWithCurrentThread () const
{
return Thread::getCurrentThreadId () == m_id;
}
// Adds a call to the queue of execution.
void CallQueue::queuep (Work* c)
{
// If this goes off it means calls are being made after the
// queue is closed, and probably there is no one around to
// process it.
bassert (!m_closed.isSignaled ());
if (m_queue.push_back (c))
signal ();
}
// Append the Work to the queue. If this call is made from the same
// thread as the last thread that called synchronize(), then the call
// will execute synchronously.
//
void CallQueue::callp (Work* c)
{
queuep (c);
// If we are called on the process thread and we are not
// recursed into doSynchronize, then process the queue. This
// makes calls from the process thread synchronous.
//
// NOTE: The value of isBeingSynchronized is invalid/volatile unless
// this thread is the last process thread.
//
// NOTE: There is a small window of opportunity where we
// might get an undesired synchronization if new thread
// calls synchronize() concurrently.
//
if (isAssociatedWithCurrentThread () &&
m_isBeingSynchronized.trySignal ())
{
doSynchronize ();
m_isBeingSynchronized.reset ();
}
}
bool CallQueue::synchronize ()
{
bool did_something;
// Detect recursion into doSynchronize(), and
// break ties for concurrent calls atomically.
//
if (m_isBeingSynchronized.trySignal ())
{
// Remember this thread.
m_id = Thread::getCurrentThreadId ();
did_something = doSynchronize ();
m_isBeingSynchronized.reset ();
}
else
{
did_something = false;
}
return did_something;
}
// Can still have pending calls, just can't put new ones in.
void CallQueue::close ()
{
m_closed.signal ();
synchronize ();
}
// Process everything in the queue. The list of pending calls is
// acquired atomically. New calls may enter the queue while we are
// processing.
//
// Returns true if any functors were called.
//
bool CallQueue::doSynchronize ()
{
bool did_something;
// Reset since we are emptying the queue. Since we loop
// until the queue is empty, it is possible for us to exit
// this function with an empty queue and signaled state.
//
reset ();
Work* call = m_queue.pop_front ();
if (call)
{
did_something = true;
// This method of processing one at a time has the desired
// side effect of synchronizing nested calls to us from a functor.
//
for (;;)
{
call->operator () ();
delete call;
call = m_queue.pop_front ();
if (call == 0)
break;
}
}
else
{
did_something = false;
}
return did_something;
}

View File

@@ -1,542 +0,0 @@
//------------------------------------------------------------------------------
/*
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_CALLQUEUE_BEASTHEADER
#define BEAST_CALLQUEUE_BEASTHEADER
/*============================================================================*/
/**
A FIFO for calling functors asynchronously.
This object is an alternative to traditional locking techniques used to
implement concurrent systems. Instead of acquiring a mutex to change shared
data, a functor is queued for later execution (usually on another thread). The
execution of the functor applies the transformation to the shared state that
was formerly performed within a lock (i.e. CriticalSection).
For read operations on shared data, instead of acquiring a mutex and
accessing the data directly, copies are made (one for each thread), and the
thread accesses its copy without acquiring a lock. One thread owns the master
copy of the shared state. Requests for changing shared state are made by other
threads by posting functors to the master thread's CallQueue. The master
thread notifies other threads of changes by posting functors to their
respective associated CallQueue, using the Listeners interface.
The purpose of the functor is to encapsulate one mutation of shared state to
guarantee progress towards a consensus of the concurrent data among
participating threads. Functors should execute quickly, ideally in constant
time. Dynamically allocated objects of class type passed as functor parameters
should, in general, be reference counted. The ConcurrentObject class is ideal
for meeting this requirement, and has the additional benefit that the workload
of deletion is performed on a separate, provided thread. This queue is not a
replacement for a thread pool or job queue type system.
A CallQueue is considered signaled when one or more functors are present.
Functors are executed during a call to synchronize(). The operation of
executing functors via the call to synchronize() is called synchronizing
the queue. It can more generally be thought of as synchronizing multiple
copies of shared data between threads.
Although there is some extra work required to set up and maintain this
system, the benefits are significant. Since shared data is only synchronized
at well defined times, the programmer can reason and make strong statements
about the correctness of the concurrent system. For example, if an
AudioIODeviceCallback synchronizes the CallQueue only at the beginning of its
execution, it is guaranteed that shared data will remain the same throughout
the remainder of the function.
Because shared data is accessed for reading without a lock, upper bounds
on the run time performance can easily be calculated and assured. Compare
this with the use of a mutex - the run time performance experiences a
combinatorial explosion of possibilities depending on the complex interaction
of multiple threads.
Since a CallQueue is almost always used to invoke parameterized member
functions of objects, the call() function comes in a variety of convenient
forms to make usage easy:
@code
void func1 (int);
struct Object
{
void func2 (void);
void func3 (String name);
static void func4 ();
};
CallQueue fifo ("Example");
void example ()
{
fifo.call (func1, 42); // same as: func1 (42)
Object* object = new Object;
fifo.call (&Object::func2, object); // same as: object->func2 ()
fifo.call (&Object::func3, // same as: object->funcf ("Label")
object,
"Label");
fifo.call (&Object::func4); // even static members can be called.
fifo.callf (bind (&Object::func2, // same as: object->func2 ()
object));
}
@endcode
@invariant Functors can be added from any thread at any time, to any queue
which is not closed.
@invariant When synchronize() is called, functors are called and deleted.
@invariant The thread from which synchronize() is called is considered the
thread associated with the CallQueue.
@invariant Functors queued by the same thread always execute in the same
order they were queued.
@invariant Functors are guaranteed to execute. It is an error if the
CallQueue is deleted while there are functors in it.
Normally, you will not use CallQueue directly, but one of its subclasses
instead. The CallQueue is one of a handful of objects that work together to
implement this system of concurrent data access.
For performance considerations, this implementation is wait-free for
producers and mostly wait-free for consumers. It also uses a lock-free
and wait-free (in the fast path) custom memory allocator.
@see GuiCallQueue, ManualCallQueue, MessageThread, ThreadWithCallQueue
@ingroup beast_concurrent
*/
class CallQueue
{
public:
//============================================================================
/** Type of allocator to use.
@internal
*/
typedef FifoFreeStoreType AllocatorType;
/** Abstract nullary functor in a @ref CallQueue.
Custom implementations may derive from this object for efficiency instead
of using the automatic binding functions.
*/
class Work : public LockFreeQueue <Work>::Node,
public AllocatedBy <AllocatorType>
{
public:
virtual ~Work () { }
/** Calls the functor.
This executes during the queue's call to synchronize().
*/
virtual void operator () () = 0;
};
//============================================================================
/** Create the CallQueue.
The queue starts out open and empty.
@param name A string to identify the queue during debugging.
*/
explicit CallQueue (String name);
/** Destroy the CallQueue.
@invariant Destroying a queue that contains functors results in undefined
behavior.
@note It is customary to call close() on the CallQueue early in the
shutdown process to catch functors going into the queue late.
*/
virtual ~CallQueue ();
//============================================================================
/** Add a functor and possibly synchronize.
Use this when you want to perform the bind yourself.
@param f The functor to add, typically the return value of a call
to bind().
@see call
*/
template <class Functor>
void callf (Functor f)
{
callp (new (m_allocator) CallType <Functor> (f));
}
/** Add a function call and possibly synchronize.
Parameters are evaluated immediately and added to the queue as a packaged
functor. If the current thread of execution is the same as the thread
associated with the CallQueue, synchronize() is called automatically. This
behavior can be avoided by using queue() instead.
@param f The function to call followed by up to eight parameters,
evaluated immediately. The parameter list must match the function
signature. For class member functions, the first argument must be a
pointer to the class object.
@see queue
@todo Provide an example of when synchronize() is needed in call().
*/
/** @{ */
#if BEAST_VARIADIC_MAX >= 1
template <class Fn>
void call (Fn f)
{
callf (bind (f));
}
#endif
#if BEAST_VARIADIC_MAX >= 2
template <class Fn, class T1>
void call (Fn f, T1 t1)
{
callf (bind (f, t1));
}
#endif
#if BEAST_VARIADIC_MAX >= 3
template <class Fn, class T1, class T2>
void call (Fn f, T1 t1, T2 t2)
{
callf (bind (f, t1, t2));
}
#endif
#if BEAST_VARIADIC_MAX >= 4
template <class Fn, class T1, class T2, class T3>
void call (Fn f, T1 t1, T2 t2, T3 t3)
{
callf (bind (f, t1, t2, t3));
}
#endif
#if BEAST_VARIADIC_MAX >= 5
template <class Fn, class T1, class T2, class T3, class T4>
void call (Fn f, T1 t1, T2 t2, T3 t3, T4 t4)
{
callf (bind (f, t1, t2, t3, t4));
}
#endif
#if BEAST_VARIADIC_MAX >= 6
template <class Fn, class T1, class T2, class T3, class T4, class T5>
void call (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
callf (bind (f, t1, t2, t3, t4, t5));
}
#endif
#if BEAST_VARIADIC_MAX >= 7
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6>
void call (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
{
callf (bind (f, t1, t2, t3, t4, t5, t6));
}
#endif
#if BEAST_VARIADIC_MAX >= 8
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
void call (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
{
callf (bind (f, t1, t2, t3, t4, t5, t6, t7));
}
#endif
#if BEAST_VARIADIC_MAX >= 9
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
void call (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
{
callf (bind (f, t1, t2, t3, t4, t5, t6, t7, t8));
}
#endif
/** @} */
/** Add a functor without synchronizing.
Use this when you want to perform the bind yourself.
@param f The functor to add, typically the return value of a call
to bind().
@see queue
*/
template <class Functor>
void queuef (Functor f)
{
queuep (new (m_allocator) CallType <Functor> (f));
}
/** Add a function call without synchronizing.
Parameters are evaluated immediately, then the resulting functor is added
to the queue. This is used to postpone the call to synchronize() when
there would be adverse side effects to executing the function immediately.
In this example, we use queue() instead of call() to avoid a deadlock:
@code
struct SharedState; // contains data shared between threads
ConcurrentState <SharedState> sharedState;
void stateChanged ()
{
ConcurrentState <SharedState>::ReadAccess state (sharedState);
// (read state)
}
CallQueue fifo;
void changeState ()
{
ConcurrentState <State>::WriteAccess state (sharedState);
// (read and write state)
fifo.call (&stateChanged); // BUG: DEADLOCK because of the implicit synchronize().
fifo.queue (&stateChanged); // Okay, synchronize() will be called later,
// after the write lock is released.
}
@endcode
@param f The function to call followed by up to eight parameters,
evaluated immediately. The parameter list must match the
function signature. For non-static class member functions,
the first argument must be a pointer an instance of the class.
@see call
*/
/** @{ */
#if BEAST_VARIADIC_MAX >= 1
template <class Fn>
void queue (Fn f)
{
queuef (bind (f));
}
#endif
#if BEAST_VARIADIC_MAX >= 2
template <class Fn, class T1>
void queue (Fn f, T1 t1)
{
queuef (bind (f, t1));
}
#endif
#if BEAST_VARIADIC_MAX >= 3
template <class Fn, class T1, class T2>
void queue (Fn f, T1 t1, T2 t2)
{
queuef (bind (f, t1, t2));
}
#endif
#if BEAST_VARIADIC_MAX >= 4
template <class Fn, class T1, class T2, class T3>
void queue (Fn f, T1 t1, T2 t2, T3 t3)
{
queuef (bind (f, t1, t2, t3));
}
#endif
#if BEAST_VARIADIC_MAX >= 5
template <class Fn, class T1, class T2, class T3, class T4>
void queue (Fn f, T1 t1, T2 t2, T3 t3, T4 t4)
{
queuef (bind (f, t1, t2, t3, t4));
}
#endif
#if BEAST_VARIADIC_MAX >= 6
template <class Fn, class T1, class T2, class T3, class T4, class T5>
void queue (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
queuef (bind (f, t1, t2, t3, t4, t5));
}
#endif
#if BEAST_VARIADIC_MAX >= 7
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6>
void queue (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
{
queuef (bind (f, t1, t2, t3, t4, t5, t6));
}
#endif
#if BEAST_VARIADIC_MAX >= 8
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
void queue (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
{
queuef (bind (f, t1, t2, t3, t4, t5, t6, t7));
}
#endif
#if BEAST_VARIADIC_MAX >= 9
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
void queue (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
{
queuef (bind (f, t1, t2, t3, t4, t5, t6, t7, t8));
}
#endif
/** @} */
protected:
//============================================================================
/** Synchronize the queue.
A synchronize operation calls all functors in the queue. If a functor
causes additional functors to be added, they are eventually executed
before synchronize() returns. Derived class call this when the queue is
signaled, and optionally at any other time. Calling this function from
more than one thread simultaneously is undefined.
@return true if any functors were executed.
*/
bool synchronize ();
/** Close the queue.
Functors may not be added after this routine is called. This is used for
diagnostics, to track down spurious calls during application shutdown
or exit. Derived classes may call this if the appropriate time is known.
The queue is synchronized after it is closed.
*/
void close ();
/** Called when the queue becomes signaled.
A queue is signaled on the transition from empty to non-empty. Derived
classes implement this function to perform a notification so that
synchronize() will be called. For example, by triggering a WaitableEvent.
@note Due to the implementation the queue can remain signaled for one
extra cycle. This does not happen under load and is not an issue
in practice.
*/
virtual void signal () = 0;
/** Called when the queue is reset.
A queue is reset when it was previously signaled and then becomes empty
as a result of a call to synchronize.
*/
virtual void reset () = 0;
public:
//============================================================================
/** Add a raw call.
@internal
Custom implementations use this to control the allocation.
@param c The call to add. The memory must come from the allocator.
*/
void callp (Work* c);
/** Queue a raw call.
Custom implementations use this to control the allocation.
@param c The call to add. The memory must come from the allocator.
*/
void queuep (Work* c);
/** Retrieve the allocator.
@return The allocator to use when allocating a raw Work object.
*/
inline AllocatorType& getAllocator ()
{
return m_allocator;
}
/** See if the caller is on the association thread.
@return `true` if the calling thread of execution is associated with the
queue.
*/
bool isAssociatedWithCurrentThread () const;
/** See if the queue is being synchronized.
This is used for diagnostics.
@note This must be called from the associated thread or else the return
value is undefined.
@return `true` if the call stack contains synchronize() for this queue.
*/
bool isBeingSynchronized () const
{
return m_isBeingSynchronized.isSignaled ();
}
private:
template <class Functor>
class CallType : public Work
{
public:
explicit CallType (Functor f) : m_f (f) { }
void operator () ()
{
m_f ();
}
private:
Functor m_f;
};
bool doSynchronize ();
private:
String const m_name;
Thread::ThreadID m_id;
LockFreeQueue <Work> m_queue;
AtomicFlag m_closed;
AtomicFlag m_isBeingSynchronized;
AllocatorType m_allocator;
};
#endif

View File

@@ -1,76 +0,0 @@
//------------------------------------------------------------------------------
/*
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 ConcurrentObject::Deleter : private ThreadWithCallQueue::EntryPoints
{
private:
Deleter () : m_thread ("AsyncDeleter")
{
m_thread.start (this);
}
~Deleter ()
{
m_thread.stop (true);
}
void performAtExit ()
{
//delete this;
}
static void doDelete (ConcurrentObject* sharedObject)
{
delete sharedObject;
}
public:
void destroy (ConcurrentObject* sharedObject)
{
if (m_thread.isAssociatedWithCurrentThread ())
delete sharedObject;
else
m_thread.call (&Deleter::doDelete, sharedObject);
}
static Deleter& getInstance ()
{
static Deleter instance;
return instance;
}
private:
ThreadWithCallQueue m_thread;
};
//------------------------------------------------------------------------------
ConcurrentObject::ConcurrentObject ()
{
}
ConcurrentObject::~ConcurrentObject ()
{
}
void ConcurrentObject::destroyConcurrentObject ()
{
Deleter::getInstance ().destroy (this);
}

View File

@@ -1,79 +0,0 @@
//------------------------------------------------------------------------------
/*
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_CONCURRENTOBJECT_BEASTHEADER
#define BEAST_CONCURRENTOBJECT_BEASTHEADER
/*============================================================================*/
/**
A reference counted object with overridable destroy behavior.
This is a reference counted object compatible with
ReferenceCountedObjectPtr. When the last reference is removed, the
object is queued for deletion on a separate, provided thread. On
program exit the thread will clean itself up - no other action is
required.
This class is useful for offloading the deletion work of "deep" objects
shared by multiple threads: objects containing complex members, or a
hierarchy of allocated structures. For example, a ValueTree. The problem
of performing heavyweight memory or cleanup operations from either an
AudioIODeviceCallback or the message thread is avoided.
The deletion behavior can be overriden by providing a replacement
for destroyConcurrentObject().
@ingroup beast_concurrent
*/
class ConcurrentObject : Uncopyable
{
public:
inline void incReferenceCount () noexcept
{
m_refs.addref ();
}
inline void decReferenceCount () noexcept
{
if (m_refs.release ())
destroyConcurrentObject ();
}
protected:
ConcurrentObject ();
virtual ~ConcurrentObject ();
/** Delete the object.
This function is called when the reference count drops to zero. The
default implementation performs the delete on a separate, provided thread
that cleans up after itself on exit.
*/
virtual void destroyConcurrentObject ();
protected:
class Deleter;
private:
AtomicCounter m_refs;
};
#endif

View File

@@ -1,298 +0,0 @@
//------------------------------------------------------------------------------
/*
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_CONCURRENTSTATE_BEASTHEADER
#define BEAST_CONCURRENTSTATE_BEASTHEADER
/*============================================================================*/
/**
Structured access to a shared state.
This template wraps an object containing members representing state
information shared between multiple threads of execution, where any thread
may need to read or write as needed. Synchronized access to the concurrent
state is enforced at compile time through strongly typed accessor classes.
This interface design facilitates source code pattern matching to find all
areas where a concurrent state is accessed.
There are three types of access:
- ReadAccess
Allows read access to the underlying object as `const`. ReadAccess may be
granted to one or more threads simultaneously. If one or more threads have
ReadAccess, requests to obtain WriteAccess are blocked.
- WriteAccess
Allows exclusive read/write access the underlying object. A WriteAccess
request blocks until all existing ReadAccess and WriteAccess requests are
released. While a WriteAccess exists, requests for ReadAccess will block.
- UnlockedAccess
Allows read access to the underlying object without using the lock. This
can be helpful when designing concurrent structures through composition.
It also makes it easier to search for places in code which use unlocked
access.
This code example demonstrates various forms of access to a ConcurrentState:
@code
struct SharedData
{
int value1;
String value2;
};
typedef ConcurrentState <SharedData> SharedState;
SharedState sharedState;
void readExample ()
{
SharedState::ReadAccess state (sharedState);
print (state->value1); // read access
print (state->value2); // read access
state->value1 = 42; // write disallowed: compile error
}
void writeExample ()
{
SharedState::WriteAccess state (sharedState);
state->value2 = "Label"; // write access
}
@endcode
Forwarding constructors with up to eight parameters are provided. This lets
you write constructors into the underlying data object. For example:
@code
struct SharedData
{
explicit SharedData (int numSlots)
{
m_array.reserve (numSlots);
}
std::vector <AudioSampleBuffer*> m_array;
};
// Construct SharedData with one parameter
ConcurrentState <SharedData> sharedState (16);
@endcode
@param Object The type of object to encapsulate.
@warning Recursive calls are not supported. It is generally not possible for
a thread of execution to acquire write access while it already has
read access. Such an attempt will result in undefined behavior. Calling into
unknown code while holding a lock can cause deadlock. See
@ref CallQueue::queue().
@ingroup beast_concurrent
*/
template <class Object>
class ConcurrentState : Uncopyable
{
public:
class ReadAccess;
class WriteAccess;
class UnlockedAccess;
/** Create a concurrent state.
Up to 8 parameters can be specified in the constructor. These parameters
are forwarded to the corresponding constructor in Object. If no
constructor in Object matches the parameter list, a compile error is
generated.
*/
/** @{ */
ConcurrentState () { }
template <class T1>
explicit ConcurrentState (T1 t1)
: m_obj (t1) { }
template <class T1, class T2>
ConcurrentState (T1 t1, T2 t2)
: m_obj (t1, t2) { }
template <class T1, class T2, class T3>
ConcurrentState (T1 t1, T2 t2, T3 t3)
: m_obj (t1, t2, t3) { }
template <class T1, class T2, class T3, class T4>
ConcurrentState (T1 t1, T2 t2, T3 t3, T4 t4)
: m_obj (t1, t2, t3, t4) { }
template <class T1, class T2, class T3, class T4, class T5>
ConcurrentState (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
: m_obj (t1, t2, t3, t4, t5) { }
template <class T1, class T2, class T3, class T4, class T5, class T6>
ConcurrentState (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
: m_obj (t1, t2, t3, t4, t5, t6) { }
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
ConcurrentState (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) : m_obj (t1, t2, t3, t4, t5, t6, t7) { }
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
ConcurrentState (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
: m_obj (t1, t2, t3, t4, t5, t6, t7, t8) { }
/** @} */
private:
typedef ReadWriteMutex ReadWriteMutexType;
Object m_obj;
ReadWriteMutexType m_mutex;
};
//------------------------------------------------------------------------------
/** Unlocked access to a ConcurrentState.
Use sparingly.
*/
template <class Object>
class ConcurrentState <Object>::UnlockedAccess : Uncopyable
{
public:
explicit UnlockedAccess (ConcurrentState const& state)
: m_state (state)
{
}
Object const& getObject () const
{
return m_state.m_obj;
}
Object const& operator* () const
{
return getObject ();
}
Object const* operator-> () const
{
return &getObject ();
}
private:
ConcurrentState const& m_state;
};
//------------------------------------------------------------------------------
/** Read only access to a ConcurrentState */
template <class Object>
class ConcurrentState <Object>::ReadAccess : Uncopyable
{
public:
/** Create a ReadAccess from the specified ConcurrentState */
explicit ReadAccess (ConcurrentState const volatile& state)
: m_state (const_cast <ConcurrentState const&> (state))
, m_lock (m_state.m_mutex)
{
}
/** Obtain a read only reference to Object */
Object const& getObject () const
{
return m_state.m_obj;
}
/** Obtain a read only reference to Object */
Object const& operator* () const
{
return getObject ();
}
/** Obtain a read only smart pointer to Object */
Object const* operator-> () const
{
return &getObject ();
}
private:
ConcurrentState const& m_state;
ReadWriteMutexType::ScopedReadLockType m_lock;
};
//------------------------------------------------------------------------------
/** Read/write access to a ConcurrentState */
template <class Object>
class ConcurrentState <Object>::WriteAccess : Uncopyable
{
public:
explicit WriteAccess (ConcurrentState& state)
: m_state (state)
, m_lock (m_state.m_mutex)
{
}
/** Obtain a read only reference to Object */
Object const* getObject () const
{
return m_state.m_obj;
}
/** Obtain a read only reference to Object */
Object const& operator* () const
{
return getObject ();
}
/** Obtain a read only smart pointer to Object */
Object const* operator-> () const
{
return &getObject ();
}
/** Obtain a read/write pointer to Object */
Object& getObject ()
{
return m_state.m_obj;
}
/** Obtain a read/write reference to Object */
Object& operator* ()
{
return getObject ();
}
/** Obtain a read/write smart pointer to Object */
Object* operator-> ()
{
return &getObject ();
}
private:
ConcurrentState& m_state;
ReadWriteMutexType::ScopedWriteLockType m_lock;
};
#endif

View File

@@ -1,49 +0,0 @@
//------------------------------------------------------------------------------
/*
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_GLOBALTHREADGROUP_BEASTHEADER
#define BEAST_GLOBALTHREADGROUP_BEASTHEADER
/*============================================================================*/
/**
A ThreadGroup singleton.
@see ThreadGroup
@ingroup beast_concurrent
*/
class GlobalThreadGroup : public ThreadGroup,
public RefCountedSingleton <GlobalThreadGroup>
{
private:
friend class RefCountedSingleton <GlobalThreadGroup>;
GlobalThreadGroup ()
: RefCountedSingleton <GlobalThreadGroup> (
SingletonLifetime::persistAfterCreation)
{
}
static GlobalThreadGroup* createInstance ()
{
return new GlobalThreadGroup;
}
};
#endif

View File

@@ -1,225 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
InterruptibleThread::ThreadHelper::ThreadHelper (String name,
InterruptibleThread* owner)
: Thread (name)
, m_owner (owner)
{
}
InterruptibleThread* InterruptibleThread::ThreadHelper::getOwner () const
{
return m_owner;
}
void InterruptibleThread::ThreadHelper::run ()
{
m_owner->run ();
}
//------------------------------------------------------------------------------
InterruptibleThread::InterruptibleThread (String name)
: m_thread (name, this)
, m_entryPoint (nullptr)
, m_state (stateRun)
{
}
InterruptibleThread::~InterruptibleThread ()
{
m_runEvent.signal ();
join ();
}
void InterruptibleThread::start (EntryPoint* const entryPoint)
{
m_entryPoint = entryPoint;
m_thread.startThread ();
// Prevent data race with member variables
//
m_runEvent.signal ();
}
void InterruptibleThread::join ()
{
m_thread.stopThread (-1);
}
bool InterruptibleThread::wait (int milliSeconds)
{
// Can only be called from the corresponding thread of execution.
//
bassert (isTheCurrentThread ());
bool interrupted = false;
for (;;)
{
bassert (m_state != stateWait);
// See if we are interrupted
//
if (m_state.tryChangeState (stateInterrupt, stateRun))
{
// We were interrupted, state is changed to Run. Caller must run now.
//
interrupted = true;
break;
}
else if (m_state.tryChangeState (stateRun, stateWait) ||
m_state.tryChangeState (stateReturn, stateWait))
{
// Transitioned to wait. Caller must wait now.
//
interrupted = false;
break;
}
}
if (!interrupted)
{
interrupted = m_thread.wait (milliSeconds);
if (!interrupted)
{
if (m_state.tryChangeState (stateWait, stateRun))
{
interrupted = false;
}
else
{
bassert (m_state == stateInterrupt);
interrupted = true;
}
}
}
return interrupted;
}
void InterruptibleThread::interrupt ()
{
for (;;)
{
int const state = m_state;
if (state == stateInterrupt ||
state == stateReturn ||
m_state.tryChangeState (stateRun, stateInterrupt))
{
// Thread will see this at next interruption point.
//
break;
}
else if (m_state.tryChangeState (stateWait, stateRun))
{
m_thread.notify ();
break;
}
}
}
bool InterruptibleThread::interruptionPoint ()
{
// Can only be called from the thread of execution.
//
bassert (isTheCurrentThread ());
if (m_state == stateWait)
{
// It is impossible for this function to be called while in the wait state.
//
Throw (Error ().fail (__FILE__, __LINE__));
}
else if (m_state == stateReturn)
{
// If this goes off it means the thread called the
// interruption a second time after already getting interrupted.
//
Throw (Error ().fail (__FILE__, __LINE__));
}
bool const interrupted = m_state.tryChangeState (stateInterrupt, stateRun);
return interrupted;
}
InterruptibleThread::id InterruptibleThread::getId () const
{
return m_threadId;
}
bool InterruptibleThread::isTheCurrentThread () const
{
return m_thread.getCurrentThreadId () == m_threadId;
}
void InterruptibleThread::setPriority (int priority)
{
m_thread.setPriority (priority);
}
InterruptibleThread* InterruptibleThread::getCurrentThread ()
{
InterruptibleThread* result = nullptr;
Thread* const thread = Thread::getCurrentThread ();
if (thread != nullptr)
{
ThreadHelper* const helper = dynamic_cast <ThreadHelper*> (thread);
bassert (helper != nullptr);
result = helper->getOwner ();
}
return result;
}
void InterruptibleThread::run ()
{
m_threadId = m_thread.getThreadId ();
m_runEvent.wait ();
//CatchAny (m_function);
m_entryPoint->threadRun ();
}
//------------------------------------------------------------------------------
bool CurrentInterruptibleThread::interruptionPoint ()
{
bool interrupted = false;
InterruptibleThread* const interruptibleThread (InterruptibleThread::getCurrentThread ());
bassert (interruptibleThread != nullptr);
interrupted = interruptibleThread->interruptionPoint ();
return interrupted;
}

View File

@@ -1,188 +0,0 @@
//------------------------------------------------------------------------------
/*
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_INTERRUPTIBLETHREAD_BEASTHEADER
#define BEAST_INTERRUPTIBLETHREAD_BEASTHEADER
#include "../diagnostic/beast_SafeBool.h"
#include "../functor/beast_Function.h"
//==============================================================================
/**
A thread with soft interruption support.
The thread must periodically call interruptionPoint(), which returns `true`
the first time an interruption has occurred since the last call to
interruptionPoint().
To create a thread, derive your class from InterruptibleThread::EntryPoint
and implement the threadRun() function. Then, call run() with your object.
@ingroup beast_core
*/
class InterruptibleThread
{
public:
/** InterruptibleThread entry point.
*/
class EntryPoint
{
public:
virtual ~EntryPoint () { }
virtual void threadRun () = 0;
};
public:
typedef Thread::ThreadID id;
/** Construct an interruptible thread.
The name is used for debugger diagnostics.
@param name The name of the thread.
*/
explicit InterruptibleThread (String name);
/** Destroy the interruptible thread.
This will signal an interrupt and wait until the thread exits.
*/
~InterruptibleThread ();
/** Start the thread.
*/
void start (EntryPoint* const entryPoint);
/** Wait for the thread to exit.
*/
void join ();
/** Wait for interrupt or timeout.
This call blocks until the thread is interrupted, or until the timeout
expires if milliSeconds is non-negative.
May only be called by the thread of execution.
@param milliSeconds The amount of time to wait. Negative values mean
no timeout.
@return `true` if the interrupt occurred, or `false` if the
timeout expired.
*/
bool wait (int milliSeconds = -1);
/** Interrupt the thread of execution.
This can be called from any thread.
*/
void interrupt ();
/** Determine if an interruption is requested.
After the function returns `true`, the interrupt status is cleared.
Subsequent calls will return `false` until another interrupt is requested.
May only be called by the thread of execution.
@see CurrentInterruptibleThread::interruptionPoint
@return `true` if an interrupt was requested.
*/
bool interruptionPoint ();
/** Get the ID of the associated thread.
@return The ID of the thread.
*/
id getId () const;
/** Determine if this is the thread of execution.
@note The return value is undefined if the thread is not running.
@return `true` if the caller is this thread of execution.
*/
bool isTheCurrentThread () const;
/** Adjust the thread priority.
@note This only affects some platforms.
@param priority A number from 0..10
*/
void setPriority (int priority);
/** Get the InterruptibleThread for the thread of execution.
This will return `nullptr` when called from the message thread, or from
a thread of execution that is not an InterruptibleThread.
*/
static InterruptibleThread* getCurrentThread ();
private:
class ThreadHelper : public Thread
{
public:
ThreadHelper (String name, InterruptibleThread* owner);
InterruptibleThread* getOwner () const;
void run ();
private:
InterruptibleThread* const m_owner;
};
void run ();
ThreadHelper m_thread;
EntryPoint* m_entryPoint;
Function <void (void)> m_function;
WaitableEvent m_runEvent;
id m_threadId;
enum
{
stateRun,
stateInterrupt,
stateReturn,
stateWait
};
AtomicState m_state;
};
//------------------------------------------------------------------------------
/** Global operations on the current InterruptibleThread.
Calling members of the class from a thread of execution which is not an
InterruptibleThread results in undefined behavior.
*/
class CurrentInterruptibleThread
{
public:
/** Call the current thread's interrupt point function.
*/
static bool interruptionPoint ();
};
#endif

View File

@@ -1,765 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
// CallQueue item to process a Call for a particular listener.
// This is used to avoid bind overhead.
//
class ListenersBase::CallWork : public CallQueue::Work
{
public:
inline CallWork (ListenersBase::Call* const c, void* const listener)
: m_call (c), m_listener (listener)
{
}
void operator () ()
{
m_call->operator () (m_listener);
}
private:
ListenersBase::Call::Ptr m_call;
void* const m_listener;
};
//------------------------------------------------------------------------------
// CallQueue item to process a Call for a group.
// This is used to avoid bind overhead.
//
class ListenersBase::GroupWork : public CallQueue::Work
{
public:
inline GroupWork (Group* group,
ListenersBase::Call* c,
const timestamp_t timestamp)
: m_group (group)
, m_call (c)
, m_timestamp (timestamp)
{
}
void operator () ()
{
m_group->do_call (m_call, m_timestamp);
}
private:
Group::Ptr m_group;
ListenersBase::Call::Ptr m_call;
const timestamp_t m_timestamp;
};
//------------------------------------------------------------------------------
// CallQueue item to process a call for a particular listener.
// This is used to avoid bind overhead.
//
class ListenersBase::GroupWork1 : public CallQueue::Work
{
public:
inline GroupWork1 (Group* group,
ListenersBase::Call* c,
const timestamp_t timestamp,
void* const listener)
: m_group (group)
, m_call (c)
, m_timestamp (timestamp)
, m_listener (listener)
{
}
void operator () ()
{
m_group->do_call1 (m_call, m_timestamp, m_listener);
}
private:
Group::Ptr m_group;
ListenersBase::Call::Ptr m_call;
const timestamp_t m_timestamp;
void* const m_listener;
};
//------------------------------------------------------------------------------
// A Proxy maintains a list of Entry.
// Each Entry holds a group and the current Call (which can be updated).
//
struct ListenersBase::Proxy::Entry : Entries::Node,
ReferenceCountedObject,
AllocatedBy <AllocatorType>
{
typedef ReferenceCountedObjectPtr <Entry> Ptr;
explicit Entry (Group* g)
: group (g)
{
}
~Entry ()
{
bassert (call.get () == 0);
}
Group::Ptr group;
AtomicPointer <Call> call;
};
//------------------------------------------------------------------------------
// A Group maintains a list of Entry.
//
struct ListenersBase::Group::Entry : List <Entry>::Node,
AllocatedBy <AllocatorType>
{
Entry (void* const l, const timestamp_t t)
: listener (l)
, timestamp (t)
{
}
void* const listener;
const timestamp_t timestamp;
};
//------------------------------------------------------------------------------
//
// Group
//
//------------------------------------------------------------------------------
// - A list of listeners associated with the same CallQueue.
//
// - The list is only iterated on the CallQueue's thread.
//
// - It is safe to add or remove listeners from the group
// at any time.
//
ListenersBase::Group::Group (CallQueue& callQueue)
: m_fifo (callQueue)
, m_listener (0)
{
}
ListenersBase::Group::~Group ()
{
// If this goes off it means a Listener forgot to remove itself.
bassert (m_list.empty ());
// shouldn't be deleting group during a call
bassert (m_listener == 0);
}
// Add the listener with the given timestamp.
// The listener will only get calls with higher timestamps.
// The caller must prevent duplicates.
//
void ListenersBase::Group::add (void* listener,
const timestamp_t timestamp,
AllocatorType& allocator)
{
ReadWriteMutex::ScopedWriteLockType lock (m_mutex);
bassert (!contains (listener));
// Should never be able to get here while in call()
bassert (m_listener == 0);
// Add the listener and remember the time stamp so we don't
// send it calls that were queued earlier than the add().
m_list.push_back (*new (allocator) Entry (listener, timestamp));
}
// Removes the listener from the group if it exists.
// Returns true if the listener was removed.
//
bool ListenersBase::Group::remove (void* listener)
{
bool found = false;
ReadWriteMutex::ScopedWriteLockType lock (m_mutex);
// Should never be able to get here while in call()
bassert (m_listener == 0);
for (List <Entry>::iterator iter = m_list.begin (); iter != m_list.end (); ++iter)
{
Entry* entry = & (*iter);
if (entry->listener == listener)
{
m_list.erase (m_list.iterator_to (*entry));
delete entry;
found = true;
break;
}
}
return found;
}
// Used for assertions.
// The caller must synchronize.
//
bool ListenersBase::Group::contains (void* const listener) /*const*/
{
for (List <Entry>::iterator iter = m_list.begin (); iter != m_list.end (); iter++)
if (iter->listener == listener)
return true;
return false;
}
void ListenersBase::Group::call (Call* const c, const timestamp_t timestamp)
{
bassert (!empty ());
m_fifo.callp (new (m_fifo.getAllocator ()) GroupWork (this, c, timestamp));
}
void ListenersBase::Group::queue (Call* const c, const timestamp_t timestamp)
{
bassert (!empty ());
m_fifo.queuep (new (m_fifo.getAllocator ()) GroupWork (this, c, timestamp));
}
void ListenersBase::Group::call1 (Call* const c,
const timestamp_t timestamp,
void* const listener)
{
m_fifo.callp (new (m_fifo.getAllocator ()) GroupWork1 (
this, c, timestamp, listener));
}
void ListenersBase::Group::queue1 (Call* const c,
const timestamp_t timestamp,
void* const listener)
{
m_fifo.queuep (new (m_fifo.getAllocator ()) GroupWork1 (
this, c, timestamp, listener));
}
// Queues a reference to the Call on the thread queue of each listener
// that is currently in our list. The thread queue must be in the
// stack's call chain, either directly from CallQueue::synchronize(),
// or from Proxy::do_call() called from CallQueue::synchronize().
//
void ListenersBase::Group::do_call (Call* const c, const timestamp_t timestamp)
{
if (!empty ())
{
ReadWriteMutex::ScopedReadLockType lock (m_mutex);
// Recursion not allowed.
bassert (m_listener == 0);
// The body of the loop MUST NOT cause listeners to get called.
// Therefore, we don't have to worry about listeners removing
// themselves while iterating the list.
//
for (List <Entry>::iterator iter = m_list.begin (); iter != m_list.end ();)
{
Entry* entry = & (*iter++);
// Since it is possible for a listener to be added after a
// Call gets queued but before it executes, this prevents listeners
// from seeing Calls created before they were added.
//
if (timestamp > entry->timestamp)
{
m_listener = entry->listener;
// The thread queue's synchronize() function MUST be in our call
// stack to guarantee that these calls will not execute immediately.
// They will be handled by the tail recusion unrolling in the
// thread queue.
bassert (m_fifo.isBeingSynchronized ());
m_fifo.callp (new (m_fifo.getAllocator ()) CallWork (c, m_listener));
m_listener = 0;
}
}
}
else
{
// last listener was removed before we got here,
// and the parent listener list may have been deleted.
}
}
void ListenersBase::Group::do_call1 (Call* const c, const timestamp_t timestamp,
void* const listener)
{
if (!empty ())
{
ReadWriteMutex::ScopedReadLockType lock (m_mutex);
// Recursion not allowed.
bassert (m_listener == 0);
for (List <Entry>::iterator iter = m_list.begin (); iter != m_list.end ();)
{
Entry* entry = & (*iter++);
if (entry->listener == listener)
{
if (timestamp > entry->timestamp)
{
m_listener = entry->listener;
bassert (m_fifo.isBeingSynchronized ());
m_fifo.callp (new (m_fifo.getAllocator ()) CallWork (c, m_listener));
m_listener = 0;
}
}
}
}
else
{
// Listener was removed
}
}
//------------------------------------------------------------------------------
//
// Proxy
//
//------------------------------------------------------------------------------
// CallQueue item for processing a an Entry for a Proxy.
// This is used to avoid bind overhead.
//
class ListenersBase::Proxy::Work : public CallQueue::Work
{
public:
inline Work (Proxy* proxy,
Entry* const entry,
const timestamp_t timestamp)
: m_proxy (proxy)
, m_entry (entry)
, m_timestamp (timestamp)
{
}
void operator () ()
{
ListenersBase::Call* c = m_entry->call.exchange (0);
Group* group = m_entry->group;
if (!group->empty ())
group->do_call (c, m_timestamp);
c->decReferenceCount ();
}
private:
Proxy* const m_proxy;
Entry::Ptr m_entry;
const timestamp_t m_timestamp;
};
// Holds a Call, and gets put in the CallQueue in place of the Call.
// The Call may be replaced if it hasn't been processed yet.
// A Proxy exists for the lifetime of the Listeners.
//
ListenersBase::Proxy::Proxy (void const* const member, const size_t bytes)
: m_bytes (bytes)
{
if (bytes > maxMemberBytes)
Throw (Error ().fail (__FILE__, __LINE__, "the Proxy member is too large"));
memcpy (m_member, member, bytes);
}
ListenersBase::Proxy::~Proxy ()
{
// If the proxy is getting destroyed it means:
// - the listeners object is getting destroyed
// - all listeners must have removed themselves
// - all thread queues have been fully processed
// Therefore, our entries should be gone.
// NO it is possible for an empty Group, for which
// the parent listeners object has been destroyed,
// to still exist in a thread queue!!!
// But all listeners should have removed themselves
// so our list of groups should still be empty.
bassert (m_entries.empty ());
}
// Adds the group to the Proxy.
// Caller must have the proxies mutex.
// Caller is responsible for preventing duplicates.
//
void ListenersBase::Proxy::add (Group* group, AllocatorType& allocator)
{
Entry* entry (new (allocator) Entry (group));
// Manual addref and put raw pointer in list
entry->incReferenceCount ();
m_entries.push_back (*entry);
}
// Removes the group from the Proxy.
// Caller must have the proxies mutex.
// Caller is responsible for making sure the group exists.
void ListenersBase::Proxy::remove (Group* group)
{
for (Entries::iterator iter = m_entries.begin (); iter != m_entries.end ();)
{
Entry* entry = & (*iter++);
if (entry->group == group)
{
// remove from list and manual release
m_entries.erase (m_entries.iterator_to (*entry));
entry->decReferenceCount ();
// Entry might still be in the empty group's thread queue
break;
}
}
}
// For each group, updates the call.
// Queues each group that isn't already queued.
// Caller must acquire the group read lock.
//
void ListenersBase::Proxy::update (Call* const c, const timestamp_t timestamp)
{
// why would we even want to be called?
bassert (!m_entries.empty ());
// With the read lock, this list can't change on us unless someone
// adds a listener to a new thread queue in response to a call.
for (Entries::iterator iter = m_entries.begin (); iter != m_entries.end ();)
{
Entry* entry = & (*iter++);
// Manually add a reference since we use a raw pointer
c->incReferenceCount ();
// Atomically exchange the new call for the old one
Call* old = entry->call.exchange (c);
// If no old call then they need to be queued
if (!old)
{
CallQueue& callQueue = entry->group->getCallQueue ();
callQueue.callp (new (callQueue.getAllocator ()) Work (this, entry, timestamp));
}
else
{
old->decReferenceCount ();
}
}
}
bool ListenersBase::Proxy::match (void const* const member, const size_t bytes) const
{
return m_bytes == bytes && memcmp (member, m_member, bytes) == 0;
}
//------------------------------------------------------------------------------
//
// ListenersBase
//
//------------------------------------------------------------------------------
ListenersBase::ListenersBase ()
: m_timestamp (0)
, m_allocator (AllocatorType::getInstance ())
, m_callAllocator (CallAllocatorType::getInstance ())
{
}
ListenersBase::~ListenersBase ()
{
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
{
Group* group = & (*iter++);
// If this goes off it means a Listener forgot to remove.
bassert (group->empty ());
group->decReferenceCount ();
}
// Proxies are never deleted until here.
for (Proxies::iterator iter = m_proxies.begin (); iter != m_proxies.end ();)
delete & (*iter++);
}
void ListenersBase::add_void (void* const listener, CallQueue& callQueue)
{
ReadWriteMutex::ScopedWriteLockType lock (m_groups_mutex);
#if BEAST_DEBUG
// Make sure the listener has not already been added
// SHOULD USE const_iterator!
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
{
Group* group = & (*iter++);
// We can be in do_call() on another thread now, but it
// doesn't modify the list, and we have the write lock.
bassert (!group->contains (listener));
}
#endif
// See if we already have a Group for this thread queue.
Group::Ptr group;
// SHOULD USE const_iterator
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
{
Group::Ptr cur = & (*iter++);
if (&cur->getCallQueue () == &callQueue)
{
group = cur;
break;
}
}
if (!group)
{
group = new (m_allocator) Group (callQueue);
// Add it to the list, and give it a manual ref
// since the list currently uses raw pointers.
group->incReferenceCount ();
m_groups.push_back (*group);
// Tell existing proxies to add the group
ReadWriteMutex::ScopedReadLockType lock (m_proxies_mutex);
for (Proxies::iterator iter = m_proxies.begin (); iter != m_proxies.end ();)
(iter++)->add (group, *m_allocator);
}
// Add the listener to the group with the current timestamp
group->add (listener, m_timestamp, *m_allocator);
// Increment the timestamp within the mutex so
// future calls will be newer than this listener.
++m_timestamp;
}
void ListenersBase::remove_void (void* const listener)
{
ReadWriteMutex::ScopedWriteLockType lock (m_groups_mutex);
// Make sure the listener exists
#if BEAST_DEBUG
{
bool exists = false;
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
{
Group* group = & (*iter++);
// this should never happen while we hold the mutex
bassert (!group->empty ());
if (group->contains (listener))
{
bassert (!exists); // added twice?
exists = true;
// keep going to make sure there are no empty groups
}
}
bassert (exists);
}
#endif
// Find the group and remove
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
{
Group::Ptr group = & (*iter++);
// If the listener is in there, take it out.
if (group->remove (listener))
{
// Are we the last listener?
if (group->empty ())
{
// Tell proxies to remove the group
{
ReadWriteMutex::ScopedWriteLockType lock (m_proxies_mutex);
for (Proxies::iterator iter = m_proxies.begin (); iter != m_proxies.end ();)
{
Proxy* proxy = & (*iter++);
proxy->remove (group);
}
}
// Remove it from the list and manually release
// the reference since the list uses raw pointers.
m_groups.erase (m_groups.iterator_to (*group.getObject ()));
group->decReferenceCount ();
// It is still possible for the group to exist at this
// point in a thread queue but it will get processed,
// do nothing, and release its own final reference.
}
break;
}
}
}
void ListenersBase::callp (Call::Ptr cp)
{
Call* c = cp;
ReadWriteMutex::ScopedReadLockType lock (m_groups_mutex);
// can't be const iterator because queue() might cause called functors
// to modify the list.
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
(iter++)->call (c, m_timestamp);
}
void ListenersBase::queuep (Call::Ptr cp)
{
Call* c = cp;
ReadWriteMutex::ScopedReadLockType lock (m_groups_mutex);
// can't be const iterator because queue() might cause called functors
// to modify the list.
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
(iter++)->queue (c, m_timestamp);
}
void ListenersBase::call1p_void (void* const listener, Call* c)
{
ReadWriteMutex::ScopedReadLockType lock (m_groups_mutex);
// can't be const iterator because queue() might cause called functors
// to modify the list.
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
{
Group* group = & (*iter++);
if (group->contains (listener))
{
group->call1 (c, m_timestamp, listener);
break;
}
}
}
void ListenersBase::queue1p_void (void* const listener, Call* c)
{
ReadWriteMutex::ScopedReadLockType lock (m_groups_mutex);
// can't be const iterator because queue() might cause called functors
// to modify the list.
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
{
Group* group = & (*iter++);
if (group->contains (listener))
{
group->queue1 (c, m_timestamp, listener);
break;
}
}
}
// Search for an existing Proxy that matches the pointer to
// member and replace it's Call, or create a new Proxy for it.
//
void ListenersBase::updatep (void const* const member,
const size_t bytes, Call::Ptr cp)
{
Call* c = cp;
ReadWriteMutex::ScopedReadLockType lock (m_groups_mutex);
if (!m_groups.empty ())
{
Proxy* proxy;
{
ReadWriteMutex::ScopedReadLockType lock (m_proxies_mutex);
// See if there's already a proxy
proxy = find_proxy (member, bytes);
}
// Possibly create one
if (!proxy)
{
ReadWriteMutex::ScopedWriteLockType lock (m_proxies_mutex);
// Have to search for it again in case someone else added it
proxy = find_proxy (member, bytes);
if (!proxy)
{
// Create a new empty proxy
proxy = new (m_allocator) Proxy (member, bytes);
// Add all current groups to the Proxy.
// We need the group read lock for this (caller provided).
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
{
Group* group = & (*iter++);
proxy->add (group, *m_allocator);
}
// Add it to the list.
m_proxies.push_front (*proxy);
}
}
// Requires the group read lock
proxy->update (c, m_timestamp);
}
}
// Searches for a proxy that matches the pointer to member.
// Caller synchronizes.
//
ListenersBase::Proxy* ListenersBase::find_proxy (const void* member, size_t bytes)
{
for (Proxies::iterator iter = m_proxies.begin (); iter != m_proxies.end ();)
{
Proxy* proxy = & (*iter++);
if (proxy->match (member, bytes))
return proxy;
}
return 0;
}

View File

@@ -1,887 +0,0 @@
//------------------------------------------------------------------------------
/*
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_LISTENERS_BEASTHEADER
#define BEAST_LISTENERS_BEASTHEADER
/*============================================================================*/
/**
A group of concurrent Listeners.
A Listener is an object of class type which inherits from a defined
interface, and registers on a provided instance of Listeners to receive
asynchronous notifications of changes to concurrent states. Another way of
defining Listeners, is that it is similar to a Juce ListenerList but with
the provision that the Listener registers with the CallQueue upon which the
notification should be made.
Listeners makes extensive use of CallQueue for providing the notifications,
and provides a higher level facility for implementing the concurrent
synchronization strategy outlined in CallQueue. Therefore, the same notes
which apply to functors in CallQueue also apply to Listener member
invocations. Their execution time should be brief, limited in scope to
updating the recipient's view of a shared state, and use reference counting
for parameters of class type.
To use this system, first declare your Listener interface:
@code
struct Listener
{
// Sent on every output block
virtual void onOutputLevelChanged (const float outputLevel) { }
};
@endcode
Now set up the place where you want to send the notifications. In this
example, we will set up the AudioIODeviceCallback to notify anyone who is
interested about changes in the current audio output level. We will use
this to implement a VU meter:
@code
Listeners <Listener> listeners;
// (Process audio data)
// Calculate output level
float outputLevel = calcOutputLevel ();
// Notify listeners
listeners.call (&Listener::onOutputLevelChanged, outputLevel);
@endcode
To receive notifications, derive from Listener and then add yourself to the
Listeners object using the desired CallQueue.
@code
// We want notifications on the message thread
GuiCallQueue fifo;
struct VUMeter : public Listener, public Component
{
VUMeter () : m_outputLevel (0)
{
listeners.add (this, fifo);
}
~VUMeter ()
{
listeners.remove (this);
}
void onOutputLevelChanged (float outputLevel)
{
// Update our copy of the output level shared state.
m_outputLevel = outputLevel;
// Now trigger a redraw of the control.
repaint ();
}
float m_outputLevel;
};
@endcode
In this example, the VUMeter constructs with the output level set to zero,
and must wait for a notification before it shows up to date data. For a
simple VU meter, this is likely not a problem. But if the shared state
contains complex information, such as dynamically allocated objects with
rich data, then we need a more solid system.
We will add some classes to create a complete robust example of the use of
Listeners to synchronize shared state:
@code
// Handles audio device output.
class AudioDeviceOutput : public AudioIODeviceCallback
{
public:
struct Listener
{
// Sent on every output block.
virtual void onOutputLevelChanged (float outputLevel) { }
};
AudioDeviceOutput () : AudioDeviceOutput ("Audio CallQueue")
{
}
~AudioDeviceOutput ()
{
m_fifo.close ();
}
void addListener (Listener* listener, CallQueue& callQueue)
{
// Acquire read access to the shared state.
ConcurrentState <State>::ReadAccess state (m_state);
// Add the listener.
m_listeners.add (listener, callQueue);
// Queue an update for the listener to receive the initial state.
m_listeners.queue1 (listener,
&Listener::onOutputLevelChanged,
state->outputLevel);
}
void removeListener (Listener* listener)
{
m_listeners.remove (listener);
}
protected:
void audioDeviceIOCallback (const float** inputChannelData,
int numInputChannels,
float** outputChannelData,
int numOutputChannels,
int numSamples)
{
// Synchronize our call queue. Not needed for this example but
// included here as a best-practice for audio device I/O callbacks.
m_fifo.synchronize ();
// (Process audio data)
// Calculate output level.
float newOutputLevel = calcOutputLevel ();
// Update shared state.
{
ConcurrentState <State>::WriteAccess state (m_state);
m_state->outputLevel = newOutputLevel;
}
// Notify listeners.
listeners.call (&Listener::onOutputLevelChanged, newOutputLevel);
}
private:
struct State
{
State () : outputLevel (0) { }
float outputLevel;
};
ConcurrentState <State> m_state;
ManualCallQueue m_fifo;
};
@endcode
Although the rigor demonstrated in the example above is not strictly
required when the shared state consists only of a single float, it
becomes necessary when there are dynamically allocated objects with complex
interactions in the shared state.
@see CallQueue
@class Listeners
@ingroup beast_concurrent
*/
class ListenersBase
{
public:
struct ListenersStructureTag { };
typedef GlobalFifoFreeStore <ListenersStructureTag> AllocatorType;
typedef GlobalFifoFreeStore <ListenersBase> CallAllocatorType;
class Call : public ReferenceCountedObject,
public AllocatedBy <CallAllocatorType>
{
public:
typedef ReferenceCountedObjectPtr <Call> Ptr;
virtual void operator () (void* const listener) = 0;
};
private:
typedef unsigned long timestamp_t;
class Group;
typedef List <Group> Groups;
class Proxy;
typedef List <Proxy> Proxies;
class CallWork;
class GroupWork;
class GroupWork1;
// Maintains a list of listeners registered on the same CallQueue
//
class Group : public Groups::Node,
public ReferenceCountedObject,
public AllocatedBy <AllocatorType>
{
public:
typedef ReferenceCountedObjectPtr <Group> Ptr;
explicit Group (CallQueue& callQueue);
~Group ();
void add (void* listener, const timestamp_t timestamp,
AllocatorType& allocator);
bool remove (void* listener);
bool contains (void* const listener);
void call (Call* const c, const timestamp_t timestamp);
void queue (Call* const c, const timestamp_t timestamp);
void call1 (Call* const c, const timestamp_t timestamp,
void* const listener);
void queue1 (Call* const c, const timestamp_t timestamp,
void* const listener);
void do_call (Call* const c, const timestamp_t timestamp);
void do_call1 (Call* const c, const timestamp_t timestamp,
void* const listener);
bool empty () const
{
return m_list.empty ();
}
CallQueue& getCallQueue () const
{
return m_fifo;
}
private:
struct Entry;
CallQueue& m_fifo;
List <Entry> m_list;
void* m_listener;
CacheLine::Aligned <ReadWriteMutex> m_mutex;
};
// A Proxy is keyed to a unique pointer-to-member of a
// ListenerClass and is used to consolidate multiple unprocessed
// Calls into a single call to prevent excess messaging. It is up
// to the user of the class to decide when this behavior is appropriate.
//
class Proxy : public Proxies::Node,
public AllocatedBy <AllocatorType>
{
public:
enum
{
maxMemberBytes = 16
};
Proxy (void const* const member, const size_t bytes);
~Proxy ();
void add (Group* group, AllocatorType& allocator);
void remove (Group* group);
void update (Call* const c, const timestamp_t timestamp);
bool match (void const* const member, const size_t bytes) const;
private:
class Work;
struct Entry;
typedef List <Entry> Entries;
char m_member [maxMemberBytes];
const size_t m_bytes;
Entries m_entries;
};
protected:
ListenersBase ();
~ListenersBase ();
inline CallAllocatorType& getCallAllocator ()
{
return *m_callAllocator;
}
void add_void (void* const listener, CallQueue& callQueue);
void remove_void (void* const listener);
void callp (Call::Ptr c);
void queuep (Call::Ptr c);
void call1p_void (void* const listener, Call* c);
void queue1p_void (void* const listener, Call* c);
void updatep (void const* const member,
const size_t bytes, Call::Ptr cp);
private:
Proxy* find_proxy (const void* member, size_t bytes);
private:
Groups m_groups;
Proxies m_proxies;
timestamp_t m_timestamp;
CacheLine::Aligned <ReadWriteMutex> m_groups_mutex;
CacheLine::Aligned <ReadWriteMutex> m_proxies_mutex;
AllocatorType::Ptr m_allocator;
CallAllocatorType::Ptr m_callAllocator;
};
/*============================================================================*/
template <class ListenerClass>
class Listeners : public ListenersBase
{
private:
template <class Functor>
class CallType : public Call
{
public:
CallType (Functor f) : m_f (f)
{
}
void operator () (void* const listener)
{
ListenerClass* object = static_cast <ListenerClass*> (listener);
m_f.operator () (object);
}
private:
Functor m_f;
};
template <class Functor>
inline void callf (Functor f)
{
callp (new (getCallAllocator ()) CallType <Functor> (f));
}
template <class Functor>
inline void queuef (Functor f)
{
queuep (new (getCallAllocator ()) CallType <Functor> (f));
}
inline void call1p (ListenerClass* const listener, Call::Ptr c)
{
call1p_void (listener, c);
}
inline void queue1p (ListenerClass* const listener, Call::Ptr c)
{
queue1p_void (listener, c);
}
template <class Functor>
inline void call1f (ListenerClass* const listener, Functor f)
{
call1p (listener, new (getCallAllocator ()) CallType <Functor> (f));
}
template <class Functor>
inline void queue1f (ListenerClass* const listener, Functor f)
{
queue1p (listener, new (getCallAllocator ()) CallType <Functor> (f));
}
template <class Member, class Functor>
inline void updatef (Member member, Functor f)
{
updatep (reinterpret_cast <void*> (&member), sizeof (Member),
new (getCallAllocator ()) CallType <Functor> (f));
}
public:
/** Add a listener.
The specified listener is associated with the specified CallQueue and
added to the list.
Invariants:
- All other members of Listeners are blocked during add().
- The listener is guaranteed to receive every subsequent call.
- The listener must not already exist in the list.
- Safe to call from any thread.
@param listener The listener to add.
@param callQueue The CallQueue to associate with the listener.
*/
void add (ListenerClass* const listener, CallQueue& callQueue)
{
add_void (listener, callQueue);
}
/** Remove a listener.
The specified listener, which must have been previously added, is removed
from the list. A listener always needs to remove itself before the
associated CallQueue is closed.
Invariants:
- All other members of Listeners are blocked during remove().
- The listener is guaranteed not to receive calls after remove() returns.
- Safe to call from any thread.
@param listener The listener to remove.
*/
void remove (ListenerClass* const listener)
{
remove_void (listener);
}
/** Call a member function on every added listener, on its associated
CallQueue.
A listener's CallQueue will be synchronized if this function is called
from it's associated thread.
Invariants:
- A listener that later removes itself afterwards may not get called.
- Calls from the same thread always execute in order.
- A listener can remove itself even if it has a pending call.
@param mf The member function to call. This may be followed by up to 8
arguments.
*/
/** @{ */
#if BEAST_VARIADIC_MAX >= 1
template <class Mf>
inline void call (Mf mf)
{
callf (bind (mf, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 2
template <class Mf, class T1>
void call (Mf mf, T1 t1)
{
callf (bind (mf, _1, t1));
}
#endif
#if BEAST_VARIADIC_MAX >= 3
template <class Mf, class T1, class T2>
void call (Mf mf, T1 t1, T2 t2)
{
callf (bind (mf, _1, t1, t2));
}
#endif
#if BEAST_VARIADIC_MAX >= 4
template <class Mf, class T1, class T2, class T3>
void call (Mf mf, T1 t1, T2 t2, T3 t3)
{
callf (bind (mf, _1, t1, t2, t3));
}
#endif
#if BEAST_VARIADIC_MAX >= 5
template <class Mf, class T1, class T2, class T3, class T4>
void call (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4)
{
callf (bind (mf, _1, t1, t2, t3, t4));
}
#endif
#if BEAST_VARIADIC_MAX >= 6
template <class Mf, class T1, class T2, class T3, class T4, class T5>
void call (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
callf (bind (mf, _1, t1, t2, t3, t4, t5));
}
#endif
#if BEAST_VARIADIC_MAX >= 7
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6>
void call (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
{
callf (bind (mf, _1, t1, t2, t3, t4, t5, t6));
}
#endif
#if BEAST_VARIADIC_MAX >= 8
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
void call (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
{
callf (bind (mf, _1, t1, t2, t3, t4, t5, t6, t7));
}
#endif
#if BEAST_VARIADIC_MAX >= 9
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
void call (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
{
callf (bind (mf, _1, t1, t2, t3, t4, t5, t6, t7, t8));
}
#endif
/** @} */
/** Queue a member function on every added listener, without synchronizing.
Operates like call(), but no CallQueue synchronization takes place. This
can be necessary when the call to queue() is made inside a held lock.
@param mf The member function to call. This may be followed by up to 8
arguments.
*/
/** @{ */
#if BEAST_VARIADIC_MAX >= 1
template <class Mf>
inline void queue (Mf mf)
{
queuef (bind (mf, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 2
template <class Mf, class T1>
void queue (Mf mf, T1 t1)
{
queuef (bind (mf, _1, t1));
}
#endif
#if BEAST_VARIADIC_MAX >= 3
template <class Mf, class T1, class T2>
void queue (Mf mf, T1 t1, T2 t2)
{
queuef (bind (mf, _1, t1, t2));
}
#endif
#if BEAST_VARIADIC_MAX >= 4
template <class Mf, class T1, class T2, class T3>
void queue (Mf mf, T1 t1, T2 t2, T3 t3)
{
queuef (bind (mf, _1, t1, t2, t3));
}
#endif
#if BEAST_VARIADIC_MAX >= 5
template <class Mf, class T1, class T2, class T3, class T4>
void queue (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4)
{
queuef (bind (mf, _1, t1, t2, t3, t4));
}
#endif
#if BEAST_VARIADIC_MAX >= 6
template <class Mf, class T1, class T2, class T3, class T4, class T5>
void queue (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
queuef (bind (mf, _1, t1, t2, t3, t4, t5));
}
#endif
#if BEAST_VARIADIC_MAX >= 7
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6>
void queue (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
{
queuef (bind (mf, _1, t1, t2, t3, t4, t5, t6));
}
#endif
#if BEAST_VARIADIC_MAX >= 8
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
void queue (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
{
queuef (bind (mf, _1, t1, t2, t3, t4, t5, t6, t7));
}
#endif
#if BEAST_VARIADIC_MAX >= 9
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
void queue (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
{
queuef (bind (mf, _1, t1, t2, t3, t4, t5, t6, t7, t8));
}
#endif
/** @} */
/** Call a member function on every added listener, replacing pending
calls to the same member.
This operates like call(), except that if there are pending unprocessed
calls to the same member function,they will be replaced, with the previous
parameters destroyed normally. This functionality is useful for
high frequency notifications of non critical data, where the recipient
may not catch up often enough. For example, the output level of the
AudioIODeviceCallback in the example is a candidate for the use of
update().
@param mf The member function to call. This may be followed by up to 8
arguments.
*/
/** @{ */
#if BEAST_VARIADIC_MAX >= 1
template <class Mf>
inline void update (Mf mf)
{
updatef (mf, bind (mf, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 2
template <class Mf, class T1>
void update (Mf mf, T1 t1)
{
updatef (mf, bind (mf, _1, t1));
}
#endif
#if BEAST_VARIADIC_MAX >= 3
template <class Mf, class T1, class T2>
void update (Mf mf, T1 t1, T2 t2)
{
updatef (mf, bind (mf, _1, t1, t2));
}
#endif
#if BEAST_VARIADIC_MAX >= 4
template <class Mf, class T1, class T2, class T3>
void update (Mf mf, T1 t1, T2 t2, T3 t3)
{
updatef (mf, bind (mf, _1, t1, t2, t3));
}
#endif
#if BEAST_VARIADIC_MAX >= 5
template <class Mf, class T1, class T2, class T3, class T4>
void update (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4)
{
updatef (mf, bind (mf, _1, t1, t2, t3, t4));
}
#endif
#if BEAST_VARIADIC_MAX >= 6
template <class Mf, class T1, class T2, class T3, class T4, class T5>
void update (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
updatef (mf, bind (mf, _1, t1, t2, t3, t4, t5));
}
#endif
#if BEAST_VARIADIC_MAX >= 7
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6>
void update (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
{
updatef (mf, bind (mf, _1, t1, t2, t3, t4, t5, t6));
}
#endif
#if BEAST_VARIADIC_MAX >= 8
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
void update (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
{
updatef (mf, bind (mf, _1, t1, t2, t3, t4, t5, t6, t7));
}
#endif
#if BEAST_VARIADIC_MAX >= 9
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
void update (Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
{
updatef (mf, bind (mf, _1, t1, t2, t3, t4, t5, t6, t7, t8));
}
#endif
/** @} */
/** Call a member function on a specific listener.
Like call(), except that one listener is targeted only. This is useful when
builing complex behaviors during the addition of a listener, such as
providing an initial state.
@param listener The listener to call.
@param mf The member function to call. This may be followed by up
to 8 arguments.
*/
/** @{ */
#if BEAST_VARIADIC_MAX >= 1
template <class Mf>
inline void call1 (ListenerClass* const listener, Mf mf)
{
call1f (listener, bind (mf, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 2
template <class Mf, class T1>
void call1 (ListenerClass* const listener, Mf mf, T1 t1)
{
call1f (listener, bind (mf, _1, t1));
}
#endif
#if BEAST_VARIADIC_MAX >= 3
template <class Mf, class T1, class T2>
void call1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2)
{
call1f (listener, bind (mf, _1, t1, t2));
}
#endif
#if BEAST_VARIADIC_MAX >= 4
template <class Mf, class T1, class T2, class T3>
void call1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3)
{
call1f (listener, bind (mf, _1, t1, t2, t3));
}
#endif
#if BEAST_VARIADIC_MAX >= 5
template <class Mf, class T1, class T2, class T3, class T4>
void call1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3, T4 t4)
{
call1f (listener, bind (mf, _1, t1, t2, t3, t4));
}
#endif
#if BEAST_VARIADIC_MAX >= 6
template <class Mf, class T1, class T2, class T3, class T4, class T5>
void call1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
call1f (listener, bind (mf, _1, t1, t2, t3, t4, t5));
}
#endif
#if BEAST_VARIADIC_MAX >= 7
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6>
void call1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
{
call1f (listener, bind (mf, _1, t1, t2, t3, t4, t5, t6));
}
#endif
#if BEAST_VARIADIC_MAX >= 8
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
void call1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
{
call1f (listener, bind (mf, _1, t1, t2, t3, t4, t5, t6, t7));
}
#endif
#if BEAST_VARIADIC_MAX >= 9
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
void call1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
{
call1f (listener, bind (mf, _1, t1, t2, t3, t4, t5, t6, t7, t8));
}
#endif
/** @} */
/** Queue a member function on a specific listener.
Like call1(), except that no CallQueue synchronization takes place.
@param listener The listener to call.
@param mf The member function to call. This may be followed by up
to 8 arguments.
*/
/** @{ */
#if BEAST_VARIADIC_MAX >= 1
template <class Mf>
inline void queue1 (ListenerClass* const listener, Mf mf)
{
queue1f (listener, bind (mf, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 2
template <class Mf, class T1>
void queue1 (ListenerClass* const listener, Mf mf, T1 t1)
{
queue1f (listener, bind (mf, _1, t1));
}
#endif
#if BEAST_VARIADIC_MAX >= 3
template <class Mf, class T1, class T2>
void queue1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2)
{
queue1f (listener, bind (mf, _1, t1, t2));
}
#endif
#if BEAST_VARIADIC_MAX >= 4
template <class Mf, class T1, class T2, class T3>
void queue1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3)
{
queue1f (listener, bind (mf, _1, t1, t2, t3));
}
#endif
#if BEAST_VARIADIC_MAX >= 5
template <class Mf, class T1, class T2, class T3, class T4>
void queue1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3, T4 t4)
{
queue1f (listener, bind (mf, _1, t1, t2, t3, t4));
}
#endif
#if BEAST_VARIADIC_MAX >= 6
template <class Mf, class T1, class T2, class T3, class T4, class T5>
void queue1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
queue1f (listener, bind (mf, _1, t1, t2, t3, t4, t5));
}
#endif
#if BEAST_VARIADIC_MAX >= 7
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6>
void queue1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
{
queue1f (listener, bind (mf, _1, t1, t2, t3, t4, t5, t6));
}
#endif
#if BEAST_VARIADIC_MAX >= 8
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
void queue1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
{
queue1f (listener, bind (mf, _1, t1, t2, t3, t4, t5, t6, t7));
}
#endif
#if BEAST_VARIADIC_MAX >= 9
template <class Mf, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
void queue1 (ListenerClass* const listener, Mf mf, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
{
queue1f (listener, bind (mf, _1, t1, t2, t3, t4, t5, t6, t7, t8));
}
#endif
/** @} */
};
/** @} */
#endif

View File

@@ -1,54 +0,0 @@
/*============================================================================*/
/*
VFLib: https://github.com/vinniefalco/VFLib
Copyright (C) 2008 by Vinnie Falco <vinnie.falco@gmail.com>
This library contains portions of other open source products covered by
separate licenses. Please see the corresponding source files for specific
terms.
VFLib is provided under the terms of The MIT License (MIT):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/*============================================================================*/
ManualCallQueue::ManualCallQueue (String name)
: CallQueue (name)
{
}
void ManualCallQueue::close ()
{
CallQueue::close ();
}
bool ManualCallQueue::synchronize ()
{
return CallQueue::synchronize ();
}
void ManualCallQueue::signal ()
{
}
void ManualCallQueue::reset ()
{
}

View File

@@ -1,108 +0,0 @@
/*============================================================================*/
/*
VFLib: https://github.com/vinniefalco/VFLib
Copyright (C) 2008 by Vinnie Falco <vinnie.falco@gmail.com>
This library contains portions of other open source products covered by
separate licenses. Please see the corresponding source files for specific
terms.
VFLib is provided under the terms of The MIT License (MIT):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/*============================================================================*/
#ifndef VF_MANUALCALLQUEUE_VFHEADER
#define VF_MANUALCALLQUEUE_VFHEADER
/*============================================================================*/
/**
A CallQueue that requires periodic manual synchronization.
To use this, declare an instance and then place calls into it as usual.
Every so often, you must call synchronize() from the thread you want to
associate with the queue. Typically this is done within an
AudioIODeviceCallback:
@code
class AudioIODeviceCallbackWithCallQueue
: public AudioIODeviceCallback
, public CallQueue
{
public:
AudioIODeviceCallbackWithCallQueue () : m_fifo ("Audio CallQueue")
{
}
void audioDeviceIOCallback (const float** inputChannelData,
int numInputChannels,
float** outputChannelData,
int numOutputChannels,
int numSamples)
{
CallQueue::synchronize ();
// do audio i/o
}
void signal () { } // No action required
void reset () { } // No action required
};
@endcode
The close() function is provided for diagnostics. Call it as early as
possible based on the exit or shutdown logic of your application. If calls
are put into the queue after it is closed, it will generate an exception so
you can track it down.
@see CallQueue
@ingroup vf_concurrent
*/
class ManualCallQueue : public CallQueue
{
public:
/** Create a ManualCallQueue.
@param name A string used to help identify the associated
thread for debugging.
*/
explicit ManualCallQueue (String name);
/** Close the queue. If calls are placed into a closed queue, an exception
is thrown.
*/
void close ();
/** Synchronize the queue by calling all pending functors.
@return `true` if any functors were called.
*/
bool synchronize ();
private:
void signal ();
void reset ();
};
#endif

View File

@@ -1,63 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
ParallelFor::ParallelFor (ThreadGroup& pool)
: m_pool (pool)
, m_finishedEvent (false) // auto-reset
{
}
int ParallelFor::getNumberOfThreads () const
{
return m_pool.getNumberOfThreads ();
}
void ParallelFor::doLoop (int numberOfIterations, Iteration& iteration)
{
if (numberOfIterations > 1)
{
int const numberOfThreads = m_pool.getNumberOfThreads ();
// The largest number of pool threads we need is one less than the number
// of iterations, because we also run the loop body on the caller's thread.
//
int const maxThreads = numberOfIterations - 1;
// Calculate the number of parallel instances as the smaller of the number
// of threads available (including the caller's) and the number of iterations.
//
int const numberOfParallelInstances = std::min (
numberOfThreads + 1, numberOfIterations);
LoopState* loopState (new (m_pool.getAllocator ()) LoopState (
iteration, m_finishedEvent, numberOfIterations, numberOfParallelInstances));
m_pool.call (maxThreads, &LoopState::forLoopBody, loopState);
// Also use the caller's thread to run the loop body.
loopState->forLoopBody ();
m_finishedEvent.wait ();
}
else if (numberOfIterations == 1)
{
// Just one iteration, so do it.
iteration (0);
}
}

View File

@@ -1,491 +0,0 @@
//------------------------------------------------------------------------------
/*
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_PARALLELFOR_BEASTHEADER
#define BEAST_PARALLELFOR_BEASTHEADER
/*============================================================================*/
/**
Parallel for loop.
This uses a ThreadGroup to iterate through a for loop in parallel. The
following two pieces of code perform identical operations:
@code
extern void function (int loopIndex);
// Serial computation
//
for (int i = 0; i < numberOfIterations; ++i)
function (i);
// Parallel computation
//
ParallelFor().loop (numberOfIterations, &function);
@endcode
`function` is a caller provided functor. Convenience functions are provided
for automatic binding to member or non member functions with up to 8
arguments (not including the loop index).
@note The last argument to function () is always the loop index.
@see ThreadGroup
@ingroup beast_concurrent
*/
class ParallelFor : Uncopyable
{
public:
/** Create a parallel for loop.
It is best to keep this object around instead of creating and destroying
it every time you need to run a loop.
@param pool The ThreadGroup to use. If this is omitted then a singleton
ThreadGroup is used which contains one thread per CPU.
*/
explicit ParallelFor (ThreadGroup& pool = *GlobalThreadGroup::getInstance ());
/** Determine the number of threads in the group.
@return The number of threads in the group.
*/
int getNumberOfThreads () const;
template <class F, class T1>
void operator () (int numberOfIterations, T1 t1)
{
}
/** Execute parallel for loop.
Functor is called once for each value in the range
[0, numberOfIterations), using the ThreadGroup.
@param numberOfIterations The number of times to loop.
@param f The functor to call for each loop index.
*/
/** @{ */
template <class Functor>
void loopf (int numberOfIterations, Functor const& f)
{
IterationType <Functor> iteration (f);
doLoop (numberOfIterations, iteration);
}
#if BEAST_VARIADIC_MAX >= 1
template <class Fn>
void loop (int n, Fn f)
{
loopf (n, bind (f, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 2
template <class Fn, class T1>
void loop (int n, Fn f, T1 t1)
{
loopf (n, bind (f, t1, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 3
template <class Fn, class T1, class T2>
void loop (int n, Fn f, T1 t1, T2 t2)
{
loopf (n, bind (f, t1, t2, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 4
template <class Fn, class T1, class T2, class T3>
void loop (int n, Fn f, T1 t1, T2 t2, T3 t3)
{
loopf (n, bind (f, t1, t2, t3, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 5
template <class Fn, class T1, class T2, class T3, class T4>
void loop (int n, Fn f, T1 t1, T2 t2, T3 t3, T4 t4)
{
loopf (n, bind (f, t1, t2, t3, t4, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 6
template <class Fn, class T1, class T2, class T3, class T4, class T5>
void loop (int n, Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
loopf (n, bind (f, t1, t2, t3, t4, t5, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 7
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6>
void loop (int n, Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
{
loopf (n, bind (f, t1, t2, t3, t4, t5, t6, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 8
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
void loop (int n, Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
{
loopf (n, bind (f, t1, t2, t3, t4, t5, t6, t7, _1));
}
#endif
#if BEAST_VARIADIC_MAX >= 9
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
void loop (int n, Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
{
loopf (n, bind (f, t1, t2, t3, t4, t5, t6, t7, t8, _1));
}
#endif
/** @} */
private:
class Iteration
{
public:
virtual ~Iteration () { }
virtual void operator () (int loopIndex) = 0;
};
template <class Functor>
class IterationType : public Iteration, Uncopyable
{
public:
explicit IterationType (Functor const& f) : m_f (f)
{
}
void operator () (int loopIndex)
{
m_f (loopIndex);
}
private:
Functor m_f;
};
private:
class LoopState
: public AllocatedBy <ThreadGroup::AllocatorType>
, Uncopyable
{
private:
Iteration& m_iteration;
WaitableEvent& m_finishedEvent;
int const m_numberOfIterations;
Atomic <int> m_loopIndex;
Atomic <int> m_iterationsRemaining;
Atomic <int> m_numberOfParallelInstances;
public:
LoopState (Iteration& iteration,
WaitableEvent& finishedEvent,
int numberOfIterations,
int numberOfParallelInstances)
: m_iteration (iteration)
, m_finishedEvent (finishedEvent)
, m_numberOfIterations (numberOfIterations)
, m_loopIndex (-1)
, m_iterationsRemaining (numberOfIterations)
, m_numberOfParallelInstances (numberOfParallelInstances)
{
}
~LoopState ()
{
}
void forLoopBody ()
{
for (;;)
{
// Request a loop index to process.
int const loopIndex = ++m_loopIndex;
// Is it in range?
if (loopIndex < m_numberOfIterations)
{
// Yes, so process it.
m_iteration (loopIndex);
// Was this the last work item to complete?
if (--m_iterationsRemaining == 0)
{
// Yes, signal.
m_finishedEvent.signal ();
break;
}
}
else
{
// Out of range, all work is complete or assigned.
break;
}
}
release ();
}
void release ()
{
if (--m_numberOfParallelInstances == 0)
delete this;
}
};
private:
void doLoop (int numberOfIterations, Iteration& iteration);
private:
ThreadGroup& m_pool;
WaitableEvent m_finishedEvent;
Atomic <int> m_currentIndex;
Atomic <int> m_numberOfInstances;
int m_numberOfIterations;
};
//------------------------------------------------------------------------------
class ParallelFor2 : Uncopyable
{
public:
/** Create a parallel for loop.
It is best to keep this object around instead of creating and destroying
it every time you need to run a loop.
@param pool The ThreadGroup to use. If this is omitted then a singleton
ThreadGroup is used which contains one thread per CPU.
*/
explicit ParallelFor2 (ThreadGroup& pool = *GlobalThreadGroup::getInstance ())
: m_pool (pool)
, m_finishedEvent (false) // auto-reset
{
}
/** Determine the number of threads in the group.
@return The number of threads in the group.
*/
int getNumberOfThreads () const
{
return m_pool.getNumberOfThreads ();
}
template <class F, class T1, class T2, class T3, class T4>
void operator () (int numberOfIterations, T1 t1, T2 t2, T3 t3, T4 t4)
{
Factory4 <F, T1, T2, T3, T4> f (t1, t2, t3, t4);
doLoop (numberOfIterations, f);
}
private:
typedef ThreadGroup::AllocatorType AllocatorType;
//---
struct Iterator : public AllocatedBy <AllocatorType>
{
virtual ~Iterator () { }
virtual void operator () (int loopIndex) = 0;
};
//---
template <class Functor>
struct IteratorType : public Iterator, Uncopyable
{
explicit IteratorType (Functor f) : m_f (f)
{
}
void operator () (int loopIndex)
{
m_f (loopIndex);
}
private:
Functor m_f;
};
//---
struct Factory
{
virtual ~Factory () { }
virtual Iterator* operator () (AllocatorType& allocator) = 0;
};
template <class F, class T1, class T2, class T3, class T4>
struct Factory4 : Factory
{
Factory4 (T1 t1, T2 t2, T3 t3, T4 t4)
: m_t1 (t1), m_t2 (t2), m_t3 (t3), m_t4 (t4) { }
Iterator* operator () (AllocatorType& allocator)
{
return new (allocator) IteratorType <F> (m_t1, m_t2, m_t3, m_t4);
}
private:
T1 m_t1;
T2 m_t2;
T3 m_t3;
T4 m_t4;
};
private:
class LoopState
: public AllocatedBy <AllocatorType>
, Uncopyable
{
private:
Factory& m_factory;
WaitableEvent& m_finishedEvent;
int const m_numberOfIterations;
Atomic <int> m_loopIndex;
Atomic <int> m_iterationsRemaining;
Atomic <int> m_numberOfParallelInstances;
AllocatorType& m_allocator;
public:
LoopState (Factory& factory,
WaitableEvent& finishedEvent,
int numberOfIterations,
int numberOfParallelInstances,
AllocatorType& allocator)
: m_factory (factory)
, m_finishedEvent (finishedEvent)
, m_numberOfIterations (numberOfIterations)
, m_loopIndex (-1)
, m_iterationsRemaining (numberOfIterations)
, m_numberOfParallelInstances (numberOfParallelInstances)
, m_allocator (allocator)
{
}
~LoopState ()
{
}
void forLoopBody ()
{
Iterator* iterator = m_factory (m_allocator);
for (;;)
{
// Request a loop index to process.
int const loopIndex = ++m_loopIndex;
// Is it in range?
if (loopIndex < m_numberOfIterations)
{
// Yes, so process it.
(*iterator) (loopIndex);
// Was this the last work item to complete?
if (--m_iterationsRemaining == 0)
{
// Yes, signal.
m_finishedEvent.signal ();
break;
}
}
else
{
// Out of range, all work is complete or assigned.
break;
}
}
release ();
delete iterator;
}
void release ()
{
if (--m_numberOfParallelInstances == 0)
delete this;
}
};
private:
void doLoop (int numberOfIterations, Factory& factory)
{
if (numberOfIterations > 1)
{
int const numberOfThreads = m_pool.getNumberOfThreads ();
// The largest number of pool threads we need is one less than the number
// of iterations, because we also run the loop body on the caller's thread.
//
int const maxThreads = numberOfIterations - 1;
// Calculate the number of parallel instances as the smaller of the number
// of threads available (including the caller's) and the number of iterations.
//
int const numberOfParallelInstances = std::min (
numberOfThreads + 1, numberOfIterations);
LoopState* loopState (new (m_pool.getAllocator ()) LoopState (
factory,
m_finishedEvent,
numberOfIterations,
numberOfParallelInstances,
m_pool.getAllocator ()));
m_pool.call (maxThreads, &LoopState::forLoopBody, loopState);
// Also use the caller's thread to run the loop body.
loopState->forLoopBody ();
m_finishedEvent.wait ();
}
else if (numberOfIterations == 1)
{
// Just one iteration, so do it.
Iterator* iter = factory (m_pool.getAllocator ());
(*iter) (0);
delete iter;
}
}
private:
ThreadGroup& m_pool;
WaitableEvent m_finishedEvent;
Atomic <int> m_currentIndex;
Atomic <int> m_numberOfInstances;
int m_numberOfIterations;
};
#endif

View File

@@ -1,98 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
ReadWriteMutex::ReadWriteMutex () noexcept
{
}
ReadWriteMutex::~ReadWriteMutex () noexcept
{
}
void ReadWriteMutex::enterRead () const noexcept
{
for (;;)
{
// attempt the lock optimistically
// THIS IS NOT CACHE-FRIENDLY!
m_readers->addref ();
// is there a writer?
// THIS IS NOT CACHE-FRIENDLY!
if (m_writes->isSignaled ())
{
// a writer exists, give up the read lock
m_readers->release ();
// block until the writer is done
{
CriticalSection::ScopedLockType lock (m_mutex);
}
// now try the loop again
}
else
{
break;
}
}
}
void ReadWriteMutex::exitRead () const noexcept
{
m_readers->release ();
}
void ReadWriteMutex::enterWrite () const noexcept
{
// Optimistically acquire the write lock.
m_writes->addref ();
// Go for the mutex.
// Another writer might block us here.
m_mutex.enter ();
// Only one competing writer will get here,
// but we don't know who, so we have to drain
// readers no matter what. New readers will be
// blocked by the mutex.
//
if (m_readers->isSignaled ())
{
SpinDelay delay;
do
{
delay.pause ();
}
while (m_readers->isSignaled ());
}
}
void ReadWriteMutex::exitWrite () const noexcept
{
// Releasing the mutex first and then decrementing the
// writer count allows another waiting writer to atomically
// acquire the lock, thus starving readers. This fulfills
// the write-preferencing requirement.
m_mutex.exit ();
m_writes->release ();
}

View File

@@ -1,146 +0,0 @@
//------------------------------------------------------------------------------
/*
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_READWRITEMUTEX_BEASTHEADER
#define BEAST_READWRITEMUTEX_BEASTHEADER
/*============================================================================*/
/**
Multiple consumer, single producer (MCSP) synchronization.
This is an optimized lock for the multiple reader, single writer
scenario. It provides only a subset of features of the more general
traditional read/write lock. Specifically, these rules apply:
- A caller cannot hold a read lock while acquiring a write lock.
- Write locks are only recursive with respect to write locks.
- Read locks are only recursive with respect to read locks.
- A write lock cannot be downgraded.
- Writes are preferenced over reads.
For real-time applications, these restrictions are often not an issue.
The implementation is wait-free in the fast path: acquiring read access
for a lock without contention - just one interlocked increment!
@class ReadWriteMutex
@ingroup beast_concurrent
*/
/*============================================================================*/
/**
Scoped read lock for ReadWriteMutex.
@ingroup beast_concurrent
*/
template <class LockType>
struct GenericScopedReadLock : Uncopyable
{
inline explicit GenericScopedReadLock (LockType const& lock) noexcept
:
m_lock (lock)
{
m_lock.enterRead ();
}
inline ~GenericScopedReadLock () noexcept
{
m_lock.exitRead ();
}
private:
LockType const& m_lock;
};
/*============================================================================*/
/**
Scoped write lock for ReadWriteMutex.
@ingroup beast_concurrent
*/
template <class LockType>
struct GenericScopedWriteLock : Uncopyable
{
inline explicit GenericScopedWriteLock (LockType const& lock) noexcept
:
m_lock (lock)
{
m_lock.enterWrite ();
}
inline ~GenericScopedWriteLock () noexcept
{
m_lock.exitWrite ();
}
private:
LockType const& m_lock;
};
class ReadWriteMutex
{
public:
/** Provides the type of scoped read lock to use with a ReadWriteMutex. */
typedef GenericScopedReadLock <ReadWriteMutex> ScopedReadLockType;
/** Provides the type of scoped write lock to use with a ReadWriteMutex. */
typedef GenericScopedWriteLock <ReadWriteMutex> ScopedWriteLockType;
/** Create a ReadWriteMutex */
ReadWriteMutex () noexcept;
/** Destroy a ReadWriteMutex
If the object is destroyed while a lock is held, the result is
undefined behavior.
*/
~ReadWriteMutex () noexcept;
/** Acquire a read lock.
This is recursive with respect to other read locks. Calling this while
holding a write lock is undefined.
*/
void enterRead () const noexcept;
/** Release a previously acquired read lock */
void exitRead () const noexcept;
/** Acquire a write lock.
This is recursive with respect to other write locks. Calling this while
holding a read lock is undefined.
*/
void enterWrite () const noexcept;
/** Release a previously acquired write lock */
void exitWrite () const noexcept;
private:
CriticalSection m_mutex;
mutable CacheLine::Padded <AtomicCounter> m_writes;
mutable CacheLine::Padded <AtomicCounter> m_readers;
};
#endif

View File

@@ -1,117 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
Semaphore::WaitingThread::WaitingThread ()
: m_event (false) // auto-reset
{
}
void Semaphore::WaitingThread::wait ()
{
m_event.wait ();
}
void Semaphore::WaitingThread::signal ()
{
m_event.signal ();
}
//==============================================================================
Semaphore::Semaphore (int initialCount)
: m_counter (initialCount)
{
}
Semaphore::~Semaphore ()
{
// Can't delete the semaphore while threads are waiting on it!!
bassert (m_waitingThreads.pop_front () == nullptr);
for (;;)
{
WaitingThread* waitingThread = m_deleteList.pop_front ();
if (waitingThread != nullptr)
delete waitingThread;
else
break;
}
}
void Semaphore::signal (int amount)
{
bassert (amount > 0);
while (amount--)
{
// Make counter and list operations atomic.
LockType::ScopedLockType lock (m_mutex);
if (++m_counter <= 0)
{
WaitingThread* waitingThread = m_waitingThreads.pop_front ();
bassert (waitingThread != nullptr);
waitingThread->signal ();
}
}
}
void Semaphore::wait ()
{
// Always prepare the WaitingThread object first, either
// from the delete list or through a new allocation.
//
WaitingThread* waitingThread = m_deleteList.pop_front ();
if (waitingThread == nullptr)
waitingThread = new WaitingThread;
{
// Make counter and list operations atomic.
LockType::ScopedLockType lock (m_mutex);
if (--m_counter >= 0)
{
// Acquired the resource so put waitingThread back.
m_deleteList.push_front (waitingThread);
waitingThread = nullptr;
}
else
{
// Out of resources, go on to the waiting list.
m_waitingThreads.push_front (waitingThread);
}
}
// Do we need to wait?
if (waitingThread != nullptr)
{
// Yes so do it.
waitingThread->wait ();
// If the wait is satisfied, then we've been taken off the
// waiting list so put waitingThread back in the delete list.
//
m_deleteList.push_front (waitingThread);
}
}

View File

@@ -1,78 +0,0 @@
//------------------------------------------------------------------------------
/*
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_SEMAPHORE_BEASTHEADER
#define BEAST_SEMAPHORE_BEASTHEADER
/*============================================================================*/
/**
A semaphore.
This provides a traditional semaphore synchronization primitive. There is no
upper limit on the number of signals.
@note There is no tryWait() or timeout facility for acquiring a resource.
@ingroup beast_core
*/
class Semaphore
{
public:
/** Create a semaphore with the specified number of resources.
@param initialCount The starting number of resources.
*/
explicit Semaphore (int initialCount);
~Semaphore ();
/** Increase the number of available resources.
@param amount The number of new resources available.
*/
void signal (int amount = 1);
/** Wait for a resource.
*/
void wait ();
private:
class WaitingThread
: public LockFreeStack <WaitingThread>::Node
, LeakChecked <WaitingThread>
{
public:
WaitingThread ();
void wait ();
void signal ();
private:
WaitableEvent m_event;
};
typedef SpinLock LockType;
LockType m_mutex;
Atomic <int> m_counter;
LockFreeStack <WaitingThread> m_waitingThreads;
LockFreeStack <WaitingThread> m_deleteList;
};
#endif

View File

@@ -1,71 +0,0 @@
//------------------------------------------------------------------------------
/*
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_SERIALFOR_BEASTHEADER
#define BEAST_SERIALFOR_BEASTHEADER
/*============================================================================*/
/** Serial for loop.
Iterates a for loop sequentially. This is a drop in replacement for
ParallelFor.
@see ParallelFor
@ingroup beast_core
*/
class SerialFor : Uncopyable
{
public:
/** Create a serial for loop.
*/
inline SerialFor ()
{
}
/** Determine the number of threads used to process loops.
@return Always 1.
*/
inline int getNumberOfThreads () const
{
return 1;
}
template <class F>
inline void operator () (int numberOfIterations)
{
F f;
for (int i = 0; i < numberOfIterations; ++i)
f (i);
}
template <class F, class T1>
inline void operator () (int numberOfIterations, T1 t1)
{
F f (t1);
for (int i = 0; i < numberOfIterations; ++i)
f (i);
}
};
#endif

View File

@@ -1,36 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
SharedObject::ThreadedScope::ThreadedScope (char const* name)
: m_thread (name)
{
m_thread.start (this);
}
void SharedObject::ThreadedScope::destroySharedObject (SharedObject* const object)
{
deleteAsync (object);
}
//------------------------------------------------------------------------------
void SharedObject::destroySharedObject ()
{
delete this;
}

View File

@@ -1,310 +0,0 @@
//------------------------------------------------------------------------------
/*
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_SHAREDOBJECT_BEASTHEADER
#define BEAST_SHAREDOBJECT_BEASTHEADER
//==============================================================================
/**
A reference counted object with overridable destroy behavior.
This is a reference counted object compatible with SharedObjectPtr or
ReferenceCountedObjectPtr. When the last reference is removed, an
overridable virtual function is called to destroy the object. The default
behavior simply calls operator delete. Overrides can perform more complex
dispose actions, typically to destroy the object on a separate thread.
@ingroup beast_concurrent
*/
class SharedObject : Uncopyable
{
public:
/** Abstract SharedObject scope.
The scope is invoked to destroy the object.
*/
class Scope
{
public:
virtual ~Scope () { }
virtual void destroySharedObject (SharedObject* const object) = 0;
};
public:
/** Separate thread for a SharedObject scope.
This Scope deletes the shared object on a separate provided thread.
*/
class ThreadedScope
: public Scope
, private ThreadWithCallQueue::EntryPoints
{
public:
/** Create a ThreadedScope.
@param name The name of the provided thread, for diagnostics.
*/
explicit ThreadedScope (char const* name);
void destroySharedObject (SharedObject* const object);
/** Delete a dynamic object asynchronously.
This convenient template will delete a dynamically allocated
object on the provided thread.
*/
template <class Object>
void deleteAsync (Object* const object)
{
// If an object being deleted recursively triggers async deletes,
// it is possible that the call queue has already been closed.
// We detect this condition by checking the associated thread and
// doing the delete directly.
//
if (m_thread.isAssociatedWithCurrentThread ())
delete object;
else
m_thread.callf (Delete <Object> (object));
}
private:
// Simple functor to delete an object.
//
template <class Object>
struct Delete
{
Delete (Object* const object) : m_object (object)
{
}
void operator () ()
{
delete m_object;
}
private:
Delete& operator= (Delete const&);
Object* const m_object;
};
private:
ThreadWithCallQueue m_thread;
};
protected:
/** Construct a SharedObject.
The constructor is protected to require subclassing.
*/
SharedObject () { }
virtual ~SharedObject () { }
/** Delete the object.
The default behavior calls operator delete.
*/
virtual void destroySharedObject ();
public:
/** Increment the reference count.
It should not be necessary to call this function directly. Use one of
the RAII containers that manages the reference count to hold the
object instead.
*/
inline void incReferenceCount () noexcept
{
m_refs.addref ();
}
/** Decrement the reference count.
It should not be necessary to call this function directly. Use one of
the RAII containers that manages the reference count to hold the
object instead.
*/
inline void decReferenceCount () noexcept
{
if (m_refs.release ())
destroySharedObject ();
}
private:
AtomicCounter m_refs;
};
//------------------------------------------------------------------------------
/** RAII container for SharedObject.
This container is used to hold a pointer to a SharedObject and manage the
reference counts for you.
*/
template <class Object>
class SharedObjectPtr
{
public:
typedef Object ReferencedType;
inline SharedObjectPtr () noexcept
:
m_object (nullptr)
{
}
inline SharedObjectPtr (Object* const refCountedObject) noexcept
:
m_object (refCountedObject)
{
if (refCountedObject != nullptr)
refCountedObject->incReferenceCount ();
}
inline SharedObjectPtr (const SharedObjectPtr& other) noexcept
:
m_object (other.m_object)
{
if (m_object != nullptr)
m_object->incReferenceCount ();
}
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
inline SharedObjectPtr (SharedObjectPtr&& other) noexcept
:
m_object (other.m_object)
{
other.m_object = nullptr;
}
#endif
template <class DerivedClass>
inline SharedObjectPtr (const SharedObjectPtr <DerivedClass>& other) noexcept
:
m_object (static_cast <Object*> (other.get ()))
{
if (m_object != nullptr)
m_object->incReferenceCount ();
}
SharedObjectPtr& operator= (const SharedObjectPtr& other)
{
return operator= (other.m_object);
}
template <class DerivedClass>
SharedObjectPtr& operator= (const SharedObjectPtr <DerivedClass>& other)
{
return operator= (static_cast <Object*> (other.get ()));
}
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
SharedObjectPtr& operator= (SharedObjectPtr && other)
{
std::swap (m_object, other.m_object);
return *this;
}
#endif
SharedObjectPtr& operator= (Object* const newObject)
{
if (m_object != newObject)
{
if (newObject != nullptr)
newObject->incReferenceCount ();
Object* const oldObject = m_object;
m_object = newObject;
if (oldObject != nullptr)
oldObject->decReferenceCount ();
}
return *this;
}
inline ~SharedObjectPtr ()
{
if (m_object != nullptr)
m_object->decReferenceCount ();
}
inline operator Object* () const noexcept
{
return m_object;
}
inline Object* operator-> () const noexcept
{
return m_object;
}
inline Object* get () const noexcept
{
return m_object;
}
inline Object* getObject () const noexcept
{
return m_object;
}
private:
Object* m_object;
};
template <class Object>
bool operator== (const SharedObjectPtr <Object>& object1, Object* const object2) noexcept
{
return object1.get () == object2;
}
template <class Object>
bool operator== (const SharedObjectPtr <Object>& object1, const SharedObjectPtr <Object>& object2) noexcept
{
return object1.get () == object2.get ();
}
template <class Object>
bool operator== (Object* object1, SharedObjectPtr <Object>& object2) noexcept
{
return object1 == object2.get ();
}
template <class Object>
bool operator!= (const SharedObjectPtr <Object>& object1, const Object* object2) noexcept
{
return object1.get () != object2;
}
template <class Object>
bool operator!= (const SharedObjectPtr <Object>& object1, SharedObjectPtr <Object>& object2) noexcept
{
return object1.get () != object2.get ();
}
template <class Object>
bool operator!= (Object* object1, SharedObjectPtr <Object>& object2) noexcept
{
return object1 != object2.get ();
}
#endif

View File

@@ -1,44 +0,0 @@
//------------------------------------------------------------------------------
/*
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 SpinDelay
{
public:
SpinDelay () : m_count (0)
{
}
inline void pause ()
{
if (++m_count > 20)
Thread::yield ();
}
private:
int m_count;
};
#endif

View File

@@ -1,105 +0,0 @@
//------------------------------------------------------------------------------
/*
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 ThreadGroup::QuitType::operator () (Worker* worker)
{
worker->setShouldExit ();
}
//==============================================================================
ThreadGroup::Worker::Worker (String name, ThreadGroup& group)
: Thread (name)
, m_group (group)
, m_shouldExit (false)
{
startThread ();
}
ThreadGroup::Worker::~Worker ()
{
// Make sure the thread is stopped.
stopThread (-1);
}
void ThreadGroup::Worker::setShouldExit ()
{
m_shouldExit = true;
}
void ThreadGroup::Worker::run ()
{
do
{
m_group.m_semaphore.wait ();
Work* work = m_group.m_queue.pop_front ();
bassert (work != nullptr);
work->operator () (this);
delete work;
}
while (!m_shouldExit);
}
//==============================================================================
ThreadGroup::ThreadGroup (int numberOfThreads)
: m_numberOfThreads (numberOfThreads)
, m_semaphore (0)
{
for (int i = 0; i++ < numberOfThreads; )
{
String s;
s << "ThreadGroup (" << i << ")";
m_threads.push_front (new Worker (s, *this));
}
}
ThreadGroup::~ThreadGroup ()
{
// Put one quit item in the queue for each worker to stop.
for (int i = 0; i < m_numberOfThreads; ++i)
{
m_queue.push_front (new (getAllocator ()) QuitType);
m_semaphore.signal ();
}
for (;;)
{
Worker* worker = m_threads.pop_front ();
if (worker != nullptr)
delete worker;
else
break;
}
// There must not be pending work!
bassert (m_queue.pop_front () == nullptr);
}
int ThreadGroup::getNumberOfThreads () const
{
return m_numberOfThreads;
}

View File

@@ -1,233 +0,0 @@
//------------------------------------------------------------------------------
/*
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_THREADGROUP_BEASTHEADER
#define BEAST_THREADGROUP_BEASTHEADER
/*============================================================================*/
/**
@ingroup beast_concurrent
@brief A group of threads for parallelizing tasks.
@see ParallelFor
*/
class ThreadGroup
{
public:
typedef FifoFreeStoreType AllocatorType;
/** Creates the specified number of threads.
@param numberOfThreads The number of threads in the group. This must be
greater than zero. If this parameter is omitted,
one thread is created per available CPU.
*/
explicit ThreadGroup (int numberOfThreads = SystemStats::getNumCpus ());
~ThreadGroup ();
/** Allocator access.
*/
inline AllocatorType& getAllocator ()
{
return m_allocator;
}
/** Determine the number of threads in the group.
@return The number of threads in the group.
*/
int getNumberOfThreads () const;
/** Calls a functor on multiple threads.
The specified functor is executed on some or all available threads at once.
A call is always guaranteed to execute.
@param maxThreads The maximum number of threads to use, or -1 for all.
@param f The functor to call for each thread.
*/
/** @{ */
template <class Functor>
void callf (int maxThreads, Functor f)
{
bassert (maxThreads > 0 || maxThreads == -1);
int numberOfThreads = getNumberOfThreads ();
if (maxThreads != -1 && maxThreads < numberOfThreads)
numberOfThreads = maxThreads;
while (numberOfThreads--)
{
m_queue.push_front (new (getAllocator ()) WorkType <Functor> (f));
m_semaphore.signal ();
}
}
#if BEAST_VARIADIC_MAX >= 1
template <class Fn>
void call (int maxThreads, Fn f)
{
callf (maxThreads, bind (f));
}
#endif
#if BEAST_VARIADIC_MAX >= 2
template <class Fn, class T1>
void call (int maxThreads, Fn f, T1 t1)
{
callf (maxThreads, bind (f, t1));
}
#endif
#if BEAST_VARIADIC_MAX >= 3
template <class Fn, class T1, class T2>
void call (int maxThreads, Fn f, T1 t1, T2 t2)
{
callf (maxThreads, bind (f, t1, t2));
}
#endif
#if BEAST_VARIADIC_MAX >= 4
template <class Fn, class T1, class T2, class T3>
void call (int maxThreads, Fn f, T1 t1, T2 t2, T3 t3)
{
callf (maxThreads, bind (f, t1, t2, t3));
}
#endif
#if BEAST_VARIADIC_MAX >= 5
template <class Fn, class T1, class T2, class T3, class T4>
void call (int maxThreads, Fn f, T1 t1, T2 t2, T3 t3, T4 t4)
{
callf (maxThreads, bind (f, t1, t2, t3, t4));
}
#endif
#if BEAST_VARIADIC_MAX >= 6
template <class Fn, class T1, class T2, class T3, class T4, class T5>
void call (int maxThreads, Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
callf (maxThreads, bind (f, t1, t2, t3, t4, t5));
}
#endif
#if BEAST_VARIADIC_MAX >= 7
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6>
void call (int maxThreads, Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
{
callf (maxThreads, bind (f, t1, t2, t3, t4, t5, t6));
}
#endif
#if BEAST_VARIADIC_MAX >= 8
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
void call (int maxThreads, Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
{
callf (maxThreads, bind (f, t1, t2, t3, t4, t5, t6, t7));
}
#endif
#if BEAST_VARIADIC_MAX >= 9
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
void call (int maxThreads, Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
{
callf (maxThreads, bind (f, t1, t2, t3, t4, t5, t6, t7, t8));
}
#endif
/** @} */
private:
void stopThreads (int numberOfThreadsToStop);
//============================================================================
private:
/** A thread in the group.
*/
class Worker
: public LockFreeStack <Worker>::Node
, public Thread
, LeakChecked <Worker>
{
public:
Worker (String name, ThreadGroup& group);
~Worker ();
void setShouldExit ();
private:
void run ();
private:
ThreadGroup& m_group;
bool m_shouldExit;
};
//============================================================================
private:
/** Abstract work item.
*/
class Work : public LockFreeStack <Work>::Node
, public AllocatedBy <AllocatorType>
{
public:
virtual ~Work () { }
/* The worker is passed in so we can make it quit later.
*/
virtual void operator () (Worker* worker) = 0;
};
template <class Functor>
class WorkType : public Work, LeakChecked <WorkType <Functor> >
{
public:
explicit WorkType (Functor const& f) : m_f (f) { }
~WorkType () { }
void operator () (Worker*)
{
m_f ();
}
private:
Functor m_f;
};
/** Used to make a Worker stop
*/
class QuitType
: public Work
, LeakChecked <QuitType>
{
public:
void operator () (Worker* worker);
};
private:
int const m_numberOfThreads;
Semaphore m_semaphore;
AllocatorType m_allocator;
LockFreeStack <Work> m_queue;
LockFreeStack <Worker> m_threads;
};
#endif

View File

@@ -1,145 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
ThreadWithCallQueue::ThreadWithCallQueue (String name)
: CallQueue (name)
, m_thread (name)
, m_entryPoints (nullptr)
, m_calledStart (false)
, m_calledStop (false)
, m_shouldStop (false)
{
}
ThreadWithCallQueue::~ThreadWithCallQueue ()
{
stop (true);
}
void ThreadWithCallQueue::start (EntryPoints* const entryPoints)
{
{
// This is mostly for diagnostics
// TODO: Atomic flag for this whole thing
CriticalSection::ScopedLockType lock (m_mutex);
// start() MUST be called.
bassert (!m_calledStart);
m_calledStart = true;
}
m_entryPoints = entryPoints;
m_thread.start (this);
}
void ThreadWithCallQueue::stop (bool const wait)
{
// can't call stop(true) from within a thread function
bassert (!wait || !m_thread.isTheCurrentThread ());
{
CriticalSection::ScopedLockType lock (m_mutex);
// start() MUST be called.
bassert (m_calledStart);
// TODO: Atomic for this
if (!m_calledStop)
{
m_calledStop = true;
{
CriticalSection::ScopedUnlockType unlock (m_mutex); // getting fancy
call (&ThreadWithCallQueue::doStop, this);
// in theory something could slip in here
close ();
}
}
}
if (wait)
m_thread.join ();
}
// Should be called periodically by the idle function.
// There are three possible results:
//
// #1 Returns false. The idle function may continue or return.
// #2 Returns true. The idle function should return as soon as possible.
// #3 Throws a Thread::Interruption exception.
//
// If interruptionPoint returns true or throws, it must
// not be called again before the thread has the opportunity to reset.
//
bool ThreadWithCallQueue::interruptionPoint ()
{
return m_thread.interruptionPoint ();
}
// Interrupts the idle function by queueing a call that does nothing.
void ThreadWithCallQueue::interrupt ()
{
call (&ThreadWithCallQueue::doNothing);
}
void ThreadWithCallQueue::doNothing ()
{
// Intentionally empty
}
void ThreadWithCallQueue::signal ()
{
m_thread.interrupt ();
}
void ThreadWithCallQueue::reset ()
{
}
void ThreadWithCallQueue::doStop ()
{
m_shouldStop = true;
}
void ThreadWithCallQueue::threadRun ()
{
m_entryPoints->threadInit ();
for (;;)
{
CallQueue::synchronize ();
if (m_shouldStop)
break;
bool interrupted = m_entryPoints->threadIdle ();
if (!interrupted)
interrupted = interruptionPoint ();
if (!interrupted)
m_thread.wait ();
}
m_entryPoints->threadExit ();
}

View File

@@ -1,144 +0,0 @@
//------------------------------------------------------------------------------
/*
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_THREADWITHCALLQUEUE_BEASTHEADER
#define BEAST_THREADWITHCALLQUEUE_BEASTHEADER
/*============================================================================*/
/**
An InterruptibleThread with a CallQueue.
This combines an InterruptibleThread with a CallQueue, allowing functors to
be queued for asynchronous execution on the thread.
The thread runs an optional user-defined idle function, which must regularly
check for an interruption using the InterruptibleThread interface. When an
interruption is signaled, the idle function returns and the CallQueue is
synchronized. Then, the idle function is resumed.
When the ThreadWithCallQueue first starts up, an optional user-defined
initialization function is executed on the thread. When the thread exits,
a user-defined exit function may be executed on the thread.
@see CallQueue
@ingroup beast_concurrent
*/
class ThreadWithCallQueue
: public CallQueue
, private InterruptibleThread::EntryPoint
{
public:
/** Entry points for a ThreadWithCallQueue.
*/
class EntryPoints
{
public:
virtual ~EntryPoints () { }
virtual void threadInit () { }
virtual void threadExit () { }
virtual bool threadIdle ()
{
bool interrupted = false;
return interrupted;
}
};
/** Create a thread.
@param name The name of the InterruptibleThread and CallQueue, used
for diagnostics when debugging.
*/
explicit ThreadWithCallQueue (String name);
/** Destroy a ThreadWithCallQueue.
If the thread is still running it is stopped. The destructor blocks
until the thread exits cleanly.
*/
~ThreadWithCallQueue ();
/** Start the thread.
*/
void start (EntryPoints* const entryPoints);
/* Stop the thread.
Stops the thread and optionally wait until it exits. It is safe to call
this function at any time and as many times as desired.
After a call to stop () the CallQueue is closed, and attempts to queue new
functors will throw a runtime exception. Existing functors will still
execute.
Any listeners registered on the CallQueue need to be removed
before stop is called
@invariant The caller is not on the associated thread.
@param wait `true` if the function should wait until the thread exits
before returning.
*/
void stop (bool const wait);
/**
Determine if the thread needs interruption.
Should be called periodically by the idle function. If interruptionPoint
returns true or throws, it must not be called again until the idle function
returns and is re-entered.
@invariant No previous calls to interruptionPoint() made after the idle
function entry point returned `true`.
@return `false` if the idle function may continue, or `true` if the
idle function must return as soon as possible.
*/
bool interruptionPoint ();
/* Interrupts the idle function.
*/
void interrupt ();
private:
static void doNothing ();
void signal ();
void reset ();
void doStop ();
void threadRun ();
private:
InterruptibleThread m_thread;
EntryPoints* m_entryPoints;
bool m_calledStart;
bool m_calledStop;
bool m_shouldStop;
CriticalSection m_mutex;
};
#endif

View File

@@ -1,216 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#if defined (BEAST_CORE_BEASTHEADER) && ! BEAST_AMALGAMATED_INCLUDE
/* When you add this cpp file to your project, you mustn't include it in a file where you've
already included any other headers - just put it inside a file on its own, possibly with your config
flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix
header files that the compiler may be using.
*/
#error "Incorrect use of BEAST cpp file"
#endif
// Your project must contain a BeastConfig.h file with your project-specific settings in it,
// and your header search path must make it accessible to the module's files.
#include "BeastConfig.h"
//==============================================================================
#include "native/beast_BasicNativeHeaders.h"
#include "beast_core.h"
#include <locale>
#include <cctype>
#if ! BEAST_BSD
#include <sys/timeb.h>
#endif
#if ! BEAST_ANDROID
#include <cwctype>
#endif
#if BEAST_WINDOWS
#include <ctime>
#include <winsock2.h>
#include <ws2tcpip.h>
#if ! BEAST_MINGW
#include <Dbghelp.h>
#if ! BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
#pragma comment (lib, "DbgHelp.lib")
#endif
#endif
#if BEAST_MINGW
#include <ws2spi.h>
#endif
#else
#if BEAST_LINUX || BEAST_ANDROID
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <unistd.h>
#include <netinet/in.h>
#endif
#if BEAST_LINUX
#include <langinfo.h>
#endif
#include <pwd.h>
#include <fcntl.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <sys/time.h>
#include <net/if.h>
#include <sys/ioctl.h>
#if ! BEAST_ANDROID && ! BEAST_BSD
#include <execinfo.h>
#endif
#endif
#if BEAST_MAC || BEAST_IOS
#include <xlocale.h>
#include <mach/mach.h>
#endif
#if BEAST_ANDROID
#include <android/log.h>
#endif
//==============================================================================
namespace beast
{
#include "containers/beast_AbstractFifo.cpp"
#include "containers/beast_DynamicObject.cpp"
#include "containers/beast_NamedValueSet.cpp"
#include "containers/beast_PropertySet.cpp"
#include "containers/beast_Variant.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"
#include "streams/beast_MemoryInputStream.cpp"
#include "streams/beast_MemoryOutputStream.cpp"
#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"
#include "text/beast_StringArray.cpp"
#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_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"
//==============================================================================
#if BEAST_MAC || BEAST_IOS
#include "native/beast_osx_ObjCHelpers.h"
#endif
#if BEAST_ANDROID
#include "native/beast_android_JNIHelpers.h"
#endif
#if ! BEAST_WINDOWS
#include "native/beast_posix_SharedCode.h"
#include "native/beast_posix_NamedPipe.cpp"
#endif
//==============================================================================
#if BEAST_MAC || BEAST_IOS
#include "native/beast_mac_Files.mm"
#include "native/beast_mac_Network.mm"
#include "native/beast_mac_Strings.mm"
#include "native/beast_mac_SystemStats.mm"
#include "native/beast_mac_Threads.mm"
//==============================================================================
#elif BEAST_WINDOWS
#include "native/beast_win32_ComSmartPtr.h"
#include "native/beast_win32_Files.cpp"
#include "native/beast_win32_Network.cpp"
#include "native/beast_win32_Registry.cpp"
#include "native/beast_win32_SystemStats.cpp"
#include "native/beast_win32_Threads.cpp"
//==============================================================================
#elif BEAST_LINUX
#include "native/beast_linux_Files.cpp"
#include "native/beast_linux_Network.cpp"
#include "native/beast_linux_SystemStats.cpp"
#include "native/beast_linux_Threads.cpp"
//==============================================================================
#elif BEAST_ANDROID
#include "native/beast_android_Files.cpp"
#include "native/beast_android_Misc.cpp"
#include "native/beast_android_Network.cpp"
#include "native/beast_android_SystemStats.cpp"
#include "native/beast_android_Threads.cpp"
#endif
#include "threads/beast_HighResolutionTimer.cpp"
}

View File

@@ -1,440 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_CORE_BEASTHEADER
#define BEAST_CORE_BEASTHEADER
#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
#endif
//==============================================================================
#include "system/beast_TargetPlatform.h"
//=============================================================================
/** Config: BEAST_FORCE_DEBUG
Normally, BEAST_DEBUG is set to 1 or 0 based on compiler and project settings,
but if you define this value, you can override this to force it to be true or false.
*/
#ifndef BEAST_FORCE_DEBUG
//#define BEAST_FORCE_DEBUG 0
#endif
//=============================================================================
/** 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
#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
#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
#endif
#ifndef BEAST_ZLIB_INCLUDE_PATH
#define BEAST_ZLIB_INCLUDE_PATH <zlib.h>
#endif
/* Config: BEAST_CATCH_UNHANDLED_EXCEPTIONS
If enabled, this will add some exception-catching code to forward unhandled exceptions
to your BEASTApplication::unhandledException() callback.
*/
#ifndef BEAST_CATCH_UNHANDLED_EXCEPTIONS
//#define BEAST_CATCH_UNHANDLED_EXCEPTIONS 1
#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
#endif
#include "system/beast_StandardHeader.h"
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
}
#if BEAST_MSVC
#pragma warning (pop)
#endif
#endif // BEAST_CORE_BEASTHEADER

View File

@@ -1,24 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "beast_core.cpp"

View File

@@ -1,229 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
AbstractFifo::AbstractFifo (const int capacity) noexcept
: bufferSize (capacity)
{
bassert (bufferSize > 0);
}
AbstractFifo::~AbstractFifo() {}
int AbstractFifo::getTotalSize() const noexcept { return bufferSize; }
int AbstractFifo::getFreeSpace() const noexcept { return bufferSize - getNumReady(); }
int AbstractFifo::getNumReady() const noexcept
{
const int vs = validStart.get();
const int ve = validEnd.get();
return ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
}
void AbstractFifo::reset() noexcept
{
validEnd = 0;
validStart = 0;
}
void AbstractFifo::setTotalSize (int newSize) noexcept
{
bassert (newSize > 0);
reset();
bufferSize = newSize;
}
//==============================================================================
void AbstractFifo::prepareToWrite (int numToWrite, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept
{
const int vs = validStart.get();
const int ve = validEnd.value;
const int freeSpace = ve >= vs ? (bufferSize - (ve - vs)) : (vs - ve);
numToWrite = bmin (numToWrite, freeSpace - 1);
if (numToWrite <= 0)
{
startIndex1 = 0;
startIndex2 = 0;
blockSize1 = 0;
blockSize2 = 0;
}
else
{
startIndex1 = ve;
startIndex2 = 0;
blockSize1 = bmin (bufferSize - ve, numToWrite);
numToWrite -= blockSize1;
blockSize2 = numToWrite <= 0 ? 0 : bmin (numToWrite, vs);
}
}
void AbstractFifo::finishedWrite (int numWritten) noexcept
{
bassert (numWritten >= 0 && numWritten < bufferSize);
int newEnd = validEnd.value + numWritten;
if (newEnd >= bufferSize)
newEnd -= bufferSize;
validEnd = newEnd;
}
void AbstractFifo::prepareToRead (int numWanted, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept
{
const int vs = validStart.value;
const int ve = validEnd.get();
const int numReady = ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
numWanted = bmin (numWanted, numReady);
if (numWanted <= 0)
{
startIndex1 = 0;
startIndex2 = 0;
blockSize1 = 0;
blockSize2 = 0;
}
else
{
startIndex1 = vs;
startIndex2 = 0;
blockSize1 = bmin (bufferSize - vs, numWanted);
numWanted -= blockSize1;
blockSize2 = numWanted <= 0 ? 0 : bmin (numWanted, ve);
}
}
void AbstractFifo::finishedRead (int numRead) noexcept
{
bassert (numRead >= 0 && numRead <= bufferSize);
int newStart = validStart.value + numRead;
if (newStart >= bufferSize)
newStart -= bufferSize;
validStart = newStart;
}
//==============================================================================
//==============================================================================
#if BEAST_UNIT_TESTS
class AbstractFifoTests : public UnitTest
{
public:
AbstractFifoTests() : UnitTest ("Abstract Fifo") {}
class WriteThread : public Thread
{
public:
WriteThread (AbstractFifo& fifo_, int* buffer_)
: Thread ("fifo writer"), fifo (fifo_), buffer (buffer_)
{
startThread();
}
~WriteThread()
{
stopThread (5000);
}
void run()
{
int n = 0;
Random r;
while (! threadShouldExit())
{
int num = r.nextInt (2000) + 1;
int start1, size1, start2, size2;
fifo.prepareToWrite (num, start1, size1, start2, size2);
bassert (size1 >= 0 && size2 >= 0);
bassert (size1 == 0 || (start1 >= 0 && start1 < fifo.getTotalSize()));
bassert (size2 == 0 || (start2 >= 0 && start2 < fifo.getTotalSize()));
for (int i = 0; i < size1; ++i)
buffer [start1 + i] = n++;
for (int i = 0; i < size2; ++i)
buffer [start2 + i] = n++;
fifo.finishedWrite (size1 + size2);
}
}
private:
AbstractFifo& fifo;
int* buffer;
};
void runTest()
{
beginTest ("AbstractFifo");
int buffer [5000];
AbstractFifo fifo (numElementsInArray (buffer));
WriteThread writer (fifo, buffer);
int n = 0;
Random r;
for (int count = 100000; --count >= 0;)
{
int num = r.nextInt (6000) + 1;
int start1, size1, start2, size2;
fifo.prepareToRead (num, start1, size1, start2, size2);
if (! (size1 >= 0 && size2 >= 0)
&& (size1 == 0 || (start1 >= 0 && start1 < fifo.getTotalSize()))
&& (size2 == 0 || (start2 >= 0 && start2 < fifo.getTotalSize())))
{
expect (false, "prepareToRead returned -ve values");
break;
}
bool failed = false;
for (int i = 0; i < size1; ++i)
failed = (buffer [start1 + i] != n++) || failed;
for (int i = 0; i < size2; ++i)
failed = (buffer [start2 + i] != n++) || failed;
if (failed)
{
expect (false, "read values were incorrect");
break;
}
fifo.finishedRead (size1 + size2);
}
}
};
static AbstractFifoTests fifoUnitTests;
#endif

View File

@@ -1,217 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#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.
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.
e.g.
@code
class MyFifo
{
public:
MyFifo() : abstractFifo (1024)
{
}
void addToFifo (const int* someData, int numItems)
{
int start1, size1, start2, size2;
abstractFifo.prepareToWrite (numItems, start1, size1, start2, size2);
if (size1 > 0)
copySomeData (myBuffer + start1, someData, size1);
if (size2 > 0)
copySomeData (myBuffer + start2, someData + size1, size2);
abstractFifo.finishedWrite (size1 + size2);
}
void readFromFifo (int* someData, int numItems)
{
int start1, size1, start2, size2;
abstractFifo.prepareToRead (numSamples, start1, size1, start2, size2);
if (size1 > 0)
copySomeData (someData, myBuffer + start1, size1);
if (size2 > 0)
copySomeData (someData + size1, myBuffer + start2, size2);
abstractFifo.finishedRead (size1 + size2);
}
private:
AbstractFifo abstractFifo;
int myBuffer [1024];
};
@endcode
*/
class BEAST_API AbstractFifo
{
public:
//==============================================================================
/** Creates a FIFO to manage a buffer with the specified capacity. */
AbstractFifo (int capacity) noexcept;
/** Destructor */
~AbstractFifo();
//==============================================================================
/** Returns the total size of the buffer being managed. */
int getTotalSize() const noexcept;
/** Returns the number of items that can currently be added to the buffer without it overflowing. */
int getFreeSpace() const noexcept;
/** Returns the number of items that can currently be read from the buffer. */
int getNumReady() const noexcept;
/** Clears the buffer positions, so that it appears empty. */
void reset() noexcept;
/** Changes the buffer's total size.
Note that this isn't thread-safe, so don't call it if there's any danger that it
might overlap with a call to any other method in this class!
*/
void setTotalSize (int newSize) noexcept;
//==============================================================================
/** Returns the location within the buffer at which an incoming block of data should be written.
Because the section of data that you want to add to the buffer may overlap the end
and wrap around to the start, two blocks within your buffer are returned, and you
should copy your data into the first one, with any remaining data spilling over into
the second.
If the number of items you ask for is too large to fit within the buffer's free space, then
blockSize1 + blockSize2 may add up to a lower value than numToWrite. If this happens, you
may decide to keep waiting and re-trying the method until there's enough space available.
After calling this method, if you choose to write your data into the blocks returned, you
must call finishedWrite() to tell the FIFO how much data you actually added.
e.g.
@code
void addToFifo (const int* someData, int numItems)
{
int start1, size1, start2, size2;
prepareToWrite (numItems, start1, size1, start2, size2);
if (size1 > 0)
copySomeData (myBuffer + start1, someData, size1);
if (size2 > 0)
copySomeData (myBuffer + start2, someData + size1, size2);
finishedWrite (size1 + size2);
}
@endcode
@param numToWrite indicates how many items you'd like to add to the buffer
@param startIndex1 on exit, this will contain the start index in your buffer at which your data should be written
@param blockSize1 on exit, this indicates how many items can be written to the block starting at startIndex1
@param startIndex2 on exit, this will contain the start index in your buffer at which any data that didn't fit into
the first block should be written
@param blockSize2 on exit, this indicates how many items can be written to the block starting at startIndex2
@see finishedWrite
*/
void prepareToWrite (int numToWrite, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept;
/** Called after writing from the FIFO, to indicate that this many items have been added.
@see prepareToWrite
*/
void finishedWrite (int numWritten) noexcept;
/** Returns the location within the buffer from which the next block of data should be read.
Because the section of data that you want to read from the buffer may overlap the end
and wrap around to the start, two blocks within your buffer are returned, and you
should read from both of them.
If the number of items you ask for is greater than the amount of data available, then
blockSize1 + blockSize2 may add up to a lower value than numWanted. If this happens, you
may decide to keep waiting and re-trying the method until there's enough data available.
After calling this method, if you choose to read the data, you must call finishedRead() to
tell the FIFO how much data you have consumed.
e.g.
@code
void readFromFifo (int* someData, int numItems)
{
int start1, size1, start2, size2;
prepareToRead (numSamples, start1, size1, start2, size2);
if (size1 > 0)
copySomeData (someData, myBuffer + start1, size1);
if (size2 > 0)
copySomeData (someData + size1, myBuffer + start2, size2);
finishedRead (size1 + size2);
}
@endcode
@param numWanted indicates how many items you'd like to add to the buffer
@param startIndex1 on exit, this will contain the start index in your buffer at which your data should be written
@param blockSize1 on exit, this indicates how many items can be written to the block starting at startIndex1
@param startIndex2 on exit, this will contain the start index in your buffer at which any data that didn't fit into
the first block should be written
@param blockSize2 on exit, this indicates how many items can be written to the block starting at startIndex2
@see finishedRead
*/
void prepareToRead (int numWanted, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept;
/** Called after reading from the FIFO, to indicate that this many items have now been consumed.
@see prepareToRead
*/
void finishedRead (int numRead) noexcept;
private:
//==============================================================================
int bufferSize;
Atomic <int> validStart, validEnd;
BEAST_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AbstractFifo)
};
#endif // BEAST_ABSTRACTFIFO_BEASTHEADER

File diff suppressed because it is too large Load Diff

View File

@@ -1,133 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_ARRAYALLOCATIONBASE_BEASTHEADER
#define BEAST_ARRAYALLOCATIONBASE_BEASTHEADER
#include "../memory/beast_HeapBlock.h"
//==============================================================================
/**
Implements some basic array storage allocation functions.
This class isn't really for public use - it's used by the other
array classes, but might come in handy for some purposes.
It inherits from a critical section class to allow the arrays to use
the "empty base class optimisation" pattern to reduce their footprint.
@see Array, OwnedArray, ReferenceCountedArray
*/
template <class ElementType, class TypeOfCriticalSectionToUse>
class ArrayAllocationBase : public TypeOfCriticalSectionToUse
{
public:
//==============================================================================
/** Creates an empty array. */
ArrayAllocationBase() noexcept
: numAllocated (0)
{
}
/** Destructor. */
~ArrayAllocationBase() noexcept
{
}
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
ArrayAllocationBase (ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&& other) noexcept
: elements (static_cast <HeapBlock <ElementType>&&> (other.elements)),
numAllocated (other.numAllocated)
{
}
ArrayAllocationBase& operator= (ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&& other) noexcept
{
elements = static_cast <HeapBlock <ElementType>&&> (other.elements);
numAllocated = other.numAllocated;
return *this;
}
#endif
//==============================================================================
/** Changes the amount of storage allocated.
This will retain any data currently held in the array, and either add or
remove extra space at the end.
@param numElements the number of elements that are needed
*/
void setAllocatedSize (const int numElements)
{
if (numAllocated != numElements)
{
if (numElements > 0)
elements.realloc ((size_t) numElements);
else
elements.free();
numAllocated = numElements;
}
}
/** Increases the amount of storage allocated if it is less than a given amount.
This will retain any data currently held in the array, but will add
extra space at the end to make sure there it's at least as big as the size
passed in. If it's already bigger, no action is taken.
@param minNumElements the minimum number of elements that are needed
*/
void ensureAllocatedSize (const int minNumElements)
{
if (minNumElements > numAllocated)
setAllocatedSize ((minNumElements + minNumElements / 2 + 8) & ~7);
}
/** Minimises the amount of storage allocated so that it's no more than
the given number of elements.
*/
void shrinkToNoMoreThan (const int maxNumElements)
{
if (maxNumElements < numAllocated)
setAllocatedSize (maxNumElements);
}
/** Swap the contents of two objects. */
void swapWith (ArrayAllocationBase <ElementType, TypeOfCriticalSectionToUse>& other) noexcept
{
elements.swapWith (other.elements);
std::swap (numAllocated, other.numAllocated);
}
//==============================================================================
HeapBlock <ElementType> elements;
int numAllocated;
private:
BEAST_DECLARE_NON_COPYABLE (ArrayAllocationBase)
};
#endif // BEAST_ARRAYALLOCATIONBASE_BEASTHEADER

View File

@@ -1,74 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
DynamicObject::DynamicObject()
{
}
DynamicObject::~DynamicObject()
{
}
bool DynamicObject::hasProperty (const Identifier& propertyName) const
{
const var* const v = properties.getVarPointer (propertyName);
return v != nullptr && ! v->isMethod();
}
var DynamicObject::getProperty (const Identifier& propertyName) const
{
return properties [propertyName];
}
void DynamicObject::setProperty (const Identifier& propertyName, const var& newValue)
{
properties.set (propertyName, newValue);
}
void DynamicObject::removeProperty (const Identifier& propertyName)
{
properties.remove (propertyName);
}
bool DynamicObject::hasMethod (const Identifier& methodName) const
{
return getProperty (methodName).isMethod();
}
var DynamicObject::invokeMethod (const Identifier& methodName,
const var* parameters,
int numParameters)
{
return properties [methodName].invokeMethod (this, parameters, numParameters);
}
void DynamicObject::setMethod (const Identifier& name,
var::MethodFunction methodFunction)
{
properties.set (name, var (methodFunction));
}
void DynamicObject::clear()
{
properties.clear();
}

View File

@@ -1,121 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_DYNAMICOBJECT_BEASTHEADER
#define BEAST_DYNAMICOBJECT_BEASTHEADER
#include "beast_NamedValueSet.h"
#include "../memory/beast_ReferenceCountedObject.h"
//==============================================================================
/**
Represents a dynamically implemented object.
This class is primarily intended for wrapping scripting language objects,
but could be used for other purposes.
An instance of a DynamicObject can be used to store named properties, and
by subclassing hasMethod() and invokeMethod(), you can give your object
methods.
*/
class BEAST_API DynamicObject : public ReferenceCountedObject
{
public:
//==============================================================================
DynamicObject();
/** Destructor. */
virtual ~DynamicObject();
typedef ReferenceCountedObjectPtr<DynamicObject> Ptr;
//==============================================================================
/** Returns true if the object has a property with this name.
Note that if the property is actually a method, this will return false.
*/
virtual bool hasProperty (const Identifier& propertyName) const;
/** Returns a named property.
This returns a void if no such property exists.
*/
virtual var getProperty (const Identifier& propertyName) const;
/** Sets a named property. */
virtual void setProperty (const Identifier& propertyName, const var& newValue);
/** Removes a named property. */
virtual void removeProperty (const Identifier& propertyName);
//==============================================================================
/** Checks whether this object has the specified method.
The default implementation of this just checks whether there's a property
with this name that's actually a method, but this can be overridden for
building objects with dynamic invocation.
*/
virtual bool hasMethod (const Identifier& methodName) const;
/** Invokes a named method on this object.
The default implementation looks up the named property, and if it's a method
call, then it invokes it.
This method is virtual to allow more dynamic invocation to used for objects
where the methods may not already be set as properies.
*/
virtual var invokeMethod (const Identifier& methodName,
const var* parameters,
int numParameters);
/** Sets up a method.
This is basically the same as calling setProperty (methodName, (var::MethodFunction) myFunction), but
helps to avoid accidentally invoking the wrong type of var constructor. It also makes
the code easier to read,
The compiler will probably force you to use an explicit cast your method to a (var::MethodFunction), e.g.
@code
setMethod ("doSomething", (var::MethodFunction) &MyClass::doSomething);
@endcode
*/
void setMethod (const Identifier& methodName,
var::MethodFunction methodFunction);
//==============================================================================
/** Removes all properties and methods from the object. */
void clear();
/** Returns the NamedValueSet that holds the object's properties. */
NamedValueSet& getProperties() noexcept { return properties; }
private:
//==============================================================================
NamedValueSet properties;
BEAST_LEAK_DETECTOR (DynamicObject)
};
#endif // BEAST_DYNAMICOBJECT_BEASTHEADER

View File

@@ -1,274 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_ELEMENTCOMPARATOR_BEASTHEADER
#define BEAST_ELEMENTCOMPARATOR_BEASTHEADER
//==============================================================================
/**
Sorts a range of elements in an array.
The comparator object that is passed-in must define a public method with the following
signature:
@code
int compareElements (ElementType first, ElementType second);
@endcode
..and this method must return:
- a value of < 0 if the first comes before the second
- a value of 0 if the two objects are equivalent
- a value of > 0 if the second comes before the first
To improve performance, the compareElements() method can be declared as static or const.
@param comparator an object which defines a compareElements() method
@param array the array to sort
@param firstElement the index of the first element of the range to be sorted
@param lastElement the index of the last element in the range that needs
sorting (this is inclusive)
@param retainOrderOfEquivalentItems if true, the order of items that the
comparator deems the same will be maintained - this will be
a slower algorithm than if they are allowed to be moved around.
@see sortArrayRetainingOrder
*/
template <class ElementType, class ElementComparator>
static void sortArray (ElementComparator& comparator,
ElementType* const array,
int firstElement,
int lastElement,
const bool retainOrderOfEquivalentItems)
{
(void) comparator; // if you pass in an object with a static compareElements() method, this
// avoids getting warning messages about the parameter being unused
if (lastElement > firstElement)
{
if (retainOrderOfEquivalentItems)
{
for (int i = firstElement; i < lastElement; ++i)
{
if (comparator.compareElements (array[i], array [i + 1]) > 0)
{
std::swap (array[i], array[i + 1]);
if (i > firstElement)
i -= 2;
}
}
}
else
{
int fromStack[30], toStack[30];
int stackIndex = 0;
for (;;)
{
const int size = (lastElement - firstElement) + 1;
if (size <= 8)
{
int j = lastElement;
int maxIndex;
while (j > firstElement)
{
maxIndex = firstElement;
for (int k = firstElement + 1; k <= j; ++k)
if (comparator.compareElements (array[k], array [maxIndex]) > 0)
maxIndex = k;
std::swap (array[j], array[maxIndex]);
--j;
}
}
else
{
const int mid = firstElement + (size >> 1);
std::swap (array[mid], array[firstElement]);
int i = firstElement;
int j = lastElement + 1;
for (;;)
{
while (++i <= lastElement
&& comparator.compareElements (array[i], array [firstElement]) <= 0)
{}
while (--j > firstElement
&& comparator.compareElements (array[j], array [firstElement]) >= 0)
{}
if (j < i)
break;
std::swap (array[i], array[j]);
}
std::swap (array[j], array[firstElement]);
if (j - 1 - firstElement >= lastElement - i)
{
if (firstElement + 1 < j)
{
fromStack [stackIndex] = firstElement;
toStack [stackIndex] = j - 1;
++stackIndex;
}
if (i < lastElement)
{
firstElement = i;
continue;
}
}
else
{
if (i < lastElement)
{
fromStack [stackIndex] = i;
toStack [stackIndex] = lastElement;
++stackIndex;
}
if (firstElement + 1 < j)
{
lastElement = j - 1;
continue;
}
}
}
if (--stackIndex < 0)
break;
bassert (stackIndex < numElementsInArray (fromStack));
firstElement = fromStack [stackIndex];
lastElement = toStack [stackIndex];
}
}
}
}
//==============================================================================
/**
Searches a sorted array of elements, looking for the index at which a specified value
should be inserted for it to be in the correct order.
The comparator object that is passed-in must define a public method with the following
signature:
@code
int compareElements (ElementType first, ElementType second);
@endcode
..and this method must return:
- a value of < 0 if the first comes before the second
- a value of 0 if the two objects are equivalent
- a value of > 0 if the second comes before the first
To improve performance, the compareElements() method can be declared as static or const.
@param comparator an object which defines a compareElements() method
@param array the array to search
@param newElement the value that is going to be inserted
@param firstElement the index of the first element to search
@param lastElement the index of the last element in the range (this is non-inclusive)
*/
template <class ElementType, class ElementComparator>
static int findInsertIndexInSortedArray (ElementComparator& comparator,
ElementType* const array,
const ElementType newElement,
int firstElement,
int lastElement)
{
bassert (firstElement <= lastElement);
(void) comparator; // if you pass in an object with a static compareElements() method, this
// avoids getting warning messages about the parameter being unused
while (firstElement < lastElement)
{
if (comparator.compareElements (newElement, array [firstElement]) == 0)
{
++firstElement;
break;
}
else
{
const int halfway = (firstElement + lastElement) >> 1;
if (halfway == firstElement)
{
if (comparator.compareElements (newElement, array [halfway]) >= 0)
++firstElement;
break;
}
else if (comparator.compareElements (newElement, array [halfway]) >= 0)
{
firstElement = halfway;
}
else
{
lastElement = halfway;
}
}
}
return firstElement;
}
//==============================================================================
/**
A simple ElementComparator class that can be used to sort an array of
objects that support the '<' operator.
This will work for primitive types and objects that implement operator<().
Example: @code
Array <int> myArray;
DefaultElementComparator<int> sorter;
myArray.sort (sorter);
@endcode
@see ElementComparator
*/
template <class ElementType>
class DefaultElementComparator
{
private:
typedef PARAMETER_TYPE (ElementType) ParameterType;
public:
static int compareElements (ParameterType first, ParameterType second)
{
return (first < second) ? -1 : ((second < first) ? 1 : 0);
}
};
#endif // BEAST_ELEMENTCOMPARATOR_BEASTHEADER

View File

@@ -1,447 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_HASHMAP_BEASTHEADER
#define BEAST_HASHMAP_BEASTHEADER
#include "beast_OwnedArray.h"
#include "beast_LinkedListPointer.h"
#include "../memory/beast_ScopedPointer.h"
//==============================================================================
/**
A simple class to generate hash functions for some primitive types, intended for
use with the HashMap class.
@see HashMap
*/
class DefaultHashFunctions
{
public:
/** Generates a simple hash from an integer. */
static int generateHash (const int key, const int upperLimit) noexcept { return std::abs (key) % upperLimit; }
/** Generates a simple hash from an int64. */
static int generateHash (const int64 key, const int upperLimit) noexcept { return std::abs ((int) key) % upperLimit; }
/** Generates a simple hash from a string. */
static int generateHash (const String& key, const int upperLimit) noexcept { return (int) (((uint32) key.hashCode()) % (uint32) upperLimit); }
/** Generates a simple hash from a variant. */
static int generateHash (const var& key, const int upperLimit) noexcept { return generateHash (key.toString(), upperLimit); }
};
//==============================================================================
/**
Holds a set of mappings between some key/value pairs.
The types of the key and value objects are set as template parameters.
You can also specify a class to supply a hash function that converts a key value
into an hashed integer. This class must have the form:
@code
struct MyHashGenerator
{
static int generateHash (MyKeyType key, int upperLimit)
{
// The function must return a value 0 <= x < upperLimit
return someFunctionOfMyKeyType (key) % upperLimit;
}
};
@endcode
Like the Array class, the key and value types are expected to be copy-by-value types, so
if you define them to be pointer types, this class won't delete the objects that they
point to.
If you don't supply a class for the HashFunctionToUse template parameter, the
default one provides some simple mappings for strings and ints.
@code
HashMap<int, String> hash;
hash.set (1, "item1");
hash.set (2, "item2");
DBG (hash [1]); // prints "item1"
DBG (hash [2]); // prints "item2"
// This iterates the map, printing all of its key -> value pairs..
for (HashMap<int, String>::Iterator i (hash); i.next();)
DBG (i.getKey() << " -> " << i.getValue());
@endcode
@see CriticalSection, DefaultHashFunctions, NamedValueSet, SortedSet
*/
template <typename KeyType,
typename ValueType,
class HashFunctionToUse = DefaultHashFunctions,
class TypeOfCriticalSectionToUse = DummyCriticalSection>
class HashMap
{
private:
typedef PARAMETER_TYPE (KeyType) KeyTypeParameter;
typedef PARAMETER_TYPE (ValueType) ValueTypeParameter;
public:
//==============================================================================
/** Creates an empty hash-map.
The numberOfSlots parameter specifies the number of hash entries the map will use. This
will be the "upperLimit" parameter that is passed to your generateHash() function. The number
of hash slots will grow automatically if necessary, or it can be remapped manually using remapTable().
*/
explicit HashMap (const int numberOfSlots = defaultHashTableSize)
: totalNumItems (0)
{
slots.insertMultiple (0, nullptr, numberOfSlots);
}
/** Destructor. */
~HashMap()
{
clear();
}
//==============================================================================
/** Removes all values from the map.
Note that this will clear the content, but won't affect the number of slots (see
remapTable and getNumSlots).
*/
void clear()
{
const ScopedLockType sl (getLock());
for (int i = slots.size(); --i >= 0;)
{
HashEntry* h = slots.getUnchecked(i);
while (h != nullptr)
{
const ScopedPointer<HashEntry> deleter (h);
h = h->nextEntry;
}
slots.set (i, nullptr);
}
totalNumItems = 0;
}
//==============================================================================
/** Returns the current number of items in the map. */
inline int size() const noexcept
{
return totalNumItems;
}
/** Returns the value corresponding to a given key.
If the map doesn't contain the key, a default instance of the value type is returned.
@param keyToLookFor the key of the item being requested
*/
inline ValueType operator[] (KeyTypeParameter keyToLookFor) const
{
const ScopedLockType sl (getLock());
for (const HashEntry* entry = slots.getUnchecked (generateHashFor (keyToLookFor)); entry != nullptr; entry = entry->nextEntry)
if (entry->key == keyToLookFor)
return entry->value;
return ValueType();
}
//==============================================================================
/** Returns true if the map contains an item with the specied key. */
bool contains (KeyTypeParameter keyToLookFor) const
{
const ScopedLockType sl (getLock());
for (const HashEntry* entry = slots.getUnchecked (generateHashFor (keyToLookFor)); entry != nullptr; entry = entry->nextEntry)
if (entry->key == keyToLookFor)
return true;
return false;
}
/** Returns true if the hash contains at least one occurrence of a given value. */
bool containsValue (ValueTypeParameter valueToLookFor) const
{
const ScopedLockType sl (getLock());
for (int i = getNumSlots(); --i >= 0;)
for (const HashEntry* entry = slots.getUnchecked(i); entry != nullptr; entry = entry->nextEntry)
if (entry->value == valueToLookFor)
return true;
return false;
}
//==============================================================================
/** Adds or replaces an element in the hash-map.
If there's already an item with the given key, this will replace its value. Otherwise, a new item
will be added to the map.
*/
void set (KeyTypeParameter newKey, ValueTypeParameter newValue)
{
const ScopedLockType sl (getLock());
const int hashIndex = generateHashFor (newKey);
HashEntry* const firstEntry = slots.getUnchecked (hashIndex);
for (HashEntry* entry = firstEntry; entry != nullptr; entry = entry->nextEntry)
{
if (entry->key == newKey)
{
entry->value = newValue;
return;
}
}
slots.set (hashIndex, new HashEntry (newKey, newValue, firstEntry));
++totalNumItems;
if (totalNumItems > (getNumSlots() * 3) / 2)
remapTable (getNumSlots() * 2);
}
/** Removes an item with the given key. */
void remove (KeyTypeParameter keyToRemove)
{
const ScopedLockType sl (getLock());
const int hashIndex = generateHashFor (keyToRemove);
HashEntry* entry = slots.getUnchecked (hashIndex);
HashEntry* previous = nullptr;
while (entry != nullptr)
{
if (entry->key == keyToRemove)
{
const ScopedPointer<HashEntry> deleter (entry);
entry = entry->nextEntry;
if (previous != nullptr)
previous->nextEntry = entry;
else
slots.set (hashIndex, entry);
--totalNumItems;
}
else
{
previous = entry;
entry = entry->nextEntry;
}
}
}
/** Removes all items with the given value. */
void removeValue (ValueTypeParameter valueToRemove)
{
const ScopedLockType sl (getLock());
for (int i = getNumSlots(); --i >= 0;)
{
HashEntry* entry = slots.getUnchecked(i);
HashEntry* previous = nullptr;
while (entry != nullptr)
{
if (entry->value == valueToRemove)
{
const ScopedPointer<HashEntry> deleter (entry);
entry = entry->nextEntry;
if (previous != nullptr)
previous->nextEntry = entry;
else
slots.set (i, entry);
--totalNumItems;
}
else
{
previous = entry;
entry = entry->nextEntry;
}
}
}
}
/** Remaps the hash-map to use a different number of slots for its hash function.
Each slot corresponds to a single hash-code, and each one can contain multiple items.
@see getNumSlots()
*/
void remapTable (int newNumberOfSlots)
{
HashMap newTable (newNumberOfSlots);
for (int i = getNumSlots(); --i >= 0;)
for (const HashEntry* entry = slots.getUnchecked(i); entry != nullptr; entry = entry->nextEntry)
newTable.set (entry->key, entry->value);
swapWith (newTable);
}
/** Returns the number of slots which are available for hashing.
Each slot corresponds to a single hash-code, and each one can contain multiple items.
@see getNumSlots()
*/
inline int getNumSlots() const noexcept
{
return slots.size();
}
//==============================================================================
/** Efficiently swaps the contents of two hash-maps. */
void swapWith (HashMap& otherHashMap) noexcept
{
const ScopedLockType lock1 (getLock());
const ScopedLockType lock2 (otherHashMap.getLock());
slots.swapWithArray (otherHashMap.slots);
std::swap (totalNumItems, otherHashMap.totalNumItems);
}
//==============================================================================
/** Returns the CriticalSection that locks this structure.
To lock, you can call getLock().enter() and getLock().exit(), or preferably use
an object of ScopedLockType as an RAII lock for it.
*/
inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return lock; }
/** Returns the type of scoped lock to use for locking this array */
typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
private:
//==============================================================================
class HashEntry
{
public:
HashEntry (KeyTypeParameter k, ValueTypeParameter val, HashEntry* const next)
: key (k), value (val), nextEntry (next)
{}
const KeyType key;
ValueType value;
HashEntry* nextEntry;
BEAST_DECLARE_NON_COPYABLE (HashEntry)
};
public:
//==============================================================================
/** Iterates over the items in a HashMap.
To use it, repeatedly call next() until it returns false, e.g.
@code
HashMap <String, String> myMap;
HashMap<String, String>::Iterator i (myMap);
while (i.next())
{
DBG (i.getKey() << " -> " << i.getValue());
}
@endcode
The order in which items are iterated bears no resemblence to the order in which
they were originally added!
Obviously as soon as you call any non-const methods on the original hash-map, any
iterators that were created beforehand will cease to be valid, and should not be used.
@see HashMap
*/
class Iterator
{
public:
//==============================================================================
Iterator (const HashMap& hashMapToIterate)
: hashMap (hashMapToIterate), entry (nullptr), index (0)
{}
/** Moves to the next item, if one is available.
When this returns true, you can get the item's key and value using getKey() and
getValue(). If it returns false, the iteration has finished and you should stop.
*/
bool next()
{
if (entry != nullptr)
entry = entry->nextEntry;
while (entry == nullptr)
{
if (index >= hashMap.getNumSlots())
return false;
entry = hashMap.slots.getUnchecked (index++);
}
return true;
}
/** Returns the current item's key.
This should only be called when a call to next() has just returned true.
*/
KeyType getKey() const
{
return entry != nullptr ? entry->key : KeyType();
}
/** Returns the current item's value.
This should only be called when a call to next() has just returned true.
*/
ValueType getValue() const
{
return entry != nullptr ? entry->value : ValueType();
}
private:
//==============================================================================
const HashMap& hashMap;
HashEntry* entry;
int index;
BEAST_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Iterator)
};
private:
//==============================================================================
enum { defaultHashTableSize = 101 };
friend class Iterator;
Array <HashEntry*> slots;
int totalNumItems;
TypeOfCriticalSectionToUse lock;
int generateHashFor (KeyTypeParameter key) const
{
const int hash = HashFunctionToUse::generateHash (key, getNumSlots());
bassert (isPositiveAndBelow (hash, getNumSlots())); // your hash function is generating out-of-range numbers!
return hash;
}
BEAST_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HashMap)
};
#endif // BEAST_HASHMAP_BEASTHEADER

View File

@@ -1,366 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_LINKEDLISTPOINTER_BEASTHEADER
#define BEAST_LINKEDLISTPOINTER_BEASTHEADER
//==============================================================================
/**
Helps to manipulate singly-linked lists of objects.
For objects that are designed to contain a pointer to the subsequent item in the
list, this class contains methods to deal with the list. To use it, the ObjectType
class that it points to must contain a LinkedListPointer called nextListItem, e.g.
@code
struct MyObject
{
int x, y, z;
// A linkable object must contain a member with this name and type, which must be
// accessible by the LinkedListPointer class. (This doesn't mean it has to be public -
// you could make your class a friend of a LinkedListPointer<MyObject> instead).
LinkedListPointer<MyObject> nextListItem;
};
LinkedListPointer<MyObject> myList;
myList.append (new MyObject());
myList.append (new MyObject());
int numItems = myList.size(); // returns 2
MyObject* lastInList = myList.getLast();
@endcode
*/
template <class ObjectType>
class LinkedListPointer
{
public:
//==============================================================================
/** Creates a null pointer to an empty list. */
LinkedListPointer() noexcept
: item (nullptr)
{
}
/** Creates a pointer to a list whose head is the item provided. */
explicit LinkedListPointer (ObjectType* const headItem) noexcept
: item (headItem)
{
}
/** Sets this pointer to point to a new list. */
LinkedListPointer& operator= (ObjectType* const newItem) noexcept
{
item = newItem;
return *this;
}
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
LinkedListPointer (LinkedListPointer&& other) noexcept
: item (other.item)
{
other.item = nullptr;
}
LinkedListPointer& operator= (LinkedListPointer&& other) noexcept
{
bassert (this != &other); // hopefully the compiler should make this situation impossible!
item = other.item;
other.item = nullptr;
return *this;
}
#endif
//==============================================================================
/** Returns the item which this pointer points to. */
inline operator ObjectType*() const noexcept
{
return item;
}
/** Returns the item which this pointer points to. */
inline ObjectType* get() const noexcept
{
return item;
}
/** Returns the last item in the list which this pointer points to.
This will iterate the list and return the last item found. Obviously the speed
of this operation will be proportional to the size of the list. If the list is
empty the return value will be this object.
If you're planning on appending a number of items to your list, it's much more
efficient to use the Appender class than to repeatedly call getLast() to find the end.
*/
LinkedListPointer& getLast() noexcept
{
LinkedListPointer* l = this;
while (l->item != nullptr)
l = &(l->item->nextListItem);
return *l;
}
/** Returns the number of items in the list.
Obviously with a simple linked list, getting the size involves iterating the list, so
this can be a lengthy operation - be careful when using this method in your code.
*/
int size() const noexcept
{
int total = 0;
for (ObjectType* i = item; i != nullptr; i = i->nextListItem)
++total;
return total;
}
/** Returns the item at a given index in the list.
Since the only way to find an item is to iterate the list, this operation can obviously
be slow, depending on its size, so you should be careful when using this in algorithms.
*/
LinkedListPointer& operator[] (int index) noexcept
{
LinkedListPointer* l = this;
while (--index >= 0 && l->item != nullptr)
l = &(l->item->nextListItem);
return *l;
}
/** Returns the item at a given index in the list.
Since the only way to find an item is to iterate the list, this operation can obviously
be slow, depending on its size, so you should be careful when using this in algorithms.
*/
const LinkedListPointer& operator[] (int index) const noexcept
{
const LinkedListPointer* l = this;
while (--index >= 0 && l->item != nullptr)
l = &(l->item->nextListItem);
return *l;
}
/** Returns true if the list contains the given item. */
bool contains (const ObjectType* const itemToLookFor) const noexcept
{
for (ObjectType* i = item; i != nullptr; i = i->nextListItem)
if (itemToLookFor == i)
return true;
return false;
}
//==============================================================================
/** Inserts an item into the list, placing it before the item that this pointer
currently points to.
*/
void insertNext (ObjectType* const newItem)
{
bassert (newItem != nullptr);
bassert (newItem->nextListItem == nullptr);
newItem->nextListItem = item;
item = newItem;
}
/** Inserts an item at a numeric index in the list.
Obviously this will involve iterating the list to find the item at the given index,
so be careful about the impact this may have on execution time.
*/
void insertAtIndex (int index, ObjectType* newItem)
{
bassert (newItem != nullptr);
LinkedListPointer* l = this;
while (index != 0 && l->item != nullptr)
{
l = &(l->item->nextListItem);
--index;
}
l->insertNext (newItem);
}
/** Replaces the object that this pointer points to, appending the rest of the list to
the new object, and returning the old one.
*/
ObjectType* replaceNext (ObjectType* const newItem) noexcept
{
bassert (newItem != nullptr);
bassert (newItem->nextListItem == nullptr);
ObjectType* const oldItem = item;
item = newItem;
item->nextListItem = oldItem->nextListItem.item;
oldItem->nextListItem.item = nullptr;
return oldItem;
}
/** Adds an item to the end of the list.
This operation involves iterating the whole list, so can be slow - if you need to
append a number of items to your list, it's much more efficient to use the Appender
class than to repeatedly call append().
*/
void append (ObjectType* const newItem)
{
getLast().item = newItem;
}
/** Creates copies of all the items in another list and adds them to this one.
This will use the ObjectType's copy constructor to try to create copies of each
item in the other list, and appends them to this list.
*/
void addCopyOfList (const LinkedListPointer& other)
{
LinkedListPointer* insertPoint = this;
for (ObjectType* i = other.item; i != nullptr; i = i->nextListItem)
{
insertPoint->insertNext (new ObjectType (*i));
insertPoint = &(insertPoint->item->nextListItem);
}
}
/** Removes the head item from the list.
This won't delete the object that is removed, but returns it, so the caller can
delete it if necessary.
*/
ObjectType* removeNext() noexcept
{
ObjectType* const oldItem = item;
if (oldItem != nullptr)
{
item = oldItem->nextListItem;
oldItem->nextListItem.item = nullptr;
}
return oldItem;
}
/** Removes a specific item from the list.
Note that this will not delete the item, it simply unlinks it from the list.
*/
void remove (ObjectType* const itemToRemove)
{
if (LinkedListPointer* const l = findPointerTo (itemToRemove))
l->removeNext();
}
/** Iterates the list, calling the delete operator on all of its elements and
leaving this pointer empty.
*/
void deleteAll()
{
while (item != nullptr)
{
ObjectType* const oldItem = item;
item = oldItem->nextListItem;
delete oldItem;
}
}
/** Finds a pointer to a given item.
If the item is found in the list, this returns the pointer that points to it. If
the item isn't found, this returns null.
*/
LinkedListPointer* findPointerTo (ObjectType* const itemToLookFor) noexcept
{
LinkedListPointer* l = this;
while (l->item != nullptr)
{
if (l->item == itemToLookFor)
return l;
l = &(l->item->nextListItem);
}
return nullptr;
}
/** Copies the items in the list to an array.
The destArray must contain enough elements to hold the entire list - no checks are
made for this!
*/
void copyToArray (ObjectType** destArray) const noexcept
{
bassert (destArray != nullptr);
for (ObjectType* i = item; i != nullptr; i = i->nextListItem)
*destArray++ = i;
}
/** Swaps this pointer with another one */
void swapWith (LinkedListPointer& other) noexcept
{
std::swap (item, other.item);
}
//==============================================================================
/**
Allows efficient repeated insertions into a list.
You can create an Appender object which points to the last element in your
list, and then repeatedly call Appender::append() to add items to the end
of the list in O(1) time.
*/
class Appender
{
public:
/** Creates an appender which will add items to the given list.
*/
Appender (LinkedListPointer& endOfListPointer) noexcept
: endOfList (&endOfListPointer)
{
// This can only be used to add to the end of a list.
bassert (endOfListPointer.item == nullptr);
}
/** Appends an item to the list. */
void append (ObjectType* const newItem) noexcept
{
*endOfList = newItem;
endOfList = &(newItem->nextListItem);
}
private:
LinkedListPointer* endOfList;
BEAST_DECLARE_NON_COPYABLE (Appender)
};
private:
//==============================================================================
ObjectType* item;
BEAST_DECLARE_NON_COPYABLE (LinkedListPointer)
};
#endif // BEAST_LINKEDLISTPOINTER_BEASTHEADER

Some files were not shown because too many files have changed in this diff Show More