1 // Copyright 2012 The Chromium Authors 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/compiler_specific.h" 12 #include "build/build_config.h" 13 14 #if BUILDFLAG(IS_WIN) 15 #include "base/win/scoped_handle.h" 16 #elif BUILDFLAG(IS_APPLE) 17 #include <mach/mach.h> 18 19 #include <list> 20 #include <memory> 21 22 #include "base/functional/callback_forward.h" 23 #include "base/mac/scoped_mach_port.h" 24 #include "base/memory/ref_counted.h" 25 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 26 #include <list> 27 #include <utility> 28 29 #include "base/memory/ref_counted.h" 30 #include "base/synchronization/lock.h" 31 #endif 32 33 namespace base { 34 35 class TimeDelta; 36 37 // A WaitableEvent can be a useful thread synchronization tool when you want to 38 // allow one thread to wait for another thread to finish some work. For 39 // non-Windows systems, this can only be used from within a single address 40 // space. 41 // 42 // Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to 43 // protect a simple boolean value. However, if you find yourself using a 44 // WaitableEvent in conjunction with a Lock to wait for a more complex state 45 // change (e.g., for an item to be added to a queue), then you should probably 46 // be using a ConditionVariable instead of a WaitableEvent. 47 // 48 // NOTE: On Windows, this class provides a subset of the functionality afforded 49 // by a Windows event object. This is intentional. If you are writing Windows 50 // specific code and you need other features of a Windows event, then you might 51 // be better off just using an Windows event directly. 52 class BASE_EXPORT WaitableEvent { 53 public: 54 // Indicates whether a WaitableEvent should automatically reset the event 55 // state after a single waiting thread has been released or remain signaled 56 // until Reset() is manually invoked. 57 enum class ResetPolicy { MANUAL, AUTOMATIC }; 58 59 // Indicates whether a new WaitableEvent should start in a signaled state or 60 // not. 61 enum class InitialState { SIGNALED, NOT_SIGNALED }; 62 63 // Constructs a WaitableEvent with policy and initial state as detailed in 64 // the above enums. 65 WaitableEvent(ResetPolicy reset_policy = ResetPolicy::MANUAL, 66 InitialState initial_state = InitialState::NOT_SIGNALED); 67 68 #if BUILDFLAG(IS_WIN) 69 // Create a WaitableEvent from an Event HANDLE which has already been 70 // created. This objects takes ownership of the HANDLE and will close it when 71 // deleted. 72 explicit WaitableEvent(win::ScopedHandle event_handle); 73 #endif 74 75 WaitableEvent(const WaitableEvent&) = delete; 76 WaitableEvent& operator=(const WaitableEvent&) = delete; 77 78 ~WaitableEvent(); 79 80 // Put the event in the un-signaled state. 81 void Reset(); 82 83 // Put the event in the signaled state. Causing any thread blocked on Wait 84 // to be woken up. 85 void Signal(); 86 87 // Returns true if the event is in the signaled state, else false. If this 88 // is not a manual reset event, then this test will cause a reset. 89 bool IsSignaled(); 90 91 // Wait indefinitely for the event to be signaled. Wait's return "happens 92 // after" |Signal| has completed. This means that it's safe for a 93 // WaitableEvent to synchronise its own destruction, like this: 94 // 95 // WaitableEvent *e = new WaitableEvent; 96 // SendToOtherThread(e); 97 // e->Wait(); 98 // delete e; 99 NOT_TAIL_CALLED void Wait(); 100 101 // Wait up until wait_delta has passed for the event to be signaled 102 // (real-time; ignores time overrides). Returns true if the event was 103 // signaled. Handles spurious wakeups and guarantees that |wait_delta| will 104 // have elapsed if this returns false. 105 // 106 // TimedWait can synchronise its own destruction like |Wait|. 107 NOT_TAIL_CALLED bool TimedWait(TimeDelta wait_delta); 108 109 #if BUILDFLAG(IS_WIN) handle()110 HANDLE handle() const { return handle_.get(); } 111 #endif 112 113 // Declares that this WaitableEvent will only ever be used by a thread that is 114 // idle at the bottom of its stack and waiting for work (in particular, it is 115 // not synchronously waiting on this event before resuming ongoing work). This 116 // is useful to avoid telling base-internals that this thread is "blocked" 117 // when it's merely idle and ready to do work. As such, this is only expected 118 // to be used by thread and thread pool impls. In such cases wakeup.flow 119 // events aren't emitted on |Signal|/|Wait|, because threading implementations 120 // are responsible for emitting the cause of their wakeup from idle. declare_only_used_while_idle()121 void declare_only_used_while_idle() { only_used_while_idle_ = true; } 122 123 // Wait, synchronously, on multiple events. 124 // waitables: an array of WaitableEvent pointers 125 // count: the number of elements in @waitables 126 // 127 // returns: the index of a WaitableEvent which has been signaled. 128 // 129 // You MUST NOT delete any of the WaitableEvent objects while this wait is 130 // happening, however WaitMany's return "happens after" the |Signal| call 131 // that caused it has completed, like |Wait|. 132 // 133 // If more than one WaitableEvent is signaled to unblock WaitMany, the lowest 134 // index among them is returned. 135 NOT_TAIL_CALLED static size_t WaitMany(WaitableEvent** waitables, 136 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 // The platform specific portions of Signal and TimedWait (which do the actual 174 // signaling and waiting). 175 void SignalImpl(); 176 bool TimedWaitImpl(TimeDelta wait_delta); 177 178 #if BUILDFLAG(IS_WIN) 179 win::ScopedHandle handle_; 180 #elif BUILDFLAG(IS_APPLE) 181 // Peeks the message queue named by |port| and returns true if a message 182 // is present and false if not. If |dequeue| is true, the messsage will be 183 // drained from the queue. If |dequeue| is false, the queue will only be 184 // peeked. |port| must be a receive right. 185 static bool PeekPort(mach_port_t port, bool dequeue); 186 187 // The Mach receive right is waited on by both WaitableEvent and 188 // WaitableEventWatcher. It is valid to signal and then delete an event, and 189 // a watcher should still be notified. If the right were to be destroyed 190 // immediately, the watcher would not receive the signal. Because Mach 191 // receive rights cannot have a user refcount greater than one, the right 192 // must be reference-counted manually. 193 class ReceiveRight : public RefCountedThreadSafe<ReceiveRight> { 194 public: 195 explicit ReceiveRight(mach_port_t name); 196 197 ReceiveRight(const ReceiveRight&) = delete; 198 ReceiveRight& operator=(const ReceiveRight&) = delete; 199 Name()200 mach_port_t Name() const { return right_.get(); } 201 202 private: 203 friend class RefCountedThreadSafe<ReceiveRight>; 204 ~ReceiveRight(); 205 206 mac::ScopedMachReceiveRight right_; 207 }; 208 209 const ResetPolicy policy_; 210 211 // The receive right for the event. 212 scoped_refptr<ReceiveRight> receive_right_; 213 214 // The send right used to signal the event. This can be disposed of with 215 // the event, unlike the receive right, since a deleted event cannot be 216 // signaled. 217 mac::ScopedMachSendRight send_right_; 218 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 219 // On Windows, you must not close a HANDLE which is currently being waited on. 220 // The MSDN documentation says that the resulting behaviour is 'undefined'. 221 // To solve that issue each WaitableEventWatcher duplicates the given event 222 // handle. 223 224 // However, if we were to include the following members 225 // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an 226 // event which gets deleted. This mismatch has bitten us several times now, 227 // so we have a kernel of the WaitableEvent, which is reference counted. 228 // WaitableEventWatchers may then take a reference and thus match the Windows 229 // behaviour. 230 struct WaitableEventKernel : 231 public RefCountedThreadSafe<WaitableEventKernel> { 232 public: 233 WaitableEventKernel(ResetPolicy reset_policy, InitialState initial_state); 234 235 bool Dequeue(Waiter* waiter, void* tag); 236 237 base::Lock lock_; 238 const bool manual_reset_; 239 bool signaled_; 240 std::list<Waiter*> waiters_; 241 242 private: 243 friend class RefCountedThreadSafe<WaitableEventKernel>; 244 ~WaitableEventKernel(); 245 }; 246 247 typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex; 248 249 // When dealing with arrays of WaitableEvent*, we want to sort by the address 250 // of the WaitableEvent in order to have a globally consistent locking order. 251 // In that case we keep them, in sorted order, in an array of pairs where the 252 // second element is the index of the WaitableEvent in the original, 253 // unsorted, array. 254 static size_t EnqueueMany(WaiterAndIndex* waitables, 255 size_t count, Waiter* waiter); 256 257 bool SignalAll(); 258 bool SignalOne(); 259 void Enqueue(Waiter* waiter); 260 261 scoped_refptr<WaitableEventKernel> kernel_; 262 #endif 263 264 // Whether a thread invoking Wait() on this WaitableEvent should be considered 265 // blocked as opposed to idle (and potentially replaced if part of a pool), 266 // and whether WaitableEvent should emit a wakeup.flow event on Signal => 267 // TimedWait. 268 bool only_used_while_idle_ = false; 269 }; 270 271 } // namespace base 272 273 #endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ 274