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 // Declares that this WaitableEvent will only ever be used by a thread that is 117 // idle at the bottom of its stack and waiting for work (in particular, it is 118 // not synchronously waiting on this event before resuming ongoing work). This 119 // is useful to avoid telling base-internals that this thread is "blocked" 120 // when it's merely idle and ready to do work. As such, this is only expected 121 // to be used by thread and thread pool impls. declare_only_used_while_idle()122 void declare_only_used_while_idle() { waiting_is_blocking_ = false; } 123 124 // Wait, synchronously, on multiple events. 125 // waitables: an array of WaitableEvent pointers 126 // count: the number of elements in @waitables 127 // 128 // returns: the index of a WaitableEvent which has been signaled. 129 // 130 // You MUST NOT delete any of the WaitableEvent objects while this wait is 131 // happening, however WaitMany's return "happens after" the |Signal| call 132 // that caused it has completed, like |Wait|. 133 // 134 // If more than one WaitableEvent is signaled to unblock WaitMany, the lowest 135 // index among them is returned. 136 static size_t WaitMany(WaitableEvent** waitables, size_t count); 137 138 // For asynchronous waiting, see WaitableEventWatcher 139 140 // This is a private helper class. It's here because it's used by friends of 141 // this class (such as WaitableEventWatcher) to be able to enqueue elements 142 // of the wait-list 143 class Waiter { 144 public: 145 // Signal the waiter to wake up. 146 // 147 // Consider the case of a Waiter which is in multiple WaitableEvent's 148 // wait-lists. Each WaitableEvent is automatic-reset and two of them are 149 // signaled at the same time. Now, each will wake only the first waiter in 150 // the wake-list before resetting. However, if those two waiters happen to 151 // be the same object (as can happen if another thread didn't have a chance 152 // to dequeue the waiter from the other wait-list in time), two auto-resets 153 // will have happened, but only one waiter has been signaled! 154 // 155 // Because of this, a Waiter may "reject" a wake by returning false. In 156 // this case, the auto-reset WaitableEvent shouldn't act as if anything has 157 // been notified. 158 virtual bool Fire(WaitableEvent* signaling_event) = 0; 159 160 // Waiters may implement this in order to provide an extra condition for 161 // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the 162 // pointers match then this function is called as a final check. See the 163 // comments in ~Handle for why. 164 virtual bool Compare(void* tag) = 0; 165 166 protected: 167 virtual ~Waiter() = default; 168 }; 169 170 private: 171 friend class WaitableEventWatcher; 172 173 #if defined(OS_WIN) 174 win::ScopedHandle handle_; 175 #elif defined(OS_MACOSX) 176 // Prior to macOS 10.12, a TYPE_MACH_RECV dispatch source may not be invoked 177 // immediately. If a WaitableEventWatcher is used on a manual-reset event, 178 // and another thread that is Wait()ing on the event calls Reset() 179 // immediately after waking up, the watcher may not receive the callback. 180 // On macOS 10.12 and higher, dispatch delivery is reliable. But for OSes 181 // prior, a lock-protected list of callbacks is used for manual-reset event 182 // watchers. Automatic-reset events are not prone to this issue, since the 183 // first thread to wake will claim the event. 184 static bool UseSlowWatchList(ResetPolicy policy); 185 186 // Peeks the message queue named by |port| and returns true if a message 187 // is present and false if not. If |dequeue| is true, the messsage will be 188 // drained from the queue. If |dequeue| is false, the queue will only be 189 // peeked. |port| must be a receive right. 190 static bool PeekPort(mach_port_t port, bool dequeue); 191 192 // The Mach receive right is waited on by both WaitableEvent and 193 // WaitableEventWatcher. It is valid to signal and then delete an event, and 194 // a watcher should still be notified. If the right were to be destroyed 195 // immediately, the watcher would not receive the signal. Because Mach 196 // receive rights cannot have a user refcount greater than one, the right 197 // must be reference-counted manually. 198 class ReceiveRight : public RefCountedThreadSafe<ReceiveRight> { 199 public: 200 ReceiveRight(mach_port_t name, bool create_slow_watch_list); 201 Name()202 mach_port_t Name() const { return right_.get(); } 203 204 // This structure is used iff UseSlowWatchList() is true. See the comment 205 // in Signal() for details. 206 struct WatchList { 207 WatchList(); 208 ~WatchList(); 209 210 // The lock protects a list of closures to be run when the event is 211 // Signal()ed. The closures are invoked on the signaling thread, so they 212 // must be safe to be called from any thread. 213 Lock lock; 214 std::list<OnceClosure> list; 215 }; 216 SlowWatchList()217 WatchList* SlowWatchList() const { return slow_watch_list_.get(); } 218 219 private: 220 friend class RefCountedThreadSafe<ReceiveRight>; 221 ~ReceiveRight(); 222 223 mac::ScopedMachReceiveRight right_; 224 225 // This is allocated iff UseSlowWatchList() is true. It is created on the 226 // heap to avoid performing initialization when not using the slow path. 227 std::unique_ptr<WatchList> slow_watch_list_; 228 229 DISALLOW_COPY_AND_ASSIGN(ReceiveRight); 230 }; 231 232 const ResetPolicy policy_; 233 234 // The receive right for the event. 235 scoped_refptr<ReceiveRight> receive_right_; 236 237 // The send right used to signal the event. This can be disposed of with 238 // the event, unlike the receive right, since a deleted event cannot be 239 // signaled. 240 mac::ScopedMachSendRight send_right_; 241 #elif defined(OS_POSIX) || defined(OS_FUCHSIA) 242 // On Windows, you must not close a HANDLE which is currently being waited on. 243 // The MSDN documentation says that the resulting behaviour is 'undefined'. 244 // To solve that issue each WaitableEventWatcher duplicates the given event 245 // handle. 246 247 // However, if we were to include the following members 248 // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an 249 // event which gets deleted. This mismatch has bitten us several times now, 250 // so we have a kernel of the WaitableEvent, which is reference counted. 251 // WaitableEventWatchers may then take a reference and thus match the Windows 252 // behaviour. 253 struct WaitableEventKernel : 254 public RefCountedThreadSafe<WaitableEventKernel> { 255 public: 256 WaitableEventKernel(ResetPolicy reset_policy, InitialState initial_state); 257 258 bool Dequeue(Waiter* waiter, void* tag); 259 260 base::Lock lock_; 261 const bool manual_reset_; 262 bool signaled_; 263 std::list<Waiter*> waiters_; 264 265 private: 266 friend class RefCountedThreadSafe<WaitableEventKernel>; 267 ~WaitableEventKernel(); 268 }; 269 270 typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex; 271 272 // When dealing with arrays of WaitableEvent*, we want to sort by the address 273 // of the WaitableEvent in order to have a globally consistent locking order. 274 // In that case we keep them, in sorted order, in an array of pairs where the 275 // second element is the index of the WaitableEvent in the original, 276 // unsorted, array. 277 static size_t EnqueueMany(WaiterAndIndex* waitables, 278 size_t count, Waiter* waiter); 279 280 bool SignalAll(); 281 bool SignalOne(); 282 void Enqueue(Waiter* waiter); 283 284 scoped_refptr<WaitableEventKernel> kernel_; 285 #endif 286 287 // Whether a thread invoking Wait() on this WaitableEvent should be considered 288 // blocked as opposed to idle (and potentially replaced if part of a pool). 289 bool waiting_is_blocking_ = true; 290 291 DISALLOW_COPY_AND_ASSIGN(WaitableEvent); 292 }; 293 294 } // namespace base 295 296 #endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ 297