1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#ifndef BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ 7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 80d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include <stddef.h> 90d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/base_export.h" 110d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/macros.h" 120d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "build/build_config.h" 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_WIN) 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/win/scoped_handle.h" 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_POSIX) 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <list> 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <utility> 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/memory/ref_counted.h" 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/synchronization/lock.h" 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass TimeDelta; 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// A WaitableEvent can be a useful thread synchronization tool when you want to 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// allow one thread to wait for another thread to finish some work. For 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// non-Windows systems, this can only be used from within a single address 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// space. 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// protect a simple boolean value. However, if you find yourself using a 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// WaitableEvent in conjunction with a Lock to wait for a more complex state 37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// change (e.g., for an item to be added to a queue), then you should probably 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// be using a ConditionVariable instead of a WaitableEvent. 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// NOTE: On Windows, this class provides a subset of the functionality afforded 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// by a Windows event object. This is intentional. If you are writing Windows 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// specific code and you need other features of a Windows event, then you might 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// be better off just using an Windows event directly. 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass BASE_EXPORT WaitableEvent { 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 460c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // Indicates whether a WaitableEvent should automatically reset the event 470c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // state after a single waiting thread has been released or remain signaled 480c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // until Reset() is manually invoked. 490c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez enum class ResetPolicy { MANUAL, AUTOMATIC }; 500c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 510c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // Indicates whether a new WaitableEvent should start in a signaled state or 520c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // not. 530c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez enum class InitialState { SIGNALED, NOT_SIGNALED }; 540c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 550c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // Constructs a WaitableEvent with policy and initial state as detailed in 560c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // the above enums. 570c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent(ResetPolicy reset_policy, InitialState initial_state); 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_WIN) 60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Create a WaitableEvent from an Event HANDLE which has already been 61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // created. This objects takes ownership of the HANDLE and will close it when 62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // deleted. 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat explicit WaitableEvent(win::ScopedHandle event_handle); 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ~WaitableEvent(); 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Put the event in the un-signaled state. 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void Reset(); 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Put the event in the signaled state. Causing any thread blocked on Wait 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // to be woken up. 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void Signal(); 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Returns true if the event is in the signaled state, else false. If this 76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // is not a manual reset event, then this test will cause a reset. 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool IsSignaled(); 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Wait indefinitely for the event to be signaled. Wait's return "happens 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // after" |Signal| has completed. This means that it's safe for a 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // WaitableEvent to synchronise its own destruction, like this: 82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // WaitableEvent *e = new WaitableEvent; 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // SendToOtherThread(e); 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // e->Wait(); 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // delete e; 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void Wait(); 88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Wait up until max_time has passed for the event to be signaled. Returns 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // true if the event was signaled. If this method returns false, then it 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // does not necessarily mean that max_time was exceeded. 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // TimedWait can synchronise its own destruction like |Wait|. 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool TimedWait(const TimeDelta& max_time); 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_WIN) 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat HANDLE handle() const { return handle_.Get(); } 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Wait, synchronously, on multiple events. 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // waitables: an array of WaitableEvent pointers 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // count: the number of elements in @waitables 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // returns: the index of a WaitableEvent which has been signaled. 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // You MUST NOT delete any of the WaitableEvent objects while this wait is 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // happening, however WaitMany's return "happens after" the |Signal| call 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // that caused it has completed, like |Wait|. 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static size_t WaitMany(WaitableEvent** waitables, size_t count); 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // For asynchronous waiting, see WaitableEventWatcher 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // This is a private helper class. It's here because it's used by friends of 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // this class (such as WaitableEventWatcher) to be able to enqueue elements 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // of the wait-list 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat class Waiter { 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Signal the waiter to wake up. 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Consider the case of a Waiter which is in multiple WaitableEvent's 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // wait-lists. Each WaitableEvent is automatic-reset and two of them are 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // signaled at the same time. Now, each will wake only the first waiter in 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // the wake-list before resetting. However, if those two waiters happen to 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // be the same object (as can happen if another thread didn't have a chance 125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // to dequeue the waiter from the other wait-list in time), two auto-resets 126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // will have happened, but only one waiter has been signaled! 127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Because of this, a Waiter may "reject" a wake by returning false. In 129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // this case, the auto-reset WaitableEvent shouldn't act as if anything has 130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // been notified. 131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual bool Fire(WaitableEvent* signaling_event) = 0; 132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Waiters may implement this in order to provide an extra condition for 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // pointers match then this function is called as a final check. See the 136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // comments in ~Handle for why. 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual bool Compare(void* tag) = 0; 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat protected: 140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual ~Waiter() {} 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat }; 142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat friend class WaitableEventWatcher; 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_WIN) 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat win::ScopedHandle handle_; 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else 149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // On Windows, one can close a HANDLE which is currently being waited on. The 150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // MSDN documentation says that the resulting behaviour is 'undefined', but 151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // it doesn't crash. However, if we were to include the following members 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // event which gets deleted. This mismatch has bitten us several times now, 154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // so we have a kernel of the WaitableEvent, which is reference counted. 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // WaitableEventWatchers may then take a reference and thus match the Windows 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // behaviour. 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat struct WaitableEventKernel : 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public RefCountedThreadSafe<WaitableEventKernel> { 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 1600c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEventKernel(ResetPolicy reset_policy, InitialState initial_state); 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool Dequeue(Waiter* waiter, void* tag); 163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::Lock lock_; 165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const bool manual_reset_; 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool signaled_; 167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::list<Waiter*> waiters_; 168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat friend class RefCountedThreadSafe<WaitableEventKernel>; 171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ~WaitableEventKernel(); 172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat }; 173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex; 175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // When dealing with arrays of WaitableEvent*, we want to sort by the address 177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // of the WaitableEvent in order to have a globally consistent locking order. 178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // In that case we keep them, in sorted order, in an array of pairs where the 179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // second element is the index of the WaitableEvent in the original, 180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // unsorted, array. 181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static size_t EnqueueMany(WaiterAndIndex* waitables, 182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t count, Waiter* waiter); 183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool SignalAll(); 185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool SignalOne(); 186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void Enqueue(Waiter* waiter); 187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat scoped_refptr<WaitableEventKernel> kernel_; 189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 191b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DISALLOW_COPY_AND_ASSIGN(WaitableEvent); 192b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 193b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ 197