mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-04 11:15:56 +00:00
Move many Thread related classes
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
7
TODO.txt
7
TODO.txt
@@ -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
|
||||
|
||||
@@ -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
36
beast/Threads.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#include "RelativeTime.h"
|
||||
#include "ScopedTimeInterval.h"
|
||||
#include "../thread/SharedData.h"
|
||||
#include "../threads/SharedData.h"
|
||||
#include "../Atomic.h"
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
133
beast/threads/impl/Atomic.cpp
Normal file
133
beast/threads/impl/Atomic.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
}
|
||||
599
beast/threads/impl/Thread.cpp
Normal file
599
beast/threads/impl/Thread.cpp
Normal 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, ¶m) != 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, ¶m) == 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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "../LeakChecked.h"
|
||||
|
||||
namespace beast {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
@@ -124,3 +128,5 @@ void LeakCheckedBase::checkForLeaks ()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
}
|
||||
|
||||
@@ -170,8 +170,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** The type of a list of tests.
|
||||
*/
|
||||
/** The type of a list of tests. */
|
||||
typedef Array <UnitTest*, CriticalSection> TestList;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -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, ¶m) != 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, ¶m) == 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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
ReadWriteMutex::ReadWriteMutex () noexcept
|
||||
{
|
||||
}
|
||||
|
||||
ReadWriteMutex::~ReadWriteMutex () noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void ReadWriteMutex::enterRead () const noexcept
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// attempt the lock optimistically
|
||||
// THIS IS NOT CACHE-FRIENDLY!
|
||||
m_readers->addref ();
|
||||
|
||||
// is there a writer?
|
||||
// THIS IS NOT CACHE-FRIENDLY!
|
||||
if (m_writes->isSignaled ())
|
||||
{
|
||||
// a writer exists, give up the read lock
|
||||
m_readers->release ();
|
||||
|
||||
// block until the writer is done
|
||||
{
|
||||
CriticalSection::ScopedLockType lock (m_mutex);
|
||||
}
|
||||
|
||||
// now try the loop again
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReadWriteMutex::exitRead () const noexcept
|
||||
{
|
||||
m_readers->release ();
|
||||
}
|
||||
|
||||
void ReadWriteMutex::enterWrite () const noexcept
|
||||
{
|
||||
// Optimistically acquire the write lock.
|
||||
m_writes->addref ();
|
||||
|
||||
// Go for the mutex.
|
||||
// Another writer might block us here.
|
||||
m_mutex.enter ();
|
||||
|
||||
// Only one competing writer will get here,
|
||||
// but we don't know who, so we have to drain
|
||||
// readers no matter what. New readers will be
|
||||
// blocked by the mutex.
|
||||
//
|
||||
if (m_readers->isSignaled ())
|
||||
{
|
||||
SpinDelay delay;
|
||||
|
||||
do
|
||||
{
|
||||
delay.pause ();
|
||||
}
|
||||
while (m_readers->isSignaled ());
|
||||
}
|
||||
}
|
||||
|
||||
void ReadWriteMutex::exitWrite () const noexcept
|
||||
{
|
||||
// Releasing the mutex first and then decrementing the
|
||||
// writer count allows another waiting writer to atomically
|
||||
// acquire the lock, thus starving readers. This fulfills
|
||||
// the write-preferencing requirement.
|
||||
|
||||
m_mutex.exit ();
|
||||
|
||||
m_writes->release ();
|
||||
}
|
||||
@@ -1,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
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user