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