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 #elif defined(OS_MACOSX) 17 #include <mach/mach.h> 18 19 #include <list> 20 #include <memory> 21 22 #include "base/callback_forward.h" 23 #include "base/mac/scoped_mach_port.h" 24 #include "base/memory/ref_counted.h" 25 #include "base/synchronization/lock.h" 26 #elif defined(OS_POSIX) || defined(OS_FUCHSIA) 27 #include <list> 28 #include <utility> 29 30 #include "base/memory/ref_counted.h" 31 #include "base/synchronization/lock.h" 32 #endif 33 34 namespace base { 35 36 class TimeDelta; 37 class TimeTicks; 38 39 // A WaitableEvent can be a useful thread synchronization tool when you want to 40 // allow one thread to wait for another thread to finish some work. For 41 // non-Windows systems, this can only be used from within a single address 42 // space. 43 // 44 // Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to 45 // protect a simple boolean value. However, if you find yourself using a 46 // WaitableEvent in conjunction with a Lock to wait for a more complex state 47 // change (e.g., for an item to be added to a queue), then you should probably 48 // be using a ConditionVariable instead of a WaitableEvent. 49 // 50 // NOTE: On Windows, this class provides a subset of the functionality afforded 51 // by a Windows event object. This is intentional. If you are writing Windows 52 // specific code and you need other features of a Windows event, then you might 53 // be better off just using an Windows event directly. 54 class BASE_EXPORT WaitableEvent { 55 public: 56 // Indicates whether a WaitableEvent should automatically reset the event 57 // state after a single waiting thread has been released or remain signaled 58 // until Reset() is manually invoked. 59 enum class ResetPolicy { MANUAL, AUTOMATIC }; 60 61 // Indicates whether a new WaitableEvent should start in a signaled state or 62 // not. 63 enum class InitialState { SIGNALED, NOT_SIGNALED }; 64 65 // Constructs a WaitableEvent with policy and initial state as detailed in 66 // the above enums. 67 WaitableEvent(ResetPolicy reset_policy = ResetPolicy::MANUAL, 68 InitialState initial_state = InitialState::NOT_SIGNALED); 69 70 #if defined(OS_WIN) 71 // Create a WaitableEvent from an Event HANDLE which has already been 72 // created. This objects takes ownership of the HANDLE and will close it when 73 // deleted. 74 explicit WaitableEvent(win::ScopedHandle event_handle); 75 #endif 76 77 ~WaitableEvent(); 78 79 // Put the event in the un-signaled state. 80 void Reset(); 81 82 // Put the event in the signaled state. Causing any thread blocked on Wait 83 // to be woken up. 84 void Signal(); 85 86 // Returns true if the event is in the signaled state, else false. If this 87 // is not a manual reset event, then this test will cause a reset. 88 bool IsSignaled(); 89 90 // Wait indefinitely for the event to be signaled. Wait's return "happens 91 // after" |Signal| has completed. This means that it's safe for a 92 // WaitableEvent to synchronise its own destruction, like this: 93 // 94 // WaitableEvent *e = new WaitableEvent; 95 // SendToOtherThread(e); 96 // e->Wait(); 97 // delete e; 98 void Wait(); 99 100 // Wait up until wait_delta has passed for the event to be signaled. Returns 101 // true if the event was signaled. 102 // 103 // TimedWait can synchronise its own destruction like |Wait|. 104 bool TimedWait(const TimeDelta& wait_delta); 105 106 // Wait up until end_time deadline has passed for the event to be signaled. 107 // Return true if the event was signaled. 108 // 109 // TimedWaitUntil can synchronise its own destruction like |Wait|. 110 bool TimedWaitUntil(const TimeTicks& end_time); 111 112 #if defined(OS_WIN) handle()113 HANDLE handle() const { return handle_.Get(); } 114 #endif 115 116 // Wait, synchronously, on multiple events. 117 // waitables: an array of WaitableEvent pointers 118 // count: the number of elements in @waitables 119 // 120 // returns: the index of a WaitableEvent which has been signaled. 121 // 122 // You MUST NOT delete any of the WaitableEvent objects while this wait is 123 // happening, however WaitMany's return "happens after" the |Signal| call 124 // that caused it has completed, like |Wait|. 125 // 126 // If more than one WaitableEvent is signaled to unblock WaitMany, the lowest 127 // index among them is returned. 128 static size_t WaitMany(WaitableEvent** waitables, size_t count); 129 130 // For asynchronous waiting, see WaitableEventWatcher 131 132 // This is a private helper class. It's here because it's used by friends of 133 // this class (such as WaitableEventWatcher) to be able to enqueue elements 134 // of the wait-list 135 class Waiter { 136 public: 137 // Signal the waiter to wake up. 138 // 139 // Consider the case of a Waiter which is in multiple WaitableEvent's 140 // wait-lists. Each WaitableEvent is automatic-reset and two of them are 141 // signaled at the same time. Now, each will wake only the first waiter in 142 // the wake-list before resetting. However, if those two waiters happen to 143 // be the same object (as can happen if another thread didn't have a chance 144 // to dequeue the waiter from the other wait-list in time), two auto-resets 145 // will have happened, but only one waiter has been signaled! 146 // 147 // Because of this, a Waiter may "reject" a wake by returning false. In 148 // this case, the auto-reset WaitableEvent shouldn't act as if anything has 149 // been notified. 150 virtual bool Fire(WaitableEvent* signaling_event) = 0; 151 152 // Waiters may implement this in order to provide an extra condition for 153 // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the 154 // pointers match then this function is called as a final check. See the 155 // comments in ~Handle for why. 156 virtual bool Compare(void* tag) = 0; 157 158 protected: 159 virtual ~Waiter() = default; 160 }; 161 162 private: 163 friend class WaitableEventWatcher; 164 165 #if defined(OS_WIN) 166 win::ScopedHandle handle_; 167 #elif defined(OS_MACOSX) 168 // Prior to macOS 10.12, a TYPE_MACH_RECV dispatch source may not be invoked 169 // immediately. If a WaitableEventWatcher is used on a manual-reset event, 170 // and another thread that is Wait()ing on the event calls Reset() 171 // immediately after waking up, the watcher may not receive the callback. 172 // On macOS 10.12 and higher, dispatch delivery is reliable. But for OSes 173 // prior, a lock-protected list of callbacks is used for manual-reset event 174 // watchers. Automatic-reset events are not prone to this issue, since the 175 // first thread to wake will claim the event. 176 static bool UseSlowWatchList(ResetPolicy policy); 177 178 // Peeks the message queue named by |port| and returns true if a message 179 // is present and false if not. If |dequeue| is true, the messsage will be 180 // drained from the queue. If |dequeue| is false, the queue will only be 181 // peeked. |port| must be a receive right. 182 static bool PeekPort(mach_port_t port, bool dequeue); 183 184 // The Mach receive right is waited on by both WaitableEvent and 185 // WaitableEventWatcher. It is valid to signal and then delete an event, and 186 // a watcher should still be notified. If the right were to be destroyed 187 // immediately, the watcher would not receive the signal. Because Mach 188 // receive rights cannot have a user refcount greater than one, the right 189 // must be reference-counted manually. 190 class ReceiveRight : public RefCountedThreadSafe<ReceiveRight> { 191 public: 192 ReceiveRight(mach_port_t name, bool create_slow_watch_list); 193 Name()194 mach_port_t Name() const { return right_.get(); }; 195 196 // This structure is used iff UseSlowWatchList() is true. See the comment 197 // in Signal() for details. 198 struct WatchList { 199 WatchList(); 200 ~WatchList(); 201 202 // The lock protects a list of closures to be run when the event is 203 // Signal()ed. The closures are invoked on the signaling thread, so they 204 // must be safe to be called from any thread. 205 Lock lock; 206 std::list<OnceClosure> list; 207 }; 208 SlowWatchList()209 WatchList* SlowWatchList() const { return slow_watch_list_.get(); } 210 211 private: 212 friend class RefCountedThreadSafe<ReceiveRight>; 213 ~ReceiveRight(); 214 215 mac::ScopedMachReceiveRight right_; 216 217 // This is allocated iff UseSlowWatchList() is true. It is created on the 218 // heap to avoid performing initialization when not using the slow path. 219 std::unique_ptr<WatchList> slow_watch_list_; 220 221 DISALLOW_COPY_AND_ASSIGN(ReceiveRight); 222 }; 223 224 const ResetPolicy policy_; 225 226 // The receive right for the event. 227 scoped_refptr<ReceiveRight> receive_right_; 228 229 // The send right used to signal the event. This can be disposed of with 230 // the event, unlike the receive right, since a deleted event cannot be 231 // signaled. 232 mac::ScopedMachSendRight send_right_; 233 #elif defined(OS_POSIX) || defined(OS_FUCHSIA) 234 // On Windows, you must not close a HANDLE which is currently being waited on. 235 // The MSDN documentation says that the resulting behaviour is 'undefined'. 236 // To solve that issue each WaitableEventWatcher duplicates the given event 237 // handle. 238 239 // However, if we were to include the following members 240 // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an 241 // event which gets deleted. This mismatch has bitten us several times now, 242 // so we have a kernel of the WaitableEvent, which is reference counted. 243 // WaitableEventWatchers may then take a reference and thus match the Windows 244 // behaviour. 245 struct WaitableEventKernel : 246 public RefCountedThreadSafe<WaitableEventKernel> { 247 public: 248 WaitableEventKernel(ResetPolicy reset_policy, InitialState initial_state); 249 250 bool Dequeue(Waiter* waiter, void* tag); 251 252 base::Lock lock_; 253 const bool manual_reset_; 254 bool signaled_; 255 std::list<Waiter*> waiters_; 256 257 private: 258 friend class RefCountedThreadSafe<WaitableEventKernel>; 259 ~WaitableEventKernel(); 260 }; 261 262 typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex; 263 264 // When dealing with arrays of WaitableEvent*, we want to sort by the address 265 // of the WaitableEvent in order to have a globally consistent locking order. 266 // In that case we keep them, in sorted order, in an array of pairs where the 267 // second element is the index of the WaitableEvent in the original, 268 // unsorted, array. 269 static size_t EnqueueMany(WaiterAndIndex* waitables, 270 size_t count, Waiter* waiter); 271 272 bool SignalAll(); 273 bool SignalOne(); 274 void Enqueue(Waiter* waiter); 275 276 scoped_refptr<WaitableEventKernel> kernel_; 277 #endif 278 279 DISALLOW_COPY_AND_ASSIGN(WaitableEvent); 280 }; 281 282 } // namespace base 283 284 #endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ 285