diff options
Diffstat (limited to 'base/waitable_event.h')
-rw-r--r-- | base/waitable_event.h | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/base/waitable_event.h b/base/waitable_event.h index 73fc7ff5..d2b0999 100644 --- a/base/waitable_event.h +++ b/base/waitable_event.h @@ -16,6 +16,7 @@ #include <utility> #include "base/condition_variable.h" #include "base/lock.h" +#include "base/ref_counted.h" #endif #include "base/message_loop.h" @@ -60,8 +61,6 @@ class WaitableEvent { HANDLE Release(); #endif - // WARNING: Destroying a WaitableEvent while threads are waiting on it is not - // supported. Doing so will cause crashes or other instability. ~WaitableEvent(); // Put the event in the un-signaled state. @@ -93,6 +92,9 @@ class WaitableEvent { // count: the number of elements in @waitables // // returns: the index of a WaitableEvent which has been signaled. + // + // You MUST NOT delete any of the WaitableEvent objects while this wait is + // happening. static size_t WaitMany(WaitableEvent** waitables, size_t count); // For asynchronous waiting, see WaitableEventWatcher @@ -130,10 +132,35 @@ class WaitableEvent { #if defined(OS_WIN) HANDLE handle_; #else + // On Windows, one can close a HANDLE which is currently being waited on. The + // MSDN documentation says that the resulting behaviour is 'undefined', but + // it doesn't crash. However, if we were to include the following members + // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an + // event which gets deleted. This mismatch has bitten us several times now, + // so we have a kernel of the WaitableEvent, which is reference counted. + // WaitableEventWatchers may then take a reference and thus match the Windows + // behaviour. + struct WaitableEventKernel : + public RefCountedThreadSafe<WaitableEventKernel> { + public: + WaitableEventKernel(bool manual_reset, bool initially_signaled) + : manual_reset_(manual_reset), + signaled_(initially_signaled) { + } + + bool Dequeue(Waiter* waiter, void* tag); + + Lock lock_; + bool signaled_; + const bool manual_reset_; + std::list<Waiter*> waiters_; + }; + + scoped_refptr<WaitableEventKernel> kernel_; + bool SignalAll(); bool SignalOne(); void Enqueue(Waiter* waiter); - bool Dequeue(Waiter* waiter, void* tag); // When dealing with arrays of WaitableEvent*, we want to sort by the address // of the WaitableEvent in order to have a globally consistent locking order. @@ -143,11 +170,6 @@ class WaitableEvent { typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex; static size_t EnqueueMany(WaiterAndIndex* waitables, size_t count, Waiter* waiter); - - Lock lock_; - bool signaled_; - const bool manual_reset_; - std::list<Waiter*> waiters_; #endif DISALLOW_COPY_AND_ASSIGN(WaitableEvent); |