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