Move WaitableEvent

This commit is contained in:
Vinnie Falco
2013-10-04 11:12:16 -07:00
parent ff305e63b6
commit c864e4d3db
10 changed files with 209 additions and 125 deletions

View File

@@ -160,6 +160,7 @@
<ClInclude Include="..\..\beast\Chrono.h" />
<ClInclude Include="..\..\beast\thread\TryLockGuard.h" />
<ClInclude Include="..\..\beast\thread\UnlockGuard.h" />
<ClInclude Include="..\..\beast\thread\WaitableEvent.h" />
<ClInclude Include="..\..\beast\TypeTraits.h" />
<ClInclude Include="..\..\beast\type_traits\IntegralConstant.h" />
<ClInclude Include="..\..\beast\type_traits\IsIntegral.h" />
@@ -333,7 +334,6 @@
<ClInclude Include="..\..\modules\beast_core\threads\ThreadLocalValue.h" />
<ClInclude Include="..\..\modules\beast_core\threads\ThreadPool.h" />
<ClInclude Include="..\..\modules\beast_core\threads\TimeSliceThread.h" />
<ClInclude Include="..\..\modules\beast_core\threads\WaitableEvent.h" />
<ClInclude Include="..\..\modules\beast_core\thread\DeadlineTimer.h" />
<ClInclude Include="..\..\modules\beast_core\thread\Semaphore.h" />
<ClInclude Include="..\..\modules\beast_core\thread\ServiceQueue.h" />
@@ -511,6 +511,12 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\beast\thread\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\thread\Thread.cpp" />
<ClCompile Include="..\..\beast\utility\impl\Debug.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>

View File

@@ -512,9 +512,6 @@
<ClInclude Include="..\..\modules\beast_core\threads\TimeSliceThread.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\threads\WaitableEvent.h">
<Filter>beast_core\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\time\PerformanceCounter.h">
<Filter>beast_core\time</Filter>
</ClInclude>
@@ -1239,6 +1236,9 @@
<ClInclude Include="..\..\beast\chrono\CPUMeter.h">
<Filter>beast\chrono</Filter>
</ClInclude>
<ClInclude Include="..\..\beast\thread\WaitableEvent.h">
<Filter>beast\thread</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\modules\beast_core\containers\AbstractFifo.cpp">
@@ -1787,6 +1787,9 @@
<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>
</ItemGroup>
<ItemGroup>
<Text Include="..\..\TODO.txt">

View File

@@ -26,5 +26,6 @@
#include "thread/SharedLockGuard.h"
#include "thread/SharedMutexAdapter.h"
#include "thread/SharedData.h"
#include "thread/WaitableEvent.h"
#endif

View File

@@ -21,7 +21,7 @@
#define BEAST_CHRONO_CPUMETER_H_INCLUDED
#include "RelativeTime.h"
#include "SCopedTimeInterval.h"
#include "ScopedTimeInterval.h"
#include "../thread/SharedData.h"
#include "../Atomic.h"
@@ -120,7 +120,7 @@ private:
void advance ()
{
usage += history [index];
index = (++index) % numberOfAggregates;
index = (index+1) % numberOfAggregates;
usage -= history [index];
history [index].clear ();
}

View File

@@ -20,3 +20,4 @@
#include "BeastConfig.h"
#include "impl/RecursiveMutex.cpp"
#include "impl/WaitableEvent.cpp"

View File

@@ -24,15 +24,23 @@
#ifndef BEAST_WAITABLEEVENT_H_INCLUDED
#define BEAST_WAITABLEEVENT_H_INCLUDED
//==============================================================================
/**
Allows threads to wait for events triggered by other threads.
#include "../Config.h"
#include "../Uncopyable.h"
A thread can call wait() on a WaitableObject, and this will suspend the
#if ! BEAST_WINDOWS
#include <pthread.h>
#endif
namespace beast {
/** Allows threads to wait for events triggered by other threads.
A thread can call wait() on a WaitableEvent, and this will suspend the
calling thread until another thread wakes it up by calling the signal()
method.
*/
class BEAST_API WaitableEvent : LeakChecked <WaitableEvent>, public Uncopyable
class WaitableEvent
: public Uncopyable
//, LeakChecked <WaitableEvent> // VFALCO TODO Move LeakChecked to beast/
{
public:
//==============================================================================
@@ -45,14 +53,14 @@ public:
@param initiallySignaled If this is true then the event will be signaled when
the constructor returns.
*/
explicit WaitableEvent (bool manualReset = false, bool initiallySignaled = false) noexcept;
explicit WaitableEvent (bool manualReset = false, bool initiallySignaled = false);
/** Destructor.
If other threads are waiting on this object when it gets deleted, this
can cause nasty errors, so be careful!
*/
~WaitableEvent() noexcept;
~WaitableEvent();
//==============================================================================
/** Suspends the calling thread until the event has been signalled.
@@ -69,7 +77,11 @@ public:
@returns true if the object has been signalled, false if the timeout expires first.
@see signal, reset
*/
bool wait (int timeOutMilliseconds = -1) const noexcept;
/** @{ */
bool wait () const; // wait forever
// VFALCO TODO Change wait() to seconds instead of millis
bool wait (int timeOutMilliseconds) const; // DEPRECATED
/** @} */
//==============================================================================
/** Wakes up any threads that are currently waiting on this object.
@@ -87,26 +99,26 @@ public:
@see wait, reset
*/
void signal() const noexcept;
void signal() const;
//==============================================================================
/** Resets the event to an unsignalled state.
If it's not already signalled, this does nothing.
*/
void reset() const noexcept;
void reset() const;
private:
//==============================================================================
#if BEAST_WINDOWS
#if BEAST_WINDOWS
void* handle;
#else
#else
mutable pthread_cond_t condition;
mutable pthread_mutex_t mutex;
mutable bool triggered, manualReset;
#endif
mutable bool triggered;
mutable bool manualReset;
#endif
};
}
#endif // BEAST_WAITABLEEVENT_H_INCLUDED
#endif

View File

@@ -0,0 +1,163 @@
//------------------------------------------------------------------------------
/*
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 "../WaitableEvent.h"
#if BEAST_WINDOWS
#include <Windows.h>
namespace beast {
WaitableEvent::WaitableEvent (const bool manualReset, bool initiallySignaled)
: handle (CreateEvent (0, manualReset ? TRUE : FALSE, initiallySignaled ? TRUE : FALSE, 0))
{
}
WaitableEvent::~WaitableEvent()
{
CloseHandle (handle);
}
void WaitableEvent::signal() const
{
SetEvent (handle);
}
void WaitableEvent::reset() const
{
ResetEvent (handle);
}
bool WaitableEvent::wait () const
{
return WaitForSingleObject (handle, INFINITE) == WAIT_OBJECT_0;
}
bool WaitableEvent::wait (const int timeOutMs) const
{
if (timeOutMs >= 0)
return WaitForSingleObject (handle,
(DWORD) timeOutMs) == WAIT_OBJECT_0;
return wait ();
}
}
#else
namespace beast {
WaitableEvent::WaitableEvent (const bool useManualReset, bool initiallySignaled)
: triggered (false), manualReset (useManualReset)
{
pthread_cond_init (&condition, 0);
pthread_mutexattr_t atts;
pthread_mutexattr_init (&atts);
#if ! BEAST_ANDROID
pthread_mutexattr_setprotocol (&atts, PTHREAD_PRIO_INHERIT);
#endif
pthread_mutex_init (&mutex, &atts);
if (initiallySignaled)
signal ();
}
WaitableEvent::~WaitableEvent()
{
pthread_cond_destroy (&condition);
pthread_mutex_destroy (&mutex);
}
bool WaitableEvent::wait () const
{
return wait (-1);
}
bool WaitableEvent::wait (const int timeOutMillisecs) const
{
pthread_mutex_lock (&mutex);
if (! triggered)
{
if (timeOutMillisecs < 0)
{
do
{
pthread_cond_wait (&condition, &mutex);
}
while (! triggered);
}
else
{
struct timeval now;
gettimeofday (&now, 0);
struct timespec time;
time.tv_sec = now.tv_sec + (timeOutMillisecs / 1000);
time.tv_nsec = (now.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000;
if (time.tv_nsec >= 1000000000)
{
time.tv_nsec -= 1000000000;
time.tv_sec++;
}
do
{
if (pthread_cond_timedwait (&condition, &mutex, &time) == ETIMEDOUT)
{
pthread_mutex_unlock (&mutex);
return false;
}
}
while (! triggered);
}
}
if (! manualReset)
triggered = false;
pthread_mutex_unlock (&mutex);
return true;
}
void WaitableEvent::signal() const
{
pthread_mutex_lock (&mutex);
triggered = true;
pthread_cond_broadcast (&condition);
pthread_mutex_unlock (&mutex);
}
void WaitableEvent::reset() const
{
pthread_mutex_lock (&mutex);
triggered = false;
pthread_mutex_unlock (&mutex);
}
}
#endif

View File

@@ -148,7 +148,6 @@ class FileOutputStream;
#include "memory/MemoryAlignment.h"
#include "memory/CacheLine.h"
#include "threads/ReadWriteMutex.h"
#include "threads/WaitableEvent.h"
#include "threads/Thread.h"
#include "threads/SpinLock.h"
#include "threads/ThreadLocalValue.h"

View File

@@ -38,92 +38,6 @@ void CriticalSection::enter() const noexcept { pthread_mutex_lock (&mutex); }
bool CriticalSection::tryEnter() const noexcept { return pthread_mutex_trylock (&mutex) == 0; }
void CriticalSection::exit() const noexcept { pthread_mutex_unlock (&mutex); }
//==============================================================================
WaitableEvent::WaitableEvent (const bool useManualReset, bool initiallySignaled) noexcept
: triggered (false), manualReset (useManualReset)
{
pthread_cond_init (&condition, 0);
pthread_mutexattr_t atts;
pthread_mutexattr_init (&atts);
#if ! BEAST_ANDROID
pthread_mutexattr_setprotocol (&atts, PTHREAD_PRIO_INHERIT);
#endif
pthread_mutex_init (&mutex, &atts);
if (initiallySignaled)
signal ();
}
WaitableEvent::~WaitableEvent() noexcept
{
pthread_cond_destroy (&condition);
pthread_mutex_destroy (&mutex);
}
bool WaitableEvent::wait (const int timeOutMillisecs) const noexcept
{
pthread_mutex_lock (&mutex);
if (! triggered)
{
if (timeOutMillisecs < 0)
{
do
{
pthread_cond_wait (&condition, &mutex);
}
while (! triggered);
}
else
{
struct timeval now;
gettimeofday (&now, 0);
struct timespec time;
time.tv_sec = now.tv_sec + (timeOutMillisecs / 1000);
time.tv_nsec = (now.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000;
if (time.tv_nsec >= 1000000000)
{
time.tv_nsec -= 1000000000;
time.tv_sec++;
}
do
{
if (pthread_cond_timedwait (&condition, &mutex, &time) == ETIMEDOUT)
{
pthread_mutex_unlock (&mutex);
return false;
}
}
while (! triggered);
}
}
if (! manualReset)
triggered = false;
pthread_mutex_unlock (&mutex);
return true;
}
void WaitableEvent::signal() const noexcept
{
pthread_mutex_lock (&mutex);
triggered = true;
pthread_cond_broadcast (&condition);
pthread_mutex_unlock (&mutex);
}
void WaitableEvent::reset() const noexcept
{
pthread_mutex_lock (&mutex);
triggered = false;
pthread_mutex_unlock (&mutex);
}
//==============================================================================
void BEAST_CALLTYPE Thread::sleep (int millisecs)
{

View File

@@ -72,21 +72,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); }
//==============================================================================
WaitableEvent::WaitableEvent (const bool manualReset, bool initiallySignaled) noexcept
: handle (CreateEvent (0, manualReset ? TRUE : FALSE, initiallySignaled ? TRUE : FALSE, 0)) {}
WaitableEvent::~WaitableEvent() noexcept { CloseHandle (handle); }
void WaitableEvent::signal() const noexcept { SetEvent (handle); }
void WaitableEvent::reset() const noexcept { ResetEvent (handle); }
bool WaitableEvent::wait (const int timeOutMs) const noexcept
{
return WaitForSingleObject (handle, (DWORD) timeOutMs) == WAIT_OBJECT_0;
}
//==============================================================================
void BEAST_API beast_threadEntryPoint (void*);