mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
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:
@@ -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
|
||||
12
Subtrees/beast/.gitattributes
vendored
12
Subtrees/beast/.gitattributes
vendored
@@ -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
|
||||
26
Subtrees/beast/.gitignore
vendored
26
Subtrees/beast/.gitignore
vendored
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
//==============================================================================
|
||||
@@ -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 (¤tControl, 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 (¤tControl, newControl, mask);
|
||||
|
||||
if (result != 0)
|
||||
Throw (std::runtime_error ("error in _controlfp_s"));
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
//==============================================================================
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 ()
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user