From c864e4d3db2b0b1b1e3fe0aff29d6abdfb43785c Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Fri, 4 Oct 2013 11:12:16 -0700 Subject: [PATCH] Move WaitableEvent --- Builds/VisualStudio2012/beast.vcxproj | 8 +- Builds/VisualStudio2012/beast.vcxproj.filters | 9 +- beast/Thread.h | 1 + beast/chrono/CPUMeter.h | 4 +- beast/thread/Thread.cpp | 1 + .../threads => beast/thread}/WaitableEvent.h | 46 +++-- beast/thread/impl/WaitableEvent.cpp | 163 ++++++++++++++++++ modules/beast_core/beast_core.h | 1 - modules/beast_core/native/posix_SharedCode.h | 86 --------- modules/beast_core/native/win32_Threads.cpp | 15 -- 10 files changed, 209 insertions(+), 125 deletions(-) rename {modules/beast_core/threads => beast/thread}/WaitableEvent.h (83%) create mode 100644 beast/thread/impl/WaitableEvent.cpp diff --git a/Builds/VisualStudio2012/beast.vcxproj b/Builds/VisualStudio2012/beast.vcxproj index 657a854f91..38133a41f6 100644 --- a/Builds/VisualStudio2012/beast.vcxproj +++ b/Builds/VisualStudio2012/beast.vcxproj @@ -160,6 +160,7 @@ + @@ -333,7 +334,6 @@ - @@ -511,6 +511,12 @@ true true + + true + true + true + true + true diff --git a/Builds/VisualStudio2012/beast.vcxproj.filters b/Builds/VisualStudio2012/beast.vcxproj.filters index 6d8a46ed81..b5ca3dc0e5 100644 --- a/Builds/VisualStudio2012/beast.vcxproj.filters +++ b/Builds/VisualStudio2012/beast.vcxproj.filters @@ -512,9 +512,6 @@ beast_core\threads - - beast_core\threads - beast_core\time @@ -1239,6 +1236,9 @@ beast\chrono + + beast\thread + @@ -1787,6 +1787,9 @@ beast\chrono\impl + + beast\thread\impl + diff --git a/beast/Thread.h b/beast/Thread.h index bc3e9428a2..208caed58c 100644 --- a/beast/Thread.h +++ b/beast/Thread.h @@ -26,5 +26,6 @@ #include "thread/SharedLockGuard.h" #include "thread/SharedMutexAdapter.h" #include "thread/SharedData.h" +#include "thread/WaitableEvent.h" #endif diff --git a/beast/chrono/CPUMeter.h b/beast/chrono/CPUMeter.h index 8a02b591c2..4040e13822 100644 --- a/beast/chrono/CPUMeter.h +++ b/beast/chrono/CPUMeter.h @@ -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 (); } diff --git a/beast/thread/Thread.cpp b/beast/thread/Thread.cpp index 79ff63a23e..d44ea8210c 100644 --- a/beast/thread/Thread.cpp +++ b/beast/thread/Thread.cpp @@ -20,3 +20,4 @@ #include "BeastConfig.h" #include "impl/RecursiveMutex.cpp" +#include "impl/WaitableEvent.cpp" diff --git a/modules/beast_core/threads/WaitableEvent.h b/beast/thread/WaitableEvent.h similarity index 83% rename from modules/beast_core/threads/WaitableEvent.h rename to beast/thread/WaitableEvent.h index 8cbb68c840..e4f4191046 100644 --- a/modules/beast_core/threads/WaitableEvent.h +++ b/beast/thread/WaitableEvent.h @@ -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 +#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 , public Uncopyable +class WaitableEvent + : public Uncopyable + //, LeakChecked // 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 diff --git a/beast/thread/impl/WaitableEvent.cpp b/beast/thread/impl/WaitableEvent.cpp new file mode 100644 index 0000000000..0a976c783a --- /dev/null +++ b/beast/thread/impl/WaitableEvent.cpp @@ -0,0 +1,163 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + 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 + +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 diff --git a/modules/beast_core/beast_core.h b/modules/beast_core/beast_core.h index c43fdce66e..1ea063eb4e 100644 --- a/modules/beast_core/beast_core.h +++ b/modules/beast_core/beast_core.h @@ -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" diff --git a/modules/beast_core/native/posix_SharedCode.h b/modules/beast_core/native/posix_SharedCode.h index 6b9cb1672f..95e72f9c33 100644 --- a/modules/beast_core/native/posix_SharedCode.h +++ b/modules/beast_core/native/posix_SharedCode.h @@ -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) { diff --git a/modules/beast_core/native/win32_Threads.cpp b/modules/beast_core/native/win32_Threads.cpp index 3cbc3afee3..6c77427878 100644 --- a/modules/beast_core/native/win32_Threads.cpp +++ b/modules/beast_core/native/win32_Threads.cpp @@ -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*);