Move many Thread related classes

This commit is contained in:
Vinnie Falco
2013-10-04 13:49:24 -07:00
parent 93e9d8622e
commit 6c7f5d093c
48 changed files with 1043 additions and 2158 deletions

View File

@@ -140,6 +140,8 @@
<ClInclude Include="..\..\beast\SmartPtr.h" />
<ClInclude Include="..\..\beast\smart_ptr\ContainerDeletePolicy.h" />
<ClInclude Include="..\..\beast\smart_ptr\ScopedPointer.h" />
<ClInclude Include="..\..\beast\smart_ptr\SharedObject.h" />
<ClInclude Include="..\..\beast\smart_ptr\SharedPtr.h" />
<ClInclude Include="..\..\beast\StaticAssert.h" />
<ClInclude Include="..\..\beast\Strings.h" />
<ClInclude Include="..\..\beast\strings\CharacterFunctions.h" />
@@ -151,19 +153,21 @@
<ClInclude Include="..\..\beast\strings\String.h" />
<ClInclude Include="..\..\beast\strings\StringCharPointerType.h" />
<ClInclude Include="..\..\beast\strings\StringFromNumber.h" />
<ClInclude Include="..\..\beast\Thread.h" />
<ClInclude Include="..\..\beast\thread\LockGuard.h" />
<ClInclude Include="..\..\beast\thread\RecursiveMutex.h" />
<ClInclude Include="..\..\beast\thread\ServiceQueue.h" />
<ClInclude Include="..\..\beast\thread\SharedData.h" />
<ClInclude Include="..\..\beast\thread\SharedLockGuard.h" />
<ClInclude Include="..\..\beast\thread\SharedMutexAdapter.h" />
<ClInclude Include="..\..\beast\Threads.h" />
<ClInclude Include="..\..\beast\Chrono.h" />
<ClInclude Include="..\..\beast\thread\SpinLock.h" />
<ClInclude Include="..\..\beast\thread\ThreadLocalValue.h" />
<ClInclude Include="..\..\beast\thread\TryLockGuard.h" />
<ClInclude Include="..\..\beast\thread\UnlockGuard.h" />
<ClInclude Include="..\..\beast\thread\WaitableEvent.h" />
<ClInclude Include="..\..\beast\threads\LockGuard.h" />
<ClInclude Include="..\..\beast\threads\RecursiveMutex.h" />
<ClInclude Include="..\..\beast\threads\ServiceQueue.h" />
<ClInclude Include="..\..\beast\threads\SharedData.h" />
<ClInclude Include="..\..\beast\threads\SharedLockGuard.h" />
<ClInclude Include="..\..\beast\threads\SharedMutexAdapter.h" />
<ClInclude Include="..\..\beast\threads\SpinLock.h" />
<ClInclude Include="..\..\beast\threads\Stoppable.h" />
<ClInclude Include="..\..\beast\threads\Thread.h" />
<ClInclude Include="..\..\beast\threads\ThreadLocalValue.h" />
<ClInclude Include="..\..\beast\threads\TryLockGuard.h" />
<ClInclude Include="..\..\beast\threads\UnlockGuard.h" />
<ClInclude Include="..\..\beast\threads\WaitableEvent.h" />
<ClInclude Include="..\..\beast\TypeTraits.h" />
<ClInclude Include="..\..\beast\type_traits\IntegralConstant.h" />
<ClInclude Include="..\..\beast\type_traits\IsIntegral.h" />
@@ -175,6 +179,8 @@
<ClInclude Include="..\..\beast\utility\EnableIf.h" />
<ClInclude Include="..\..\beast\utility\Error.h" />
<ClInclude Include="..\..\beast\utility\Journal.h" />
<ClInclude Include="..\..\beast\utility\LeakChecked.h" />
<ClInclude Include="..\..\beast\utility\StaticObject.h" />
<ClInclude Include="..\..\beast\Version.h" />
<ClInclude Include="..\..\config\BeastConfig.h" />
<ClInclude Include="..\..\modules\beast_asio\async\AbstractHandler.h" />
@@ -245,7 +251,6 @@
<ClInclude Include="..\..\modules\beast_core\containers\Variant.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\FatalError.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\FPUFlags.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\LeakChecked.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\SemanticVersion.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\Throw.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\UnitTest.h" />
@@ -280,11 +285,8 @@
<ClInclude Include="..\..\modules\beast_core\memory\OptionalScopedPointer.h" />
<ClInclude Include="..\..\modules\beast_core\memory\RecycledObjectPool.h" />
<ClInclude Include="..\..\modules\beast_core\memory\SharedFunction.h" />
<ClInclude Include="..\..\modules\beast_core\memory\SharedObject.h" />
<ClInclude Include="..\..\modules\beast_core\memory\SharedSingleton.h" />
<ClInclude Include="..\..\modules\beast_core\memory\WeakReference.h" />
<ClInclude Include="..\..\modules\beast_core\memory\SharedPtr.h" />
<ClInclude Include="..\..\modules\beast_core\memory\StaticObject.h" />
<ClInclude Include="..\..\modules\beast_core\misc\Main.h" />
<ClInclude Include="..\..\modules\beast_core\misc\Result.h" />
<ClInclude Include="..\..\modules\beast_core\misc\Uuid.h" />
@@ -327,17 +329,12 @@
<ClInclude Include="..\..\modules\beast_core\threads\InterProcessLock.h" />
<ClInclude Include="..\..\modules\beast_core\threads\Process.h" />
<ClInclude Include="..\..\modules\beast_core\threads\ReadWriteLock.h" />
<ClInclude Include="..\..\modules\beast_core\threads\ReadWriteMutex.h" />
<ClInclude Include="..\..\modules\beast_core\threads\ScopedLock.h" />
<ClInclude Include="..\..\modules\beast_core\threads\ScopedReadLock.h" />
<ClInclude Include="..\..\modules\beast_core\threads\ScopedWriteLock.h" />
<ClInclude Include="..\..\modules\beast_core\threads\SpinDelay.h" />
<ClInclude Include="..\..\modules\beast_core\threads\Thread.h" />
<ClInclude Include="..\..\modules\beast_core\threads\ThreadPool.h" />
<ClInclude Include="..\..\modules\beast_core\threads\TimeSliceThread.h" />
<ClInclude Include="..\..\modules\beast_core\thread\DeadlineTimer.h" />
<ClInclude Include="..\..\modules\beast_core\thread\Semaphore.h" />
<ClInclude Include="..\..\modules\beast_core\thread\Stoppable.h" />
<ClInclude Include="..\..\modules\beast_core\thread\Workers.h" />
<ClInclude Include="..\..\modules\beast_core\thread\detail\ScopedLock.h" />
<ClInclude Include="..\..\modules\beast_core\thread\detail\TrackedMutex.h" />
@@ -492,6 +489,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\net\Net.cpp" />
<ClCompile Include="..\..\beast\smart_ptr\SmartPtr.cpp" />
<ClCompile Include="..\..\beast\strings\impl\CharacterFunctions.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -505,25 +503,43 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\strings\Strings.cpp" />
<ClCompile Include="..\..\beast\thread\impl\RecursiveMutex.cpp">
<ClCompile Include="..\..\beast\threads\impl\Atomic.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\thread\impl\ServiceQueue.cpp">
<ClCompile Include="..\..\beast\threads\impl\RecursiveMutex.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\thread\impl\WaitableEvent.cpp">
<ClCompile Include="..\..\beast\threads\impl\ServiceQueue.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\thread\Thread.cpp" />
<ClCompile Include="..\..\beast\threads\impl\Stoppable.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\threads\impl\Thread.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\threads\impl\WaitableEvent.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\threads\Threads.cpp" />
<ClCompile Include="..\..\beast\utility\impl\Debug.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -542,6 +558,18 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\utility\impl\LeakChecked.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\utility\impl\StaticObject.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\utility\Utility.cpp" />
<ClCompile Include="..\..\modules\beast_asio\async\SharedHandler.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -729,12 +757,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\diagnostic\Assert.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\diagnostic\FatalError.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -745,12 +767,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\diagnostic\LeakChecked.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\diagnostic\SemanticVersion.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -859,12 +875,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\memory\StaticObject.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\misc\Main.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -1147,36 +1157,12 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\ReadWriteMutex.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\SpinDelay.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\Thread.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\ThreadPool.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\TimeSliceThread.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\thread\DeadlineTimer.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -1189,12 +1175,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\thread\Stoppable.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\thread\Workers.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>

View File

@@ -234,9 +234,6 @@
<Filter Include="beast\utility\impl">
<UniqueIdentifier>{775ab0d6-aa5f-43d7-ab3b-3c01652a9ef1}</UniqueIdentifier>
</Filter>
<Filter Include="beast\thread">
<UniqueIdentifier>{da8084c0-491b-4eb0-b750-97182a9deed4}</UniqueIdentifier>
</Filter>
<Filter Include="beast\http">
<UniqueIdentifier>{56ef157f-ad92-4da7-8fbf-00723f769732}</UniqueIdentifier>
</Filter>
@@ -291,8 +288,11 @@
<Filter Include="beast\smart_ptr">
<UniqueIdentifier>{4e9c54da-1581-41d7-ac75-48140e4a13d4}</UniqueIdentifier>
</Filter>
<Filter Include="beast\thread\impl">
<UniqueIdentifier>{96d46096-0e7d-4ca8-9d81-72f6834f88f8}</UniqueIdentifier>
<Filter Include="beast\threads">
<UniqueIdentifier>{f864ff58-1055-4c56-805f-9f181c4f0aa1}</UniqueIdentifier>
</Filter>
<Filter Include="beast\threads\impl">
<UniqueIdentifier>{386a8cd8-6be3-4cac-9bca-7a01fdb5327a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
@@ -497,15 +497,6 @@
<ClInclude Include="..\..\modules\beast_core\threads\ScopedWriteLock.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\Thread.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\ThreadPool.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\TimeSliceThread.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\time\PerformanceCounter.h">
<Filter>beast_core\time</Filter>
</ClInclude>
@@ -587,9 +578,6 @@
<ClInclude Include="..\..\modules\beast_core\diagnostic\FPUFlags.h">
<Filter>beast_core\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\diagnostic\LeakChecked.h">
<Filter>beast_core\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\diagnostic\Throw.h">
<Filter>beast_core\diagnostic</Filter>
</ClInclude>
@@ -704,9 +692,6 @@
<ClInclude Include="..\..\modules\beast_core\diagnostic\MeasureFunctionCallTime.h">
<Filter>beast_core\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\ReadWriteMutex.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\thread\MutexTraits.h">
<Filter>beast_core\thread</Filter>
</ClInclude>
@@ -800,12 +785,6 @@
<ClInclude Include="..\..\beast\mpl\PointerToOther.h">
<Filter>beast\mpl</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\SharedPtr.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\SharedObject.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\async\ComposedAsyncOperation.h">
<Filter>beast_asio\async</Filter>
</ClInclude>
@@ -938,9 +917,6 @@
<ClInclude Include="..\..\modules\beast_core\diagnostic\FatalError.h">
<Filter>beast_core\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\memory\StaticObject.h">
<Filter>beast_core\memory</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_crypto\math\UnsignedInteger.h">
<Filter>beast_crypto\math</Filter>
</ClInclude>
@@ -995,21 +971,6 @@
<ClInclude Include="..\..\beast\mpl\IsCallPossible.h">
<Filter>beast\mpl</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\Thread.h">
<Filter>beast</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\LockGuard.h">
<Filter>beast\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\SharedLockGuard.h">
<Filter>beast\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\SharedData.h">
<Filter>beast\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\SharedMutexAdapter.h">
<Filter>beast\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\Uncopyable.h">
<Filter>beast</Filter>
</ClInclude>
@@ -1037,9 +998,6 @@
<ClInclude Include="..\..\beast\mpl\CopyConst.h">
<Filter>beast\mpl</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\thread\Stoppable.h">
<Filter>beast_core\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\http\impl\http-parser\http_parser.h">
<Filter>beast\http\impl\http-parser</Filter>
</ClInclude>
@@ -1212,32 +1170,65 @@
<ClInclude Include="..\..\modules\beast_asio\http\HTTPResponseParser.h">
<Filter>beast_asio\http</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\RecursiveMutex.h">
<Filter>beast\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\UnlockGuard.h">
<Filter>beast\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\TryLockGuard.h">
<Filter>beast\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\chrono\ScopedTimeInterval.h">
<Filter>beast\chrono</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\chrono\CPUMeter.h">
<Filter>beast\chrono</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\WaitableEvent.h">
<Filter>beast\thread</Filter>
<ClInclude Include="..\..\beast\smart_ptr\SharedObject.h">
<Filter>beast\smart_ptr</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\ServiceQueue.h">
<Filter>beast\thread</Filter>
<ClInclude Include="..\..\beast\smart_ptr\SharedPtr.h">
<Filter>beast\smart_ptr</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\ThreadLocalValue.h">
<Filter>beast\thread</Filter>
<ClInclude Include="..\..\beast\Threads.h">
<Filter>beast</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\SpinLock.h">
<Filter>beast\thread</Filter>
<ClInclude Include="..\..\beast\threads\LockGuard.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\RecursiveMutex.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\ServiceQueue.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\SharedData.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\SharedLockGuard.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\SharedMutexAdapter.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\SpinLock.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\Thread.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\ThreadLocalValue.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\TryLockGuard.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\UnlockGuard.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\WaitableEvent.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\utility\LeakChecked.h">
<Filter>beast\utility</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\utility\StaticObject.h">
<Filter>beast\utility</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\threads\Stoppable.h">
<Filter>beast\threads</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
@@ -1406,15 +1397,6 @@
<ClCompile Include="..\..\modules\beast_core\threads\ReadWriteLock.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\Thread.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\ThreadPool.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\TimeSliceThread.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\time\PerformanceCounter.cpp">
<Filter>beast_core\time</Filter>
</ClCompile>
@@ -1484,9 +1466,6 @@
<ClCompile Include="..\..\modules\beast_core\diagnostic\FPUFlags.cpp">
<Filter>beast_core\diagnostic</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\diagnostic\LeakChecked.cpp">
<Filter>beast_core\diagnostic</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\SpinDelay.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
@@ -1565,9 +1544,6 @@
<ClCompile Include="..\..\modules\beast_core\diagnostic\SemanticVersion.cpp">
<Filter>beast_core\diagnostic</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\threads\ReadWriteMutex.cpp">
<Filter>beast_core\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\thread\impl\TrackedMutex.cpp">
<Filter>beast_core\thread\impl</Filter>
</ClCompile>
@@ -1673,12 +1649,6 @@
<ClCompile Include="..\..\modules\beast_core\diagnostic\FatalError.cpp">
<Filter>beast_core\diagnostic</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\memory\StaticObject.cpp">
<Filter>beast_core\memory</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\diagnostic\Assert.cpp">
<Filter>beast_core\diagnostic</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_crypto\math\UnsignedInteger.cpp">
<Filter>beast_crypto\math</Filter>
</ClCompile>
@@ -1703,9 +1673,6 @@
<ClCompile Include="..\..\modules\beast_asio\http\HTTPRequest.cpp">
<Filter>beast_asio\http</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_core\thread\Stoppable.cpp">
<Filter>beast_core\thread</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\http\impl\http-parser\http_parser.c">
<Filter>beast\http\impl\http-parser</Filter>
</ClCompile>
@@ -1775,20 +1742,38 @@
<ClCompile Include="..\..\modules\beast_asio\http\HTTPResponseParser.cpp">
<Filter>beast_asio\http</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\thread\impl\RecursiveMutex.cpp">
<Filter>beast\thread\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\thread\Thread.cpp">
<Filter>beast\thread</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\chrono\impl\CPUMeter.cpp">
<Filter>beast\chrono\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\thread\impl\WaitableEvent.cpp">
<Filter>beast\thread\impl</Filter>
<ClCompile Include="..\..\beast\smart_ptr\SmartPtr.cpp">
<Filter>beast\smart_ptr</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\thread\impl\ServiceQueue.cpp">
<Filter>beast\thread\impl</Filter>
<ClCompile Include="..\..\beast\threads\impl\Atomic.cpp">
<Filter>beast\threads\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\threads\impl\RecursiveMutex.cpp">
<Filter>beast\threads\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\threads\impl\ServiceQueue.cpp">
<Filter>beast\threads\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\threads\impl\WaitableEvent.cpp">
<Filter>beast\threads\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\threads\Threads.cpp">
<Filter>beast\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\threads\impl\Thread.cpp">
<Filter>beast\threads\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\utility\impl\LeakChecked.cpp">
<Filter>beast\utility\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\utility\impl\StaticObject.cpp">
<Filter>beast\utility\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\beast\threads\impl\Stoppable.cpp">
<Filter>beast\threads\impl</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>

View File

@@ -2,13 +2,6 @@
BEAST TODO
--------------------------------------------------------------------------------
- Remove ReadWriteMutex and replace it with a CriticalSection
since the implementation is broken.
- Rewrite SharedData to work with a CriticalSection
- Use new file naming convention
- Use SemanticVersion for beast version numbers to replace BEAST_VERSION
- add support for a __PRETTY_FUNCTION__ equivalent for all environments

View File

@@ -23,6 +23,8 @@
#include "Config.h"
#include "smart_ptr/ContainerDeletePolicy.h"
#include "smart_ptr/SharedObject.h"
#include "smart_ptr/SharedPtr.h"
#include "smart_ptr/ScopedPointer.h"
#endif

36
beast/Threads.h Normal file
View File

@@ -0,0 +1,36 @@
//------------------------------------------------------------------------------
/*
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_THREADS_H_INCLUDED
#define BEAST_THREADS_H_INCLUDED
#include "threads/LockGuard.h"
#include "threads/UnlockGuard.h"
#include "threads/TryLockGuard.h"
#include "threads/SharedLockGuard.h"
#include "threads/SharedMutexAdapter.h"
#include "threads/SharedData.h"
#include "threads/ServiceQueue.h"
#include "threads/SpinLock.h"
#include "threads/Stoppable.h"
#include "threads/Thread.h"
#include "threads/ThreadLocalValue.h"
#include "threads/WaitableEvent.h"
#endif

View File

@@ -24,6 +24,8 @@
#include "utility/EnableIf.h"
#include "utility/Error.h"
#include "utility/Journal.h"
#include "utility/LeakChecked.h"
#include "utility/StaticObject.h"
#endif

View File

@@ -22,7 +22,7 @@
#include "RelativeTime.h"
#include "ScopedTimeInterval.h"
#include "../thread/SharedData.h"
#include "../threads/SharedData.h"
#include "../Atomic.h"
namespace beast {

View File

@@ -24,9 +24,11 @@
#ifndef BEAST_SMARTPTR_SCOPEDPOINTER_H_INCLUDED
#define BEAST_SMARTPTR_SCOPEDPOINTER_H_INCLUDED
#include "ContainerDeletePolicy.h"
#include "../Config.h"
#include "../Uncopyable.h"
#include "../StaticAssert.h"
#include "ContainerDeletePolicy.h"
namespace beast {
@@ -73,13 +75,13 @@ class ScopedPointer : public Uncopyable
public:
//==============================================================================
/** Creates a ScopedPointer containing a null pointer. */
inline ScopedPointer() noexcept
inline ScopedPointer()
: object (nullptr)
{
}
/** Creates a ScopedPointer that owns the specified object. */
inline ScopedPointer (ObjectType* const objectToTakePossessionOf) noexcept
inline ScopedPointer (ObjectType* const objectToTakePossessionOf)
: object (objectToTakePossessionOf)
{
}
@@ -90,7 +92,7 @@ public:
the pointer from the other object to this one, and the other object is reset to
be a null pointer.
*/
ScopedPointer (ScopedPointer& objectToTransferFrom) noexcept
ScopedPointer (ScopedPointer& objectToTransferFrom)
: object (objectToTransferFrom.object)
{
objectToTransferFrom.object = nullptr;
@@ -150,13 +152,13 @@ public:
}
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
ScopedPointer (ScopedPointer&& other) noexcept
ScopedPointer (ScopedPointer&& other)
: object (other.object)
{
other.object = nullptr;
}
ScopedPointer& operator= (ScopedPointer&& other) noexcept
ScopedPointer& operator= (ScopedPointer&& other)
{
object = other.object;
other.object = nullptr;
@@ -166,28 +168,28 @@ public:
//==============================================================================
/** Returns the object that this ScopedPointer refers to. */
inline operator ObjectType*() const noexcept { return object; }
inline operator ObjectType*() const { return object; }
/** Returns the object that this ScopedPointer refers to. */
inline ObjectType* get() const noexcept { return object; }
inline ObjectType* get() const { return object; }
/** Returns the object that this ScopedPointer refers to. */
inline ObjectType& operator*() const noexcept { return *object; }
inline ObjectType& operator*() const { return *object; }
/** Lets you access methods and properties of the object that this ScopedPointer refers to. */
inline ObjectType* operator->() const noexcept { return object; }
inline ObjectType* operator->() const { return object; }
//==============================================================================
/** Removes the current object from this ScopedPointer without deleting it.
This will return the current object, and set the ScopedPointer to a null pointer.
*/
ObjectType* release() noexcept { ObjectType* const o = object; object = nullptr; return o; }
ObjectType* release() { ObjectType* const o = object; object = nullptr; return o; }
//==============================================================================
/** Swaps this object with that of another ScopedPointer.
The two objects simply exchange their pointers.
*/
void swapWith (ScopedPointer <ObjectType>& other) noexcept
void swapWith (ScopedPointer <ObjectType>& other)
{
// Two ScopedPointers should never be able to refer to the same object - if
// this happens, you must have done something dodgy!
@@ -206,7 +208,7 @@ private:
ObjectType* object;
// (Required as an alternative to the overloaded & operator).
const ScopedPointer* getAddress() const noexcept { return this; }
const ScopedPointer* getAddress() const { return this; }
#if ! BEAST_MSVC // (MSVC can't deal with multiple copy constructors)
/* The copy constructors are private to stop people accidentally copying a const ScopedPointer
@@ -233,7 +235,7 @@ private:
This can be handy for checking whether this is a null pointer.
*/
template <class ObjectType>
bool operator== (const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
bool operator== (const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2)
{
return static_cast <ObjectType*> (pointer1) == pointer2;
}
@@ -242,7 +244,7 @@ bool operator== (const ScopedPointer<ObjectType>& pointer1, ObjectType* const po
This can be handy for checking whether this is a null pointer.
*/
template <class ObjectType>
bool operator!= (const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
bool operator!= (const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2)
{
return static_cast <ObjectType*> (pointer1) != pointer2;
}

View File

@@ -24,6 +24,12 @@
#ifndef BEAST_SHAREDOBJECT_H_INCLUDED
#define BEAST_SHAREDOBJECT_H_INCLUDED
#include "../Config.h"
#include "../Atomic.h"
#include "../Uncopyable.h"
namespace beast {
//==============================================================================
/**
Adds reference-counting to an object.
@@ -194,4 +200,6 @@ private:
int refCount;
};
}
#endif

View File

@@ -21,8 +21,13 @@
*/
//==============================================================================
#ifndef BEAST_CORE_SHAREDPTR_H_INCLUDED
#define BEAST_CORE_SHAREDPTR_H_INCLUDED
#ifndef BEAST_SMARTPTR_SHAREDPTR_H_INCLUDED
#define BEAST_SMARTPTR_SHAREDPTR_H_INCLUDED
#include "../Config.h"
#include "SharedObject.h"
namespace beast {
// Visual Studio doesn't seem to do very well when it comes
// to templated constructors and assignments so we provide
@@ -317,4 +322,6 @@ bool operator!= (T const* lhs, SharedPtr <U> const& rhs) noexcept
}
/** @} */
}
#endif

View File

@@ -17,18 +17,9 @@
*/
//==============================================================================
#ifndef BEAST_THREAD_H_INCLUDED
#define BEAST_THREAD_H_INCLUDED
#include "BeastConfig.h"
#include "thread/LockGuard.h"
#include "thread/UnlockGuard.h"
#include "thread/TryLockGuard.h"
#include "thread/SharedLockGuard.h"
#include "thread/SharedMutexAdapter.h"
#include "thread/SharedData.h"
#include "thread/ServiceQueue.h"
#include "thread/SpinLock.h"
#include "thread/ThreadLocalValue.h"
#include "thread/WaitableEvent.h"
#endif
#include "ContainerDeletePolicy.h"
#include "ScopedPointer.h"
#include "SharedObject.h"
#include "SharedPtr.h"

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#ifndef BEAST_THREAD_LOCKGUARD_H_INCLUDED
#define BEAST_THREAD_LOCKGUARD_H_INCLUDED
#ifndef BEAST_THREADS_LOCKGUARD_H_INCLUDED
#define BEAST_THREADS_LOCKGUARD_H_INCLUDED
#include "../Uncopyable.h"

View File

@@ -21,8 +21,8 @@
*/
//==============================================================================
#ifndef BEAST_THREAD_RECURSIVEMUTEX_H_INCLUDED
#define BEAST_THREAD_RECURSIVEMUTEX_H_INCLUDED
#ifndef BEAST_THREADS_RECURSIVEMUTEX_H_INCLUDED
#define BEAST_THREADS_RECURSIVEMUTEX_H_INCLUDED
#include "../Config.h"
#include "LockGuard.h"

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#ifndef BEAST_THREAD_SERVICEQUEUE_H_INCLUDED
#define BEAST_THREAD_SERVICEQUEUE_H_INCLUDED
#ifndef BEAST_THREADS_SERVICEQUEUE_H_INCLUDED
#define BEAST_THREADS_SERVICEQUEUE_H_INCLUDED
#include "../chrono/CPUMeter.h"
#include "../intrusive/List.h"

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#ifndef BEAST_THREAD_SHAREDDATA_H_INCLUDED
#define BEAST_THREAD_SHAREDDATA_H_INCLUDED
#ifndef BEAST_THREADS_SHAREDDATA_H_INCLUDED
#define BEAST_THREADS_SHAREDDATA_H_INCLUDED
#include "RecursiveMutex.h"
#include "SharedMutexAdapter.h"

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#ifndef BEAST_THREAD_SHAREDLOCKGUARD_H_INCLUDED
#define BEAST_THREAD_SHAREDLOCKGUARD_H_INCLUDED
#ifndef BEAST_THREADS_SHAREDLOCKGUARD_H_INCLUDED
#define BEAST_THREADS_SHAREDLOCKGUARD_H_INCLUDED
#include "../Uncopyable.h"

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#ifndef BEAST_THREAD_SHAREDMUTEXADAPTER_H_INCLUDED
#define BEAST_THREAD_SHAREDMUTEXADAPTER_H_INCLUDED
#ifndef BEAST_THREADS_SHAREDMUTEXADAPTER_H_INCLUDED
#define BEAST_THREADS_SHAREDMUTEXADAPTER_H_INCLUDED
#include "LockGuard.h"
#include "SharedLockGuard.h"

View File

@@ -21,8 +21,8 @@
*/
//==============================================================================
#ifndef BEAST_THREAD_SPINLOCK_H_INCLUDED
#define BEAST_THREAD_SPINLOCK_H_INCLUDED
#ifndef BEAST_THREADS_SPINLOCK_H_INCLUDED
#define BEAST_THREADS_SPINLOCK_H_INCLUDED
#include "../Atomic.h"
#include "LockGuard.h"

View File

@@ -17,8 +17,16 @@
*/
//==============================================================================
#ifndef BEAST_CORE_STOPPABLE_H_INCLUDED
#define BEAST_CORE_STOPPABLE_H_INCLUDED
#ifndef BEAST_THREADS_STOPPABLE_H_INCLUDED
#define BEAST_THREADS_STOPPABLE_H_INCLUDED
#include "../Atomic.h"
#include "../intrusive/LockFreeStack.h"
#include "../utility/Journal.h"
#include "WaitableEvent.h"
namespace beast {
class RootStoppable;
@@ -314,4 +322,6 @@ private:
};
/** @} */
}
#endif

View File

@@ -21,8 +21,14 @@
*/
//==============================================================================
#ifndef BEAST_JUCE_THREAD_H_INCLUDED
#define BEAST_JUCE_THREAD_H_INCLUDED
#ifndef BEAST_THREADS_THREAD_H_INCLUDED
#define BEAST_THREADS_THREAD_H_INCLUDED
#include "../utility/LeakChecked.h"
#include "RecursiveMutex.h"
#include "WaitableEvent.h"
namespace beast {
//==============================================================================
/**
@@ -265,7 +271,7 @@ private:
const String threadName;
void* volatile threadHandle;
ThreadID threadId;
CriticalSection startStopLock;
RecursiveMutex startStopLock;
WaitableEvent startSuspensionEvent, defaultEvent;
int threadPriority;
uint32 affinityMask;
@@ -282,4 +288,7 @@ private:
static bool setThreadPriority (void*, int);
};
#endif // BEAST_THREAD_H_INCLUDED
}
#endif

View File

@@ -21,10 +21,12 @@
*/
//==============================================================================
#ifndef BEAST_THREAD_THREADLOCALVALUE_H_INCLUDED
#define BEAST_THREAD_THREADLOCALVALUE_H_INCLUDED
#ifndef BEAST_THREADS_THREADLOCALVALUE_H_INCLUDED
#define BEAST_THREADS_THREADLOCALVALUE_H_INCLUDED
#include "../Config.h"
#include "SpinLock.h"
#include "Thread.h"
namespace beast {

View File

@@ -19,6 +19,9 @@
#include "BeastConfig.h"
#include "impl/Atomic.cpp"
#include "impl/RecursiveMutex.cpp"
#include "impl/ServiceQueue.cpp"
#include "impl/Stoppable.cpp"
#include "impl/Thread.cpp"
#include "impl/WaitableEvent.cpp"

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#ifndef BEAST_THREAD_TRYLOCKGUARD_H_INCLUDED
#define BEAST_THREAD_TRYLOCKGUARD_H_INCLUDED
#ifndef BEAST_THREADS_TRYLOCKGUARD_H_INCLUDED
#define BEAST_THREADS_TRYLOCKGUARD_H_INCLUDED
#include "../Uncopyable.h"

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#ifndef BEAST_THREAD_UNLOCKGUARD_H_INCLUDED
#define BEAST_THREAD_UNLOCKGUARD_H_INCLUDED
#ifndef BEAST_THREADS_UNLOCKGUARD_H_INCLUDED
#define BEAST_THREADS_UNLOCKGUARD_H_INCLUDED
#include "../Uncopyable.h"

View File

@@ -21,8 +21,8 @@
*/
//==============================================================================
#ifndef BEAST_WAITABLEEVENT_H_INCLUDED
#define BEAST_WAITABLEEVENT_H_INCLUDED
#ifndef BEAST_THREADS_WAITABLEEVENT_H_INCLUDED
#define BEAST_THREADS_WAITABLEEVENT_H_INCLUDED
#include "../Config.h"
#include "../Uncopyable.h"

View File

@@ -0,0 +1,133 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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 "../../../modules/beast_core/beast_core.h" // for UnitTest
namespace beast {
class AtomicTests : public UnitTest
{
public:
AtomicTests() : UnitTest ("Atomic", "beast") {}
template <typename Type>
void testFloat ()
{
Atomic<Type> a, b;
a = (Type) 21;
memoryBarrier();
/* These are some simple test cases to check the atomics - let me know
if any of these assertions fail on your system!
*/
expect (a.get() == (Type) 21);
expect (a.compareAndSetValue ((Type) 100, (Type) 50) == (Type) 21);
expect (a.get() == (Type) 21);
expect (a.compareAndSetValue ((Type) 101, a.get()) == (Type) 21);
expect (a.get() == (Type) 101);
expect (! a.compareAndSetBool ((Type) 300, (Type) 200));
expect (a.get() == (Type) 101);
expect (a.compareAndSetBool ((Type) 200, a.get()));
expect (a.get() == (Type) 200);
expect (a.exchange ((Type) 300) == (Type) 200);
expect (a.get() == (Type) 300);
b = a;
expect (b.get() == a.get());
}
template <typename Type>
void testInteger ()
{
Atomic<Type> a, b;
a.set ((Type) 10);
expect (a.value == (Type) 10);
expect (a.get() == (Type) 10);
a += (Type) 15;
expect (a.get() == (Type) 25);
memoryBarrier();
a -= (Type) 5;
expect (a.get() == (Type) 20);
expect (++a == (Type) 21);
++a;
expect (--a == (Type) 21);
expect (a.get() == (Type) 21);
memoryBarrier();
testFloat <Type> ();
}
void runTest()
{
beginTestCase ("Misc");
char a1[7];
expect (numElementsInArray(a1) == 7);
int a2[3];
expect (numElementsInArray(a2) == 3);
expect (ByteOrder::swap ((uint16) 0x1122) == 0x2211);
expect (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211);
expect (ByteOrder::swap ((uint64) literal64bit (0x1122334455667788)) == literal64bit (0x8877665544332211));
beginTestCase ("int");
testInteger <int> ();
beginTestCase ("unsigned int");
testInteger <unsigned int> ();
beginTestCase ("int32");
testInteger <int32> ();
beginTestCase ("uint32");
testInteger <uint32> ();
beginTestCase ("long");
testInteger <long> ();
beginTestCase ("void*");
testInteger <void*> ();
beginTestCase ("int*");
testInteger <int*> ();
beginTestCase ("float");
testFloat <float> ();
#if ! BEAST_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms
beginTestCase ("int64");
testInteger <int64> ();
beginTestCase ("uint64");
testInteger <uint64> ();
beginTestCase ("double");
testFloat <double> ();
#endif
}
};
static AtomicTests atomicTests;
}

View File

@@ -17,6 +17,10 @@
*/
//==============================================================================
#include "../Stoppable.h"
namespace beast {
Stoppable::Stoppable (char const* name, RootStoppable& root)
: m_name (name)
, m_root (root)
@@ -190,3 +194,5 @@ void RootStoppable::stopAsync ()
stopAsyncRecursive ();
}
}

View File

@@ -0,0 +1,599 @@
//------------------------------------------------------------------------------
/*
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 "../Thread.h"
namespace beast {
Thread::Thread (const String& threadName_)
: threadName (threadName_),
threadHandle (nullptr),
threadId (0),
threadPriority (5),
affinityMask (0),
shouldExit (false)
{
}
Thread::~Thread()
{
/* If your thread class's destructor has been called without first stopping the thread, that
means that this partially destructed object is still performing some work - and that's
probably a Bad Thing!
To avoid this type of nastiness, always make sure you call stopThread() before or during
your subclass's destructor.
*/
check_precondition (! isThreadRunning());
stopThread ();
}
//==============================================================================
// Use a ref-counted object to hold this shared data, so that it can outlive its static
// shared pointer when threads are still running during static shutdown.
struct CurrentThreadHolder : public SharedObject
{
CurrentThreadHolder() noexcept {}
typedef SharedPtr <CurrentThreadHolder> Ptr;
ThreadLocalValue<Thread*> value;
};
static char currentThreadHolderLock [sizeof (SpinLock)]; // (statically initialised to zeros).
static SpinLock* castToSpinLockWithoutAliasingWarning (void* s)
{
return static_cast<SpinLock*> (s);
}
static CurrentThreadHolder::Ptr getCurrentThreadHolder()
{
static CurrentThreadHolder::Ptr currentThreadHolder;
SpinLock::ScopedLockType lock (*castToSpinLockWithoutAliasingWarning (currentThreadHolderLock));
if (currentThreadHolder == nullptr)
currentThreadHolder = new CurrentThreadHolder();
return currentThreadHolder;
}
void Thread::threadEntryPoint()
{
const CurrentThreadHolder::Ptr currentThreadHolder (getCurrentThreadHolder());
currentThreadHolder->value = this;
if (threadName.isNotEmpty())
setCurrentThreadName (threadName);
if (startSuspensionEvent.wait (10000))
{
bassert (getCurrentThreadId() == threadId);
if (affinityMask != 0)
setCurrentThreadAffinityMask (affinityMask);
run();
}
currentThreadHolder->value.releaseCurrentThreadStorage();
closeThreadHandle();
}
// used to wrap the incoming call from the platform-specific code
void BEAST_API beast_threadEntryPoint (void* userData)
{
static_cast <Thread*> (userData)->threadEntryPoint();
}
//==============================================================================
void Thread::startThread()
{
const RecursiveMutex::ScopedLockType sl (startStopLock);
shouldExit = false;
if (threadHandle == nullptr)
{
launchThread();
setThreadPriority (threadHandle, threadPriority);
startSuspensionEvent.signal();
}
}
void Thread::startThread (const int priority)
{
const RecursiveMutex::ScopedLockType sl (startStopLock);
if (threadHandle == nullptr)
{
threadPriority = priority;
startThread();
}
else
{
setPriority (priority);
}
}
bool Thread::isThreadRunning() const
{
return threadHandle != nullptr;
}
Thread* Thread::getCurrentThread()
{
return getCurrentThreadHolder()->value.get();
}
//==============================================================================
void Thread::signalThreadShouldExit()
{
shouldExit = true;
}
bool Thread::waitForThreadToExit (const int timeOutMilliseconds) const
{
// Doh! So how exactly do you expect this thread to wait for itself to stop??
bassert (getThreadId() != getCurrentThreadId() || getCurrentThreadId() == 0);
const uint32 timeoutEnd = Time::getMillisecondCounter() + (uint32) timeOutMilliseconds;
while (isThreadRunning())
{
if (timeOutMilliseconds >= 0 && Time::getMillisecondCounter() > timeoutEnd)
return false;
sleep (2);
}
return true;
}
bool Thread::stopThread (const int timeOutMilliseconds)
{
bool cleanExit = true;
// agh! You can't stop the thread that's calling this method! How on earth
// would that work??
bassert (getCurrentThreadId() != getThreadId());
const RecursiveMutex::ScopedLockType sl (startStopLock);
if (isThreadRunning())
{
signalThreadShouldExit();
notify();
if (timeOutMilliseconds != 0)
{
cleanExit = waitForThreadToExit (timeOutMilliseconds);
}
if (isThreadRunning())
{
bassert (! cleanExit);
// very bad karma if this point is reached, as there are bound to be
// locks and events left in silly states when a thread is killed by force..
killThread();
threadHandle = nullptr;
threadId = 0;
cleanExit = false;
}
else
{
cleanExit = true;
}
}
return cleanExit;
}
void Thread::stopThreadAsync ()
{
const RecursiveMutex::ScopedLockType sl (startStopLock);
if (isThreadRunning())
{
signalThreadShouldExit();
notify();
}
}
//==============================================================================
bool Thread::setPriority (const int newPriority)
{
// NB: deadlock possible if you try to set the thread prio from the thread itself,
// so using setCurrentThreadPriority instead in that case.
if (getCurrentThreadId() == getThreadId())
return setCurrentThreadPriority (newPriority);
const RecursiveMutex::ScopedLockType sl (startStopLock);
if (setThreadPriority (threadHandle, newPriority))
{
threadPriority = newPriority;
return true;
}
return false;
}
bool Thread::setCurrentThreadPriority (const int newPriority)
{
return setThreadPriority (0, newPriority);
}
void Thread::setAffinityMask (const uint32 newAffinityMask)
{
affinityMask = newAffinityMask;
}
//==============================================================================
bool Thread::wait (const int timeOutMilliseconds) const
{
return defaultEvent.wait (timeOutMilliseconds);
}
void Thread::notify() const
{
defaultEvent.signal();
}
//==============================================================================
// This is here so we dont have circular includes
//
void SpinLock::enter() const noexcept
{
if (! tryEnter())
{
for (int i = 20; --i >= 0;)
if (tryEnter())
return;
while (! tryEnter())
Thread::yield();
}
}
}
//------------------------------------------------------------------------------
#if BEAST_WINDOWS
#include <windows.h>
#include <process.h>
#include <tchar.h>
namespace beast {
HWND beast_messageWindowHandle = 0; // (this is used by other parts of the codebase)
void BEAST_API beast_threadEntryPoint (void*);
static unsigned int __stdcall threadEntryProc (void* userData)
{
if (beast_messageWindowHandle != 0)
AttachThreadInput (GetWindowThreadProcessId (beast_messageWindowHandle, 0),
GetCurrentThreadId(), TRUE);
beast_threadEntryPoint (userData);
_endthreadex (0);
return 0;
}
void Thread::launchThread()
{
unsigned int newThreadId;
threadHandle = (void*) _beginthreadex (0, 0, &threadEntryProc, this, 0, &newThreadId);
threadId = (ThreadID) newThreadId;
}
void Thread::closeThreadHandle()
{
CloseHandle ((HANDLE) threadHandle);
threadId = 0;
threadHandle = 0;
}
void Thread::killThread()
{
if (threadHandle != 0)
{
#if BEAST_DEBUG
OutputDebugStringA ("** Warning - Forced thread termination **\n");
#endif
TerminateThread (threadHandle, 0);
}
}
void Thread::setCurrentThreadName (const String& name)
{
#if BEAST_DEBUG && BEAST_MSVC
struct
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
} info;
info.dwType = 0x1000;
info.szName = name.toUTF8();
info.dwThreadID = GetCurrentThreadId();
info.dwFlags = 0;
__try
{
RaiseException (0x406d1388 /*MS_VC_EXCEPTION*/, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{}
#else
(void) name;
#endif
}
Thread::ThreadID Thread::getCurrentThreadId()
{
return (ThreadID) (pointer_sized_int) GetCurrentThreadId();
}
bool Thread::setThreadPriority (void* handle, int priority)
{
int pri = THREAD_PRIORITY_TIME_CRITICAL;
if (priority < 1) pri = THREAD_PRIORITY_IDLE;
else if (priority < 2) pri = THREAD_PRIORITY_LOWEST;
else if (priority < 5) pri = THREAD_PRIORITY_BELOW_NORMAL;
else if (priority < 7) pri = THREAD_PRIORITY_NORMAL;
else if (priority < 9) pri = THREAD_PRIORITY_ABOVE_NORMAL;
else if (priority < 10) pri = THREAD_PRIORITY_HIGHEST;
if (handle == 0)
handle = GetCurrentThread();
return SetThreadPriority (handle, pri) != FALSE;
}
void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask)
{
SetThreadAffinityMask (GetCurrentThread(), affinityMask);
}
struct SleepEvent
{
SleepEvent() noexcept
: handle (CreateEvent (nullptr, FALSE, FALSE,
#if BEAST_DEBUG
_T("BEAST Sleep Event")))
#else
nullptr))
#endif
{}
~SleepEvent() noexcept
{
CloseHandle (handle);
handle = 0;
}
HANDLE handle;
};
static SleepEvent sleepEvent;
void BEAST_CALLTYPE Thread::sleep (const int millisecs)
{
if (millisecs >= 10 || sleepEvent.handle == 0)
{
Sleep ((DWORD) millisecs);
}
else
{
// unlike Sleep() this is guaranteed to return to the current thread after
// the time expires, so we'll use this for short waits, which are more likely
// to need to be accurate
WaitForSingleObject (sleepEvent.handle, (DWORD) millisecs);
}
}
void Thread::yield()
{
Sleep (0);
}
}
//------------------------------------------------------------------------------
#else
#include <time.h>
#if BEAST_BSD
// ???
#else
# include <sys/prctl.h>
#endif
namespace beast {
void BEAST_CALLTYPE Thread::sleep (int millisecs)
{
struct timespec time;
time.tv_sec = millisecs / 1000;
time.tv_nsec = (millisecs % 1000) * 1000000;
nanosleep (&time, nullptr);
}
void BEAST_API beast_threadEntryPoint (void*);
extern "C" void* threadEntryProc (void*);
extern "C" void* threadEntryProc (void* userData)
{
BEAST_AUTORELEASEPOOL
{
#if BEAST_ANDROID
struct AndroidThreadScope
{
AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); }
~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); }
};
const AndroidThreadScope androidEnv;
#endif
beast_threadEntryPoint (userData);
}
return nullptr;
}
void Thread::launchThread()
{
threadHandle = 0;
pthread_t handle = 0;
if (pthread_create (&handle, 0, threadEntryProc, this) == 0)
{
pthread_detach (handle);
threadHandle = (void*) handle;
threadId = (ThreadID) threadHandle;
}
}
void Thread::closeThreadHandle()
{
threadId = 0;
threadHandle = 0;
}
void Thread::killThread()
{
if (threadHandle != 0)
{
#if BEAST_ANDROID
bassertfalse; // pthread_cancel not available!
#else
pthread_cancel ((pthread_t) threadHandle);
#endif
}
}
void Thread::setCurrentThreadName (const String& name)
{
#if BEAST_IOS || (BEAST_MAC && defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
BEAST_AUTORELEASEPOOL
{
[[NSThread currentThread] setName: beastStringToNS (name)];
}
#elif BEAST_LINUX
#if (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012
pthread_setname_np (pthread_self(), name.toRawUTF8());
#else
prctl (PR_SET_NAME, name.toRawUTF8(), 0, 0, 0);
#endif
#endif
}
bool Thread::setThreadPriority (void* handle, int priority)
{
struct sched_param param;
int policy;
priority = blimit (0, 10, priority);
if (handle == nullptr)
handle = (void*) pthread_self();
if (pthread_getschedparam ((pthread_t) handle, &policy, &param) != 0)
return false;
policy = priority == 0 ? SCHED_OTHER : SCHED_RR;
const int minPriority = sched_get_priority_min (policy);
const int maxPriority = sched_get_priority_max (policy);
param.sched_priority = ((maxPriority - minPriority) * priority) / 10 + minPriority;
return pthread_setschedparam ((pthread_t) handle, policy, &param) == 0;
}
Thread::ThreadID Thread::getCurrentThreadId()
{
return (ThreadID) pthread_self();
}
void Thread::yield()
{
sched_yield();
}
//==============================================================================
/* Remove this macro if you're having problems compiling the cpu affinity
calls (the API for these has changed about quite a bit in various Linux
versions, and a lot of distros seem to ship with obsolete versions)
*/
#if defined (CPU_ISSET) && ! defined (SUPPORT_AFFINITIES)
#define SUPPORT_AFFINITIES 1
#endif
void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask)
{
#if SUPPORT_AFFINITIES
cpu_set_t affinity;
CPU_ZERO (&affinity);
for (int i = 0; i < 32; ++i)
if ((affinityMask & (1 << i)) != 0)
CPU_SET (i, &affinity);
/*
N.B. If this line causes a compile error, then you've probably not got the latest
version of glibc installed.
If you don't want to update your copy of glibc and don't care about cpu affinities,
then you can just disable all this stuff by setting the SUPPORT_AFFINITIES macro to 0.
*/
sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinity);
sched_yield();
#else
/* affinities aren't supported because either the appropriate header files weren't found,
or the SUPPORT_AFFINITIES macro was turned off
*/
bassertfalse;
(void) affinityMask;
#endif
}
}
//------------------------------------------------------------------------------
#endif

View File

@@ -17,11 +17,17 @@
*/
//==============================================================================
#ifndef BEAST_LEAKCHECKED_H_INCLUDED
#define BEAST_LEAKCHECKED_H_INCLUDED
#ifndef BEAST_UTILITY_LEAKCHECKED_H_INCLUDED
#define BEAST_UTILITY_LEAKCHECKED_H_INCLUDED
namespace detail
{
#include "../Config.h"
#include "../Atomic.h"
#include "../intrusive/LockFreeStack.h"
#include "StaticObject.h"
namespace beast {
namespace detail {
class LeakCheckedBase
{
@@ -169,4 +175,6 @@ using detail::disabled::LeakChecked;
using detail::disabled::LeakCheckedBase;
#endif
}
#endif

View File

@@ -17,8 +17,10 @@
*/
//==============================================================================
#ifndef BEAST_STATICOBJECT_H_INCLUDED
#define BEAST_STATICOBJECT_H_INCLUDED
#ifndef BEAST_UTILITY_STATICOBJECT_H_INCLUDED
#define BEAST_UTILITY_STATICOBJECT_H_INCLUDED
namespace beast {
// Spec: N2914=09-0104
//
@@ -106,4 +108,6 @@ private:
};
};
}
#endif

View File

@@ -21,8 +21,10 @@
#include "impl/Error.cpp"
// For Journal and Debug
#include "../../modules/beast_core/beast_core.h"
#include "impl/Journal.cpp"
#include "impl/Debug.cpp"
#include "impl/Journal.cpp"
#include "impl/LeakChecked.cpp"
#include "impl/StaticObject.cpp"

View File

@@ -17,6 +17,10 @@
*/
//==============================================================================
#include "../LeakChecked.h"
namespace beast {
namespace detail
{
@@ -124,3 +128,5 @@ void LeakCheckedBase::checkForLeaks ()
}
}
}

View File

@@ -17,6 +17,11 @@
*/
//==============================================================================
#include "../StaticObject.h"
#include "../../threads/Thread.h"
namespace beast {
namespace detail
{
@@ -32,3 +37,5 @@ void staticObjectWait (std::size_t n)
}
}
}

View File

@@ -137,7 +137,6 @@ namespace beast
#include "diagnostic/FatalError.cpp"
#include "diagnostic/FPUFlags.cpp"
#include "diagnostic/LeakChecked.cpp"
#include "diagnostic/SemanticVersion.cpp"
#include "diagnostic/UnitTest.cpp"
#include "diagnostic/UnitTestUtilities.cpp"
@@ -161,7 +160,6 @@ namespace beast
#include "maths/Random.cpp"
#include "memory/MemoryBlock.cpp"
#include "memory/StaticObject.cpp"
#include "misc/Main.cpp"
#include "misc/Result.cpp"
@@ -192,17 +190,12 @@ namespace beast
#include "thread/impl/TrackedMutex.cpp"
#include "thread/DeadlineTimer.cpp"
#include "thread/Stoppable.cpp"
#include "thread/Semaphore.cpp"
#include "thread/Workers.cpp"
#include "threads/ChildProcess.cpp"
#include "threads/ReadWriteLock.cpp"
#include "threads/ReadWriteMutex.cpp"
#include "threads/SpinDelay.cpp"
#include "threads/Thread.cpp"
#include "threads/ThreadPool.cpp"
#include "threads/TimeSliceThread.cpp"
#include "time/PerformanceCounter.cpp"
#include "time/AtExitHook.cpp"

View File

@@ -58,7 +58,7 @@
#include "../../beast/SafeBool.h"
#include "../../beast/Strings.h"
#include "../../beast/TypeTraits.h"
#include "../../beast/Thread.h"
#include "../../beast/Threads.h"
#include "../../beast/Utility.h"
#include "../../beast/Chrono.h"
@@ -81,10 +81,8 @@ class FileOutputStream;
#include "memory/AtomicPointer.h"
#include "memory/AtomicState.h"
#include "threads/SpinDelay.h"
#include "memory/StaticObject.h"
#include "time/AtExitHook.h"
#include "diagnostic/LeakChecked.h"
#include "time/Time.h"
#include "threads/ScopedLock.h"
#include "threads/CriticalSection.h"
@@ -147,8 +145,6 @@ class FileOutputStream;
#include "memory/MemoryAlignment.h"
#include "memory/CacheLine.h"
#include "threads/ReadWriteMutex.h"
#include "threads/Thread.h"
#include "thread/MutexTraits.h"
#include "thread/TrackedMutex.h"
#include "diagnostic/FatalError.h"
@@ -157,8 +153,6 @@ class FileOutputStream;
#include "maths/uint24.h"
#include "logging/Logger.h"
#include "diagnostic/FPUFlags.h"
#include "memory/SharedObject.h"
#include "memory/SharedPtr.h"
#include "memory/SharedFunction.h"
#include "containers/AbstractFifo.h"
#include "text/Identifier.h"
@@ -223,8 +217,6 @@ class FileOutputStream;
#include "threads/Process.h"
#include "threads/ScopedReadLock.h"
#include "threads/ScopedWriteLock.h"
#include "threads/ThreadPool.h"
#include "threads/TimeSliceThread.h"
#include "diagnostic/UnitTest.h"
#include "xml/XmlDocument.h"
#include "xml/XmlElement.h"
@@ -238,7 +230,6 @@ class FileOutputStream;
#include "thread/DeadlineTimer.h"
#include "thread/Semaphore.h"
#include "thread/Stoppable.h"
#include "thread/Workers.h"
}

View File

@@ -170,8 +170,7 @@ public:
}
};
/** The type of a list of tests.
*/
/** The type of a list of tests. */
typedef Array <UnitTest*, CriticalSection> TestList;
//--------------------------------------------------------------------------

View File

@@ -39,13 +39,6 @@ bool CriticalSection::tryEnter() const noexcept { return pthread_mutex_trylock (
void CriticalSection::exit() const noexcept { pthread_mutex_unlock (&mutex); }
//==============================================================================
void BEAST_CALLTYPE Thread::sleep (int millisecs)
{
struct timespec time;
time.tv_sec = millisecs / 1000;
time.tv_nsec = (millisecs % 1000) * 1000000;
nanosleep (&time, nullptr);
}
void Process::terminate()
{
@@ -913,146 +906,7 @@ void InterProcessLock::exit()
}
//==============================================================================
void BEAST_API beast_threadEntryPoint (void*);
extern "C" void* threadEntryProc (void*);
extern "C" void* threadEntryProc (void* userData)
{
BEAST_AUTORELEASEPOOL
{
#if BEAST_ANDROID
struct AndroidThreadScope
{
AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); }
~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); }
};
const AndroidThreadScope androidEnv;
#endif
beast_threadEntryPoint (userData);
}
return nullptr;
}
void Thread::launchThread()
{
threadHandle = 0;
pthread_t handle = 0;
if (pthread_create (&handle, 0, threadEntryProc, this) == 0)
{
pthread_detach (handle);
threadHandle = (void*) handle;
threadId = (ThreadID) threadHandle;
}
}
void Thread::closeThreadHandle()
{
threadId = 0;
threadHandle = 0;
}
void Thread::killThread()
{
if (threadHandle != 0)
{
#if BEAST_ANDROID
bassertfalse; // pthread_cancel not available!
#else
pthread_cancel ((pthread_t) threadHandle);
#endif
}
}
void Thread::setCurrentThreadName (const String& name)
{
#if BEAST_IOS || (BEAST_MAC && defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
BEAST_AUTORELEASEPOOL
{
[[NSThread currentThread] setName: beastStringToNS (name)];
}
#elif BEAST_LINUX
#if (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012
pthread_setname_np (pthread_self(), name.toRawUTF8());
#else
prctl (PR_SET_NAME, name.toRawUTF8(), 0, 0, 0);
#endif
#endif
}
bool Thread::setThreadPriority (void* handle, int priority)
{
struct sched_param param;
int policy;
priority = blimit (0, 10, priority);
if (handle == nullptr)
handle = (void*) pthread_self();
if (pthread_getschedparam ((pthread_t) handle, &policy, &param) != 0)
return false;
policy = priority == 0 ? SCHED_OTHER : SCHED_RR;
const int minPriority = sched_get_priority_min (policy);
const int maxPriority = sched_get_priority_max (policy);
param.sched_priority = ((maxPriority - minPriority) * priority) / 10 + minPriority;
return pthread_setschedparam ((pthread_t) handle, policy, &param) == 0;
}
Thread::ThreadID Thread::getCurrentThreadId()
{
return (ThreadID) pthread_self();
}
void Thread::yield()
{
sched_yield();
}
//==============================================================================
/* Remove this macro if you're having problems compiling the cpu affinity
calls (the API for these has changed about quite a bit in various Linux
versions, and a lot of distros seem to ship with obsolete versions)
*/
#if defined (CPU_ISSET) && ! defined (SUPPORT_AFFINITIES)
#define SUPPORT_AFFINITIES 1
#endif
void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask)
{
#if SUPPORT_AFFINITIES
cpu_set_t affinity;
CPU_ZERO (&affinity);
for (int i = 0; i < 32; ++i)
if ((affinityMask & (1 << i)) != 0)
CPU_SET (i, &affinity);
/*
N.B. If this line causes a compile error, then you've probably not got the latest
version of glibc installed.
If you don't want to update your copy of glibc and don't care about cpu affinities,
then you can just disable all this stuff by setting the SUPPORT_AFFINITIES macro to 0.
*/
sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinity);
sched_yield();
#else
/* affinities aren't supported because either the appropriate header files weren't found,
or the SUPPORT_AFFINITIES macro was turned off
*/
bassertfalse;
(void) affinityMask;
#endif
}
//==============================================================================
bool DynamicLibrary::open (const String& name)
{
close();

View File

@@ -21,8 +21,6 @@
*/
//==============================================================================
HWND beast_messageWindowHandle = 0; // (this is used by other parts of the codebase)
void* getUser32Function (const char* functionName)
{
HMODULE module = GetModuleHandleA ("user32.dll");
@@ -72,143 +70,6 @@ void CriticalSection::enter() const noexcept { EnterCriticalSection ((CRITICAL_S
bool CriticalSection::tryEnter() const noexcept { return TryEnterCriticalSection ((CRITICAL_SECTION*) section) != FALSE; }
void CriticalSection::exit() const noexcept { LeaveCriticalSection ((CRITICAL_SECTION*) section); }
//==============================================================================
void BEAST_API beast_threadEntryPoint (void*);
static unsigned int __stdcall threadEntryProc (void* userData)
{
if (beast_messageWindowHandle != 0)
AttachThreadInput (GetWindowThreadProcessId (beast_messageWindowHandle, 0),
GetCurrentThreadId(), TRUE);
beast_threadEntryPoint (userData);
_endthreadex (0);
return 0;
}
void Thread::launchThread()
{
unsigned int newThreadId;
threadHandle = (void*) _beginthreadex (0, 0, &threadEntryProc, this, 0, &newThreadId);
threadId = (ThreadID) newThreadId;
}
void Thread::closeThreadHandle()
{
CloseHandle ((HANDLE) threadHandle);
threadId = 0;
threadHandle = 0;
}
void Thread::killThread()
{
if (threadHandle != 0)
{
#if BEAST_DEBUG
OutputDebugStringA ("** Warning - Forced thread termination **\n");
#endif
TerminateThread (threadHandle, 0);
}
}
void Thread::setCurrentThreadName (const String& name)
{
#if BEAST_DEBUG && BEAST_MSVC
struct
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
} info;
info.dwType = 0x1000;
info.szName = name.toUTF8();
info.dwThreadID = GetCurrentThreadId();
info.dwFlags = 0;
__try
{
RaiseException (0x406d1388 /*MS_VC_EXCEPTION*/, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{}
#else
(void) name;
#endif
}
Thread::ThreadID Thread::getCurrentThreadId()
{
return (ThreadID) (pointer_sized_int) GetCurrentThreadId();
}
bool Thread::setThreadPriority (void* handle, int priority)
{
int pri = THREAD_PRIORITY_TIME_CRITICAL;
if (priority < 1) pri = THREAD_PRIORITY_IDLE;
else if (priority < 2) pri = THREAD_PRIORITY_LOWEST;
else if (priority < 5) pri = THREAD_PRIORITY_BELOW_NORMAL;
else if (priority < 7) pri = THREAD_PRIORITY_NORMAL;
else if (priority < 9) pri = THREAD_PRIORITY_ABOVE_NORMAL;
else if (priority < 10) pri = THREAD_PRIORITY_HIGHEST;
if (handle == 0)
handle = GetCurrentThread();
return SetThreadPriority (handle, pri) != FALSE;
}
void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask)
{
SetThreadAffinityMask (GetCurrentThread(), affinityMask);
}
//==============================================================================
struct SleepEvent
{
SleepEvent() noexcept
: handle (CreateEvent (nullptr, FALSE, FALSE,
#if BEAST_DEBUG
_T("BEAST Sleep Event")))
#else
nullptr))
#endif
{}
~SleepEvent() noexcept
{
CloseHandle (handle);
handle = 0;
}
HANDLE handle;
};
static SleepEvent sleepEvent;
void BEAST_CALLTYPE Thread::sleep (const int millisecs)
{
if (millisecs >= 10 || sleepEvent.handle == 0)
{
Sleep ((DWORD) millisecs);
}
else
{
// unlike Sleep() this is guaranteed to return to the current thread after
// the time expires, so we'll use this for short waits, which are more likely
// to need to be accurate
WaitForSingleObject (sleepEvent.handle, (DWORD) millisecs);
}
}
void Thread::yield()
{
Sleep (0);
}
//==============================================================================
static int lastProcessPriority = -1;

View File

@@ -1,98 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
ReadWriteMutex::ReadWriteMutex () noexcept
{
}
ReadWriteMutex::~ReadWriteMutex () noexcept
{
}
void ReadWriteMutex::enterRead () const noexcept
{
for (;;)
{
// attempt the lock optimistically
// THIS IS NOT CACHE-FRIENDLY!
m_readers->addref ();
// is there a writer?
// THIS IS NOT CACHE-FRIENDLY!
if (m_writes->isSignaled ())
{
// a writer exists, give up the read lock
m_readers->release ();
// block until the writer is done
{
CriticalSection::ScopedLockType lock (m_mutex);
}
// now try the loop again
}
else
{
break;
}
}
}
void ReadWriteMutex::exitRead () const noexcept
{
m_readers->release ();
}
void ReadWriteMutex::enterWrite () const noexcept
{
// Optimistically acquire the write lock.
m_writes->addref ();
// Go for the mutex.
// Another writer might block us here.
m_mutex.enter ();
// Only one competing writer will get here,
// but we don't know who, so we have to drain
// readers no matter what. New readers will be
// blocked by the mutex.
//
if (m_readers->isSignaled ())
{
SpinDelay delay;
do
{
delay.pause ();
}
while (m_readers->isSignaled ());
}
}
void ReadWriteMutex::exitWrite () const noexcept
{
// Releasing the mutex first and then decrementing the
// writer count allows another waiting writer to atomically
// acquire the lock, thus starving readers. This fulfills
// the write-preferencing requirement.
m_mutex.exit ();
m_writes->release ();
}

View File

@@ -1,150 +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_H_INCLUDED
#define BEAST_READWRITEMUTEX_H_INCLUDED
/*============================================================================*/
/**
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 : public 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 : public 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 BEAST_API ReadWriteMutex
{
public:
/** Provides the type of scoped read lock to use with a ReadWriteMutex. */
typedef GenericScopedReadLock <ReadWriteMutex> ScopedReadLockType;
/** Provides the type of scoped write lock to use with a ReadWriteMutex. */
typedef GenericScopedWriteLock <ReadWriteMutex> ScopedWriteLockType;
/** Create a ReadWriteMutex */
ReadWriteMutex () noexcept;
/** Destroy a ReadWriteMutex
If the object is destroyed while a lock is held, the result is
undefined behavior.
*/
~ReadWriteMutex () noexcept;
/** Acquire a read lock.
This is recursive with respect to other read locks. Calling this while
holding a write lock is undefined.
*/
void enterRead () const noexcept;
/** Release a previously acquired read lock */
void exitRead () const noexcept;
/** Acquire a write lock.
This is recursive with respect to other write locks. Calling this while
holding a read lock is undefined.
*/
void enterWrite () const noexcept;
/** Release a previously acquired write lock */
void exitWrite () const noexcept;
private:
CriticalSection m_mutex;
mutable CacheLine::Padded <AtomicCounter> m_writes;
mutable CacheLine::Padded <AtomicCounter> m_readers;
};
#endif

View File

@@ -1,376 +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.
*/
//==============================================================================
Thread::Thread (const String& threadName_)
: threadName (threadName_),
threadHandle (nullptr),
threadId (0),
threadPriority (5),
affinityMask (0),
shouldExit (false)
{
}
Thread::~Thread()
{
/* If your thread class's destructor has been called without first stopping the thread, that
means that this partially destructed object is still performing some work - and that's
probably a Bad Thing!
To avoid this type of nastiness, always make sure you call stopThread() before or during
your subclass's destructor.
*/
check_precondition (! isThreadRunning());
stopThread ();
}
//==============================================================================
// Use a ref-counted object to hold this shared data, so that it can outlive its static
// shared pointer when threads are still running during static shutdown.
struct CurrentThreadHolder : public SharedObject
{
CurrentThreadHolder() noexcept {}
typedef SharedPtr <CurrentThreadHolder> Ptr;
ThreadLocalValue<Thread*> value;
};
static char currentThreadHolderLock [sizeof (SpinLock)]; // (statically initialised to zeros).
static SpinLock* castToSpinLockWithoutAliasingWarning (void* s)
{
return static_cast<SpinLock*> (s);
}
static CurrentThreadHolder::Ptr getCurrentThreadHolder()
{
static CurrentThreadHolder::Ptr currentThreadHolder;
SpinLock::ScopedLockType lock (*castToSpinLockWithoutAliasingWarning (currentThreadHolderLock));
if (currentThreadHolder == nullptr)
currentThreadHolder = new CurrentThreadHolder();
return currentThreadHolder;
}
void Thread::threadEntryPoint()
{
const CurrentThreadHolder::Ptr currentThreadHolder (getCurrentThreadHolder());
currentThreadHolder->value = this;
if (threadName.isNotEmpty())
setCurrentThreadName (threadName);
if (startSuspensionEvent.wait (10000))
{
bassert (getCurrentThreadId() == threadId);
if (affinityMask != 0)
setCurrentThreadAffinityMask (affinityMask);
run();
}
currentThreadHolder->value.releaseCurrentThreadStorage();
closeThreadHandle();
}
// used to wrap the incoming call from the platform-specific code
void BEAST_API beast_threadEntryPoint (void* userData)
{
static_cast <Thread*> (userData)->threadEntryPoint();
}
//==============================================================================
void Thread::startThread()
{
const ScopedLock sl (startStopLock);
shouldExit = false;
if (threadHandle == nullptr)
{
launchThread();
setThreadPriority (threadHandle, threadPriority);
startSuspensionEvent.signal();
}
}
void Thread::startThread (const int priority)
{
const ScopedLock sl (startStopLock);
if (threadHandle == nullptr)
{
threadPriority = priority;
startThread();
}
else
{
setPriority (priority);
}
}
bool Thread::isThreadRunning() const
{
return threadHandle != nullptr;
}
Thread* Thread::getCurrentThread()
{
return getCurrentThreadHolder()->value.get();
}
//==============================================================================
void Thread::signalThreadShouldExit()
{
shouldExit = true;
}
bool Thread::waitForThreadToExit (const int timeOutMilliseconds) const
{
// Doh! So how exactly do you expect this thread to wait for itself to stop??
bassert (getThreadId() != getCurrentThreadId() || getCurrentThreadId() == 0);
const uint32 timeoutEnd = Time::getMillisecondCounter() + (uint32) timeOutMilliseconds;
while (isThreadRunning())
{
if (timeOutMilliseconds >= 0 && Time::getMillisecondCounter() > timeoutEnd)
return false;
sleep (2);
}
return true;
}
bool Thread::stopThread (const int timeOutMilliseconds)
{
bool cleanExit = true;
// agh! You can't stop the thread that's calling this method! How on earth
// would that work??
bassert (getCurrentThreadId() != getThreadId());
const ScopedLock sl (startStopLock);
if (isThreadRunning())
{
signalThreadShouldExit();
notify();
if (timeOutMilliseconds != 0)
{
cleanExit = waitForThreadToExit (timeOutMilliseconds);
}
if (isThreadRunning())
{
bassert (! cleanExit);
// very bad karma if this point is reached, as there are bound to be
// locks and events left in silly states when a thread is killed by force..
killThread();
threadHandle = nullptr;
threadId = 0;
cleanExit = false;
}
else
{
cleanExit = true;
}
}
return cleanExit;
}
void Thread::stopThreadAsync ()
{
const ScopedLock sl (startStopLock);
if (isThreadRunning())
{
signalThreadShouldExit();
notify();
}
}
//==============================================================================
bool Thread::setPriority (const int newPriority)
{
// NB: deadlock possible if you try to set the thread prio from the thread itself,
// so using setCurrentThreadPriority instead in that case.
if (getCurrentThreadId() == getThreadId())
return setCurrentThreadPriority (newPriority);
const ScopedLock sl (startStopLock);
if (setThreadPriority (threadHandle, newPriority))
{
threadPriority = newPriority;
return true;
}
return false;
}
bool Thread::setCurrentThreadPriority (const int newPriority)
{
return setThreadPriority (0, newPriority);
}
void Thread::setAffinityMask (const uint32 newAffinityMask)
{
affinityMask = newAffinityMask;
}
//==============================================================================
bool Thread::wait (const int timeOutMilliseconds) const
{
return defaultEvent.wait (timeOutMilliseconds);
}
void Thread::notify() const
{
defaultEvent.signal();
}
//==============================================================================
void SpinLock::enter() const noexcept
{
if (! tryEnter())
{
for (int i = 20; --i >= 0;)
if (tryEnter())
return;
while (! tryEnter())
Thread::yield();
}
}
//==============================================================================
class AtomicTests : public UnitTest
{
public:
AtomicTests() : UnitTest ("Atomic", "beast") {}
void runTest()
{
beginTestCase ("Misc");
char a1[7];
expect (numElementsInArray(a1) == 7);
int a2[3];
expect (numElementsInArray(a2) == 3);
expect (ByteOrder::swap ((uint16) 0x1122) == 0x2211);
expect (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211);
expect (ByteOrder::swap ((uint64) literal64bit (0x1122334455667788)) == literal64bit (0x8877665544332211));
beginTestCase ("int");
AtomicTester <int>::testInteger (*this);
beginTestCase ("unsigned int");
AtomicTester <unsigned int>::testInteger (*this);
beginTestCase ("int32");
AtomicTester <int32>::testInteger (*this);
beginTestCase ("uint32");
AtomicTester <uint32>::testInteger (*this);
beginTestCase ("long");
AtomicTester <long>::testInteger (*this);
beginTestCase ("void*");
AtomicTester <void*>::testInteger (*this);
beginTestCase ("int*");
AtomicTester <int*>::testInteger (*this);
beginTestCase ("float");
AtomicTester <float>::testFloat (*this);
#if ! BEAST_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms
beginTestCase ("int64");
AtomicTester <int64>::testInteger (*this);
beginTestCase ("uint64");
AtomicTester <uint64>::testInteger (*this);
beginTestCase ("double");
AtomicTester <double>::testFloat (*this);
#endif
}
template <typename Type>
class AtomicTester
{
public:
AtomicTester() {}
static void testInteger (UnitTest& test)
{
Atomic<Type> a, b;
a.set ((Type) 10);
test.expect (a.value == (Type) 10);
test.expect (a.get() == (Type) 10);
a += (Type) 15;
test.expect (a.get() == (Type) 25);
memoryBarrier();
a -= (Type) 5;
test.expect (a.get() == (Type) 20);
test.expect (++a == (Type) 21);
++a;
test.expect (--a == (Type) 21);
test.expect (a.get() == (Type) 21);
memoryBarrier();
testFloat (test);
}
static void testFloat (UnitTest& test)
{
Atomic<Type> a, b;
a = (Type) 21;
memoryBarrier();
/* These are some simple test cases to check the atomics - let me know
if any of these assertions fail on your system!
*/
test.expect (a.get() == (Type) 21);
test.expect (a.compareAndSetValue ((Type) 100, (Type) 50) == (Type) 21);
test.expect (a.get() == (Type) 21);
test.expect (a.compareAndSetValue ((Type) 101, a.get()) == (Type) 21);
test.expect (a.get() == (Type) 101);
test.expect (! a.compareAndSetBool ((Type) 300, (Type) 200));
test.expect (a.get() == (Type) 101);
test.expect (a.compareAndSetBool ((Type) 200, a.get()));
test.expect (a.get() == (Type) 200);
test.expect (a.exchange ((Type) 300) == (Type) 200);
test.expect (a.get() == (Type) 300);
b = a;
test.expect (b.get() == a.get());
}
};
};
static AtomicTests atomicTests;

View File

@@ -1,371 +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.
*/
//==============================================================================
ThreadPoolJob::ThreadPoolJob (const String& name)
: jobName (name),
pool (nullptr),
shouldStop (false),
isActive (false),
shouldBeDeleted (false)
{
}
ThreadPoolJob::~ThreadPoolJob()
{
// you mustn't delete a job while it's still in a pool! Use ThreadPool::removeJob()
// to remove it first!
bassert (pool == nullptr || ! pool->contains (this));
}
String ThreadPoolJob::getJobName() const
{
return jobName;
}
void ThreadPoolJob::setJobName (const String& newName)
{
jobName = newName;
}
void ThreadPoolJob::signalJobShouldExit()
{
shouldStop = true;
}
//==============================================================================
class ThreadPool::ThreadPoolThread
: public Thread
, LeakChecked <ThreadPoolThread>
{
public:
ThreadPoolThread (ThreadPool& pool_)
: Thread ("Pool"),
pool (pool_)
{
}
void run() override
{
while (! threadShouldExit())
{
if (! pool.runNextJob())
wait (500);
}
}
private:
ThreadPool& pool;
};
//==============================================================================
ThreadPool::ThreadPool (const int numThreads)
{
bassert (numThreads > 0); // not much point having a pool without any threads!
createThreads (numThreads);
}
ThreadPool::ThreadPool()
{
createThreads (SystemStats::getNumCpus());
}
ThreadPool::~ThreadPool()
{
removeAllJobs (true, 5000);
stopThreads();
}
void ThreadPool::createThreads (int numThreads)
{
for (int i = bmax (1, numThreads); --i >= 0;)
threads.add (new ThreadPoolThread (*this));
for (int i = threads.size(); --i >= 0;)
threads.getUnchecked(i)->startThread();
}
void ThreadPool::stopThreads()
{
for (int i = threads.size(); --i >= 0;)
threads.getUnchecked(i)->signalThreadShouldExit();
for (int i = threads.size(); --i >= 0;)
threads.getUnchecked(i)->stopThread (500);
}
void ThreadPool::addJob (ThreadPoolJob* const job, const bool deleteJobWhenFinished)
{
bassert (job != nullptr);
bassert (job->pool == nullptr);
if (job->pool == nullptr)
{
job->pool = this;
job->shouldStop = false;
job->isActive = false;
job->shouldBeDeleted = deleteJobWhenFinished;
{
const ScopedLock sl (lock);
jobs.add (job);
}
for (int i = threads.size(); --i >= 0;)
threads.getUnchecked(i)->notify();
}
}
int ThreadPool::getNumJobs() const
{
return jobs.size();
}
ThreadPoolJob* ThreadPool::getJob (const int index) const
{
const ScopedLock sl (lock);
return jobs [index];
}
bool ThreadPool::contains (const ThreadPoolJob* const job) const
{
const ScopedLock sl (lock);
return jobs.contains (const_cast <ThreadPoolJob*> (job));
}
bool ThreadPool::isJobRunning (const ThreadPoolJob* const job) const
{
const ScopedLock sl (lock);
return jobs.contains (const_cast <ThreadPoolJob*> (job)) && job->isActive;
}
bool ThreadPool::waitForJobToFinish (const ThreadPoolJob* const job,
const int timeOutMs) const
{
if (job != nullptr)
{
const uint32 start = Time::getMillisecondCounter();
while (contains (job))
{
if (timeOutMs >= 0 && Time::getMillisecondCounter() >= start + (uint32) timeOutMs)
return false;
jobFinishedSignal.wait (2);
}
}
return true;
}
bool ThreadPool::removeJob (ThreadPoolJob* const job,
const bool interruptIfRunning,
const int timeOutMs)
{
bool dontWait = true;
OwnedArray<ThreadPoolJob> deletionList;
if (job != nullptr)
{
const ScopedLock sl (lock);
if (jobs.contains (job))
{
if (job->isActive)
{
if (interruptIfRunning)
job->signalJobShouldExit();
dontWait = false;
}
else
{
jobs.removeFirstMatchingValue (job);
addToDeleteList (deletionList, job);
}
}
}
return dontWait || waitForJobToFinish (job, timeOutMs);
}
bool ThreadPool::removeAllJobs (const bool interruptRunningJobs, const int timeOutMs,
ThreadPool::JobSelector* selectedJobsToRemove)
{
Array <ThreadPoolJob*> jobsToWaitFor;
{
OwnedArray<ThreadPoolJob> deletionList;
{
const ScopedLock sl (lock);
for (int i = jobs.size(); --i >= 0;)
{
ThreadPoolJob* const job = jobs.getUnchecked(i);
if (selectedJobsToRemove == nullptr || selectedJobsToRemove->isJobSuitable (job))
{
if (job->isActive)
{
jobsToWaitFor.add (job);
if (interruptRunningJobs)
job->signalJobShouldExit();
}
else
{
jobs.remove (i);
addToDeleteList (deletionList, job);
}
}
}
}
}
const uint32 start = Time::getMillisecondCounter();
for (;;)
{
for (int i = jobsToWaitFor.size(); --i >= 0;)
{
ThreadPoolJob* const job = jobsToWaitFor.getUnchecked (i);
if (! isJobRunning (job))
jobsToWaitFor.remove (i);
}
if (jobsToWaitFor.size() == 0)
break;
if (timeOutMs >= 0 && Time::getMillisecondCounter() >= start + (uint32) timeOutMs)
return false;
jobFinishedSignal.wait (20);
}
return true;
}
StringArray ThreadPool::getNamesOfAllJobs (const bool onlyReturnActiveJobs) const
{
StringArray s;
const ScopedLock sl (lock);
for (int i = 0; i < jobs.size(); ++i)
{
const ThreadPoolJob* const job = jobs.getUnchecked(i);
if (job->isActive || ! onlyReturnActiveJobs)
s.add (job->getJobName());
}
return s;
}
bool ThreadPool::setThreadPriorities (const int newPriority)
{
bool ok = true;
for (int i = threads.size(); --i >= 0;)
if (! threads.getUnchecked(i)->setPriority (newPriority))
ok = false;
return ok;
}
ThreadPoolJob* ThreadPool::pickNextJobToRun()
{
OwnedArray<ThreadPoolJob> deletionList;
{
const ScopedLock sl (lock);
for (int i = 0; i < jobs.size(); ++i)
{
ThreadPoolJob* job = jobs[i];
if (job != nullptr && ! job->isActive)
{
if (job->shouldStop)
{
jobs.remove (i);
addToDeleteList (deletionList, job);
--i;
continue;
}
job->isActive = true;
return job;
}
}
}
return nullptr;
}
bool ThreadPool::runNextJob()
{
ThreadPoolJob* const job = pickNextJobToRun();
if (job == nullptr)
return false;
ThreadPoolJob::JobStatus result = ThreadPoolJob::jobHasFinished;
result = job->runJob();
OwnedArray<ThreadPoolJob> deletionList;
{
const ScopedLock sl (lock);
if (jobs.contains (job))
{
job->isActive = false;
if (result != ThreadPoolJob::jobNeedsRunningAgain || job->shouldStop)
{
jobs.removeFirstMatchingValue (job);
addToDeleteList (deletionList, job);
jobFinishedSignal.signal();
}
else
{
// move the job to the end of the queue if it wants another go
jobs.move (jobs.indexOf (job), -1);
}
}
}
return true;
}
void ThreadPool::addToDeleteList (OwnedArray<ThreadPoolJob>& deletionList, ThreadPoolJob* const job) const
{
job->shouldStop = true;
job->pool = nullptr;
if (job->shouldBeDeleted)
deletionList.add (job);
}

View File

@@ -1,304 +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_THREADPOOL_H_INCLUDED
#define BEAST_THREADPOOL_H_INCLUDED
class ThreadPool;
class ThreadPoolThread;
//==============================================================================
/**
A task that is executed by a ThreadPool object.
A ThreadPool keeps a list of ThreadPoolJob objects which are executed by
its threads.
The runJob() method needs to be implemented to do the task, and if the code that
does the work takes a significant time to run, it must keep checking the shouldExit()
method to see if something is trying to interrupt the job. If shouldExit() returns
true, the runJob() method must return immediately.
@see ThreadPool, Thread
*/
class BEAST_API ThreadPoolJob : LeakChecked <ThreadPoolJob>, public Uncopyable
{
public:
//==============================================================================
/** Creates a thread pool job object.
After creating your job, add it to a thread pool with ThreadPool::addJob().
*/
explicit ThreadPoolJob (const String& name);
/** Destructor. */
virtual ~ThreadPoolJob();
//==============================================================================
/** Returns the name of this job.
@see setJobName
*/
String getJobName() const;
/** Changes the job's name.
@see getJobName
*/
void setJobName (const String& newName);
//==============================================================================
/** These are the values that can be returned by the runJob() method.
*/
enum JobStatus
{
jobHasFinished = 0, /**< indicates that the job has finished and can be
removed from the pool. */
jobNeedsRunningAgain /**< indicates that the job would like to be called
again when a thread is free. */
};
/** Peforms the actual work that this job needs to do.
Your subclass must implement this method, in which is does its work.
If the code in this method takes a significant time to run, it must repeatedly check
the shouldExit() method to see if something is trying to interrupt the job.
If shouldExit() ever returns true, the runJob() method must return immediately.
If this method returns jobHasFinished, then the job will be removed from the pool
immediately. If it returns jobNeedsRunningAgain, then the job will be left in the
pool and will get a chance to run again as soon as a thread is free.
@see shouldExit()
*/
virtual JobStatus runJob() = 0;
//==============================================================================
/** Returns true if this job is currently running its runJob() method. */
bool isRunning() const noexcept { return isActive; }
/** Returns true if something is trying to interrupt this job and make it stop.
Your runJob() method must call this whenever it gets a chance, and if it ever
returns true, the runJob() method must return immediately.
@see signalJobShouldExit()
*/
bool shouldExit() const noexcept { return shouldStop; }
/** Calling this will cause the shouldExit() method to return true, and the job
should (if it's been implemented correctly) stop as soon as possible.
@see shouldExit()
*/
void signalJobShouldExit();
//==============================================================================
private:
friend class ThreadPool;
friend class ThreadPoolThread;
String jobName;
ThreadPool* pool;
bool shouldStop, isActive, shouldBeDeleted;
};
//==============================================================================
/**
A set of threads that will run a list of jobs.
When a ThreadPoolJob object is added to the ThreadPool's list, its runJob() method
will be called by the next pooled thread that becomes free.
@see ThreadPoolJob, Thread
*/
class BEAST_API ThreadPool : LeakChecked <ThreadPool>, public Uncopyable
{
public:
//==============================================================================
/** Creates a thread pool.
Once you've created a pool, you can give it some jobs by calling addJob().
@param numberOfThreads the number of threads to run. These will be started
immediately, and will run until the pool is deleted.
*/
ThreadPool (int numberOfThreads);
/** Creates a thread pool with one thread per CPU core.
Once you've created a pool, you can give it some jobs by calling addJob().
If you want to specify the number of threads, use the other constructor; this
one creates a pool which has one thread for each CPU core.
@see SystemStats::getNumCpus()
*/
ThreadPool();
/** Destructor.
This will attempt to remove all the jobs before deleting, but if you want to
specify a timeout, you should call removeAllJobs() explicitly before deleting
the pool.
*/
~ThreadPool();
//==============================================================================
/** A callback class used when you need to select which ThreadPoolJob objects are suitable
for some kind of operation.
@see ThreadPool::removeAllJobs
*/
class BEAST_API JobSelector
{
public:
virtual ~JobSelector() {}
/** Should return true if the specified thread matches your criteria for whatever
operation that this object is being used for.
Any implementation of this method must be extremely fast and thread-safe!
*/
virtual bool isJobSuitable (ThreadPoolJob* job) = 0;
};
//==============================================================================
/** Adds a job to the queue.
Once a job has been added, then the next time a thread is free, it will run
the job's ThreadPoolJob::runJob() method. Depending on the return value of the
runJob() method, the pool will either remove the job from the pool or add it to
the back of the queue to be run again.
If deleteJobWhenFinished is true, then the job object will be owned and deleted by
the pool when not needed - if you do this, make sure that your object's destructor
is thread-safe.
If deleteJobWhenFinished is false, the pointer will be used but not deleted, and
the caller is responsible for making sure the object is not deleted before it has
been removed from the pool.
*/
void addJob (ThreadPoolJob* job,
bool deleteJobWhenFinished);
/** Tries to remove a job from the pool.
If the job isn't yet running, this will simply remove it. If it is running, it
will wait for it to finish.
If the timeout period expires before the job finishes running, then the job will be
left in the pool and this will return false. It returns true if the job is sucessfully
stopped and removed.
@param job the job to remove
@param interruptIfRunning if true, then if the job is currently busy, its
ThreadPoolJob::signalJobShouldExit() method will be called to try
to interrupt it. If false, then if the job will be allowed to run
until it stops normally (or the timeout expires)
@param timeOutMilliseconds the length of time this method should wait for the job to finish
before giving up and returning false
*/
bool removeJob (ThreadPoolJob* job,
bool interruptIfRunning,
int timeOutMilliseconds);
/** Tries to remove all jobs from the pool.
@param interruptRunningJobs if true, then all running jobs will have their ThreadPoolJob::signalJobShouldExit()
methods called to try to interrupt them
@param timeOutMilliseconds the length of time this method should wait for all the jobs to finish
before giving up and returning false
@param selectedJobsToRemove if this is non-zero, the JobSelector object is asked to decide which
jobs should be removed. If it is zero, all jobs are removed
@returns true if all jobs are successfully stopped and removed; false if the timeout period
expires while waiting for one or more jobs to stop
*/
bool removeAllJobs (bool interruptRunningJobs,
int timeOutMilliseconds,
JobSelector* selectedJobsToRemove = nullptr);
/** Returns the number of jobs currently running or queued.
*/
int getNumJobs() const;
/** Returns one of the jobs in the queue.
Note that this can be a very volatile list as jobs might be continuously getting shifted
around in the list, and this method may return 0 if the index is currently out-of-range.
*/
ThreadPoolJob* getJob (int index) const;
/** Returns true if the given job is currently queued or running.
@see isJobRunning()
*/
bool contains (const ThreadPoolJob* job) const;
/** Returns true if the given job is currently being run by a thread.
*/
bool isJobRunning (const ThreadPoolJob* job) const;
/** Waits until a job has finished running and has been removed from the pool.
This will wait until the job is no longer in the pool - i.e. until its
runJob() method returns ThreadPoolJob::jobHasFinished.
If the timeout period expires before the job finishes, this will return false;
it returns true if the job has finished successfully.
*/
bool waitForJobToFinish (const ThreadPoolJob* job,
int timeOutMilliseconds) const;
/** Returns a list of the names of all the jobs currently running or queued.
If onlyReturnActiveJobs is true, only the ones currently running are returned.
*/
StringArray getNamesOfAllJobs (bool onlyReturnActiveJobs) const;
/** Changes the priority of all the threads.
This will call Thread::setPriority() for each thread in the pool.
May return false if for some reason the priority can't be changed.
*/
bool setThreadPriorities (int newPriority);
private:
//==============================================================================
Array <ThreadPoolJob*> jobs;
class ThreadPoolThread;
friend class ThreadPoolThread;
friend class OwnedArray <ThreadPoolThread>;
OwnedArray <ThreadPoolThread> threads;
CriticalSection lock;
WaitableEvent jobFinishedSignal;
bool runNextJob();
ThreadPoolJob* pickNextJobToRun();
void addToDeleteList (OwnedArray<ThreadPoolJob>&, ThreadPoolJob*) const;
void createThreads (int numThreads);
void stopThreads();
// Note that this method has changed, and no longer has a parameter to indicate
// whether the jobs should be deleted - see the new method for details.
void removeAllJobs (bool, int, bool);
};
#endif // BEAST_THREADPOOL_H_INCLUDED

View File

@@ -1,166 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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.
*/
//==============================================================================
TimeSliceThread::TimeSliceThread (const String& name)
: Thread (name),
clientBeingCalled (nullptr)
{
}
TimeSliceThread::~TimeSliceThread()
{
stopThread (2000);
}
//==============================================================================
void TimeSliceThread::addTimeSliceClient (TimeSliceClient* const client, int millisecondsBeforeStarting)
{
if (client != nullptr)
{
const ScopedLock sl (listLock);
client->nextCallTime = Time::getCurrentTime() + RelativeTime::milliseconds (millisecondsBeforeStarting);
clients.addIfNotAlreadyThere (client);
notify();
}
}
void TimeSliceThread::removeTimeSliceClient (TimeSliceClient* const client)
{
const ScopedLock sl1 (listLock);
// if there's a chance we're in the middle of calling this client, we need to
// also lock the outer lock..
if (clientBeingCalled == client)
{
const ScopedUnlock ul (listLock); // unlock first to get the order right..
const ScopedLock sl2 (callbackLock);
const ScopedLock sl3 (listLock);
clients.removeFirstMatchingValue (client);
}
else
{
clients.removeFirstMatchingValue (client);
}
}
void TimeSliceThread::moveToFrontOfQueue (TimeSliceClient* client)
{
const ScopedLock sl (listLock);
if (clients.contains (client))
{
client->nextCallTime = Time::getCurrentTime();
notify();
}
}
int TimeSliceThread::getNumClients() const
{
return clients.size();
}
TimeSliceClient* TimeSliceThread::getClient (const int i) const
{
const ScopedLock sl (listLock);
return clients [i];
}
//==============================================================================
TimeSliceClient* TimeSliceThread::getNextClient (int index) const
{
Time soonest;
TimeSliceClient* client = nullptr;
for (int i = clients.size(); --i >= 0;)
{
TimeSliceClient* const c = clients.getUnchecked ((i + index) % clients.size());
if (client == nullptr || c->nextCallTime < soonest)
{
client = c;
soonest = c->nextCallTime;
}
}
return client;
}
void TimeSliceThread::run()
{
int index = 0;
while (! threadShouldExit())
{
int timeToWait = 500;
{
Time nextClientTime;
{
const ScopedLock sl2 (listLock);
index = clients.size() > 0 ? ((index + 1) % clients.size()) : 0;
if (TimeSliceClient* const firstClient = getNextClient (index))
nextClientTime = firstClient->nextCallTime;
}
const Time now (Time::getCurrentTime());
if (nextClientTime > now)
{
timeToWait = (int) bmin ((int64) 500, (nextClientTime - now).inMilliseconds());
}
else
{
timeToWait = index == 0 ? 1 : 0;
const ScopedLock sl (callbackLock);
{
const ScopedLock sl2 (listLock);
clientBeingCalled = getNextClient (index);
}
if (clientBeingCalled != nullptr)
{
const int msUntilNextCall = clientBeingCalled->useTimeSlice();
const ScopedLock sl2 (listLock);
if (msUntilNextCall >= 0)
clientBeingCalled->nextCallTime = now + RelativeTime::milliseconds (msUntilNextCall);
else
clients.removeFirstMatchingValue (clientBeingCalled);
clientBeingCalled = nullptr;
}
}
}
if (timeToWait > 0)
wait (timeToWait);
}
}

View File

@@ -1,143 +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_TIMESLICETHREAD_H_INCLUDED
#define BEAST_TIMESLICETHREAD_H_INCLUDED
class TimeSliceThread;
//==============================================================================
/**
Used by the TimeSliceThread class.
To register your class with a TimeSliceThread, derive from this class and
use the TimeSliceThread::addTimeSliceClient() method to add it to the list.
Make sure you always call TimeSliceThread::removeTimeSliceClient() before
deleting your client!
@see TimeSliceThread
*/
class BEAST_API TimeSliceClient
{
public:
/** Destructor. */
virtual ~TimeSliceClient() {}
/** Called back by a TimeSliceThread.
When you register this class with it, a TimeSliceThread will repeatedly call
this method.
The implementation of this method should use its time-slice to do something that's
quick - never block for longer than absolutely necessary.
@returns Your method should return the number of milliseconds which it would like to wait before being called
again. Returning 0 will make the thread call again as soon as possible (after possibly servicing
other busy clients). If you return a value below zero, your client will be removed from the list of clients,
and won't be called again. The value you specify isn't a guaranteee, and is only used as a hint by the
thread - the actual time before the next callback may be more or less than specified.
You can force the TimeSliceThread to wake up and poll again immediately by calling its notify() method.
*/
virtual int useTimeSlice() = 0;
private:
friend class TimeSliceThread;
Time nextCallTime;
};
//==============================================================================
/**
A thread that keeps a list of clients, and calls each one in turn, giving them
all a chance to run some sort of short task.
@see TimeSliceClient, Thread
*/
class BEAST_API TimeSliceThread
: public Thread
, LeakChecked <TimeSliceThread>
{
public:
//==============================================================================
/**
Creates a TimeSliceThread.
When first created, the thread is not running. Use the startThread()
method to start it.
*/
explicit TimeSliceThread (const String& threadName);
/** Destructor.
Deleting a Thread object that is running will only give the thread a
brief opportunity to stop itself cleanly, so it's recommended that you
should always call stopThread() with a decent timeout before deleting,
to avoid the thread being forcibly killed (which is a Bad Thing).
*/
~TimeSliceThread();
//==============================================================================
/** Adds a client to the list.
The client's callbacks will start after the number of milliseconds specified
by millisecondsBeforeStarting (and this may happen before this method has returned).
*/
void addTimeSliceClient (TimeSliceClient* client, int millisecondsBeforeStarting = 0);
/** Removes a client from the list.
This method will make sure that all callbacks to the client have completely
finished before the method returns.
*/
void removeTimeSliceClient (TimeSliceClient* client);
/** If the given client is waiting in the queue, it will be moved to the front
and given a time-slice as soon as possible.
If the specified client has not been added, nothing will happen.
*/
void moveToFrontOfQueue (TimeSliceClient* client);
/** Returns the number of registered clients. */
int getNumClients() const;
/** Returns one of the registered clients. */
TimeSliceClient* getClient (int index) const;
//==============================================================================
#ifndef DOXYGEN
void run() override;
#endif
//==============================================================================
private:
CriticalSection callbackLock, listLock;
Array <TimeSliceClient*> clients;
TimeSliceClient* clientBeingCalled;
TimeSliceClient* getNextClient (int index) const;
};
#endif // BEAST_TIMESLICETHREAD_H_INCLUDED