blob: 08da7e949e39e4eb1e1397e654a1e5023545bb6c [file] [log] [blame]
[email protected]f2ebbf062012-04-06 03:14:301// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]b2e97292008-09-02 18:20:342// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]44f9c952011-01-02 06:05:395#ifndef BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_
6#define BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_
[email protected]b2e97292008-09-02 18:20:347
avi9b6f42932015-12-26 22:15:148#include <stddef.h>
9
[email protected]0bea7252011-08-05 15:34:0010#include "base/base_export.h"
Gabriel Charette0a68eb9d2021-02-11 17:40:0511#include "base/compiler_specific.h"
avi9b6f42932015-12-26 22:15:1412#include "base/macros.h"
13#include "build/build_config.h"
[email protected]b2e97292008-09-02 18:20:3414
15#if defined(OS_WIN)
rvargas59d5d592014-09-23 21:39:3116#include "base/win/scoped_handle.h"
Avi Drissman5b286372020-07-28 21:59:3817#elif defined(OS_APPLE)
Robert Sesekd54c0c1e2017-08-03 22:18:2818#include <mach/mach.h>
Michael Nordman20b379b2017-07-21 18:08:0919
Robert Sesekd54c0c1e2017-08-03 22:18:2820#include <list>
21#include <memory>
22
23#include "base/callback_forward.h"
24#include "base/mac/scoped_mach_port.h"
25#include "base/memory/ref_counted.h"
26#include "base/synchronization/lock.h"
Fabrice de Gans-Riberi306871de2018-05-16 19:38:3927#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
[email protected]1c4947f2009-01-15 22:25:1128#include <list>
29#include <utility>
Robert Sesekd54c0c1e2017-08-03 22:18:2830
[email protected]3b63f8f42011-03-28 01:54:1531#include "base/memory/ref_counted.h"
[email protected]20305ec2011-01-21 04:55:5232#include "base/synchronization/lock.h"
[email protected]b2e97292008-09-02 18:20:3433#endif
34
[email protected]b2e97292008-09-02 18:20:3435namespace base {
36
[email protected]e1acf6f2008-10-27 20:43:3337class TimeDelta;
38
[email protected]b2e97292008-09-02 18:20:3439// A WaitableEvent can be a useful thread synchronization tool when you want to
[email protected]1c4947f2009-01-15 22:25:1140// 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.
[email protected]b2e97292008-09-02 18:20:3443//
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.
[email protected]0bea7252011-08-05 15:34:0054class BASE_EXPORT WaitableEvent {
[email protected]b2e97292008-09-02 18:20:3455 public:
gabe5ff4d62016-06-01 00:16:5056 // 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.
Gabriel Charettec9ba7a92018-05-10 21:10:5967 WaitableEvent(ResetPolicy reset_policy = ResetPolicy::MANUAL,
68 InitialState initial_state = InitialState::NOT_SIGNALED);
gabe5ff4d62016-06-01 00:16:5069
[email protected]1c4947f2009-01-15 22:25:1170#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.
rvargas94ed6c4e2014-11-25 01:23:3174 explicit WaitableEvent(win::ScopedHandle event_handle);
[email protected]1c4947f2009-01-15 22:25:1175#endif
76
[email protected]b2e97292008-09-02 18:20:3477 ~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
[email protected]e70af3a2014-08-07 08:09:1190 // 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;
Gabriel Charette0a68eb9d2021-02-11 17:40:0598 void NOT_TAIL_CALLED Wait();
[email protected]b2e97292008-09-02 18:20:3499
Gabriel Charetteef6cbc22019-08-02 06:24:59100 // Wait up until wait_delta has passed for the event to be signaled
101 // (real-time; ignores time overrides). Returns true if the event was
102 // signaled. Handles spurious wakeups and guarantees that |wait_delta| will
103 // have elapsed if this returns false.
[email protected]e70af3a2014-08-07 08:09:11104 //
105 // TimedWait can synchronise its own destruction like |Wait|.
Gabriel Charette0a68eb9d2021-02-11 17:40:05106 bool NOT_TAIL_CALLED TimedWait(const TimeDelta& wait_delta);
staniscacf68012016-11-30 19:56:09107
[email protected]b2e97292008-09-02 18:20:34108#if defined(OS_WIN)
rvargas59d5d592014-09-23 21:39:31109 HANDLE handle() const { return handle_.Get(); }
[email protected]1c4947f2009-01-15 22:25:11110#endif
111
Gabriel Charette5db1ab82018-11-07 05:14:06112 // Declares that this WaitableEvent will only ever be used by a thread that is
113 // idle at the bottom of its stack and waiting for work (in particular, it is
114 // not synchronously waiting on this event before resuming ongoing work). This
115 // is useful to avoid telling base-internals that this thread is "blocked"
116 // when it's merely idle and ready to do work. As such, this is only expected
117 // to be used by thread and thread pool impls.
118 void declare_only_used_while_idle() { waiting_is_blocking_ = false; }
119
[email protected]1c4947f2009-01-15 22:25:11120 // Wait, synchronously, on multiple events.
121 // waitables: an array of WaitableEvent pointers
122 // count: the number of elements in @waitables
123 //
124 // returns: the index of a WaitableEvent which has been signaled.
[email protected]c891ab92009-03-26 18:28:19125 //
126 // You MUST NOT delete any of the WaitableEvent objects while this wait is
[email protected]e70af3a2014-08-07 08:09:11127 // happening, however WaitMany's return "happens after" the |Signal| call
128 // that caused it has completed, like |Wait|.
rockot6622a122017-03-22 19:38:03129 //
130 // If more than one WaitableEvent is signaled to unblock WaitMany, the lowest
131 // index among them is returned.
Gabriel Charette0a68eb9d2021-02-11 17:40:05132 static size_t NOT_TAIL_CALLED WaitMany(WaitableEvent** waitables,
133 size_t count);
[email protected]1c4947f2009-01-15 22:25:11134
135 // For asynchronous waiting, see WaitableEventWatcher
136
137 // This is a private helper class. It's here because it's used by friends of
138 // this class (such as WaitableEventWatcher) to be able to enqueue elements
139 // of the wait-list
140 class Waiter {
141 public:
142 // Signal the waiter to wake up.
143 //
144 // Consider the case of a Waiter which is in multiple WaitableEvent's
145 // wait-lists. Each WaitableEvent is automatic-reset and two of them are
146 // signaled at the same time. Now, each will wake only the first waiter in
147 // the wake-list before resetting. However, if those two waiters happen to
148 // be the same object (as can happen if another thread didn't have a chance
149 // to dequeue the waiter from the other wait-list in time), two auto-resets
150 // will have happened, but only one waiter has been signaled!
151 //
152 // Because of this, a Waiter may "reject" a wake by returning false. In
153 // this case, the auto-reset WaitableEvent shouldn't act as if anything has
154 // been notified.
155 virtual bool Fire(WaitableEvent* signaling_event) = 0;
156
157 // Waiters may implement this in order to provide an extra condition for
158 // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the
159 // pointers match then this function is called as a final check. See the
160 // comments in ~Handle for why.
161 virtual bool Compare(void* tag) = 0;
[email protected]20cb5f482009-12-16 01:01:25162
163 protected:
Chris Watkins091d6292017-12-13 04:25:58164 virtual ~Waiter() = default;
[email protected]1c4947f2009-01-15 22:25:11165 };
166
167 private:
168 friend class WaitableEventWatcher;
169
170#if defined(OS_WIN)
rvargas59d5d592014-09-23 21:39:31171 win::ScopedHandle handle_;
Avi Drissman5b286372020-07-28 21:59:38172#elif defined(OS_APPLE)
Robert Sesekd54c0c1e2017-08-03 22:18:28173 // Prior to macOS 10.12, a TYPE_MACH_RECV dispatch source may not be invoked
174 // immediately. If a WaitableEventWatcher is used on a manual-reset event,
175 // and another thread that is Wait()ing on the event calls Reset()
176 // immediately after waking up, the watcher may not receive the callback.
177 // On macOS 10.12 and higher, dispatch delivery is reliable. But for OSes
178 // prior, a lock-protected list of callbacks is used for manual-reset event
179 // watchers. Automatic-reset events are not prone to this issue, since the
180 // first thread to wake will claim the event.
181 static bool UseSlowWatchList(ResetPolicy policy);
182
183 // Peeks the message queue named by |port| and returns true if a message
184 // is present and false if not. If |dequeue| is true, the messsage will be
185 // drained from the queue. If |dequeue| is false, the queue will only be
186 // peeked. |port| must be a receive right.
187 static bool PeekPort(mach_port_t port, bool dequeue);
188
189 // The Mach receive right is waited on by both WaitableEvent and
190 // WaitableEventWatcher. It is valid to signal and then delete an event, and
191 // a watcher should still be notified. If the right were to be destroyed
192 // immediately, the watcher would not receive the signal. Because Mach
193 // receive rights cannot have a user refcount greater than one, the right
194 // must be reference-counted manually.
195 class ReceiveRight : public RefCountedThreadSafe<ReceiveRight> {
196 public:
197 ReceiveRight(mach_port_t name, bool create_slow_watch_list);
198
Nico Weber51c45a72019-01-30 17:58:17199 mach_port_t Name() const { return right_.get(); }
Robert Sesekd54c0c1e2017-08-03 22:18:28200
201 // This structure is used iff UseSlowWatchList() is true. See the comment
202 // in Signal() for details.
203 struct WatchList {
204 WatchList();
205 ~WatchList();
206
207 // The lock protects a list of closures to be run when the event is
208 // Signal()ed. The closures are invoked on the signaling thread, so they
209 // must be safe to be called from any thread.
210 Lock lock;
211 std::list<OnceClosure> list;
212 };
213
214 WatchList* SlowWatchList() const { return slow_watch_list_.get(); }
215
216 private:
217 friend class RefCountedThreadSafe<ReceiveRight>;
218 ~ReceiveRight();
219
220 mac::ScopedMachReceiveRight right_;
221
222 // This is allocated iff UseSlowWatchList() is true. It is created on the
223 // heap to avoid performing initialization when not using the slow path.
224 std::unique_ptr<WatchList> slow_watch_list_;
225
226 DISALLOW_COPY_AND_ASSIGN(ReceiveRight);
227 };
228
229 const ResetPolicy policy_;
230
231 // The receive right for the event.
232 scoped_refptr<ReceiveRight> receive_right_;
233
234 // The send right used to signal the event. This can be disposed of with
235 // the event, unlike the receive right, since a deleted event cannot be
236 // signaled.
237 mac::ScopedMachSendRight send_right_;
Fabrice de Gans-Riberi306871de2018-05-16 19:38:39238#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
atuchin54d83152017-05-10 06:30:01239 // On Windows, you must not close a HANDLE which is currently being waited on.
240 // The MSDN documentation says that the resulting behaviour is 'undefined'.
241 // To solve that issue each WaitableEventWatcher duplicates the given event
242 // handle.
243
244 // However, if we were to include the following members
[email protected]c891ab92009-03-26 18:28:19245 // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an
246 // event which gets deleted. This mismatch has bitten us several times now,
247 // so we have a kernel of the WaitableEvent, which is reference counted.
248 // WaitableEventWatchers may then take a reference and thus match the Windows
249 // behaviour.
250 struct WaitableEventKernel :
251 public RefCountedThreadSafe<WaitableEventKernel> {
252 public:
gabd9aa1d12016-06-09 18:41:22253 WaitableEventKernel(ResetPolicy reset_policy, InitialState initial_state);
[email protected]c891ab92009-03-26 18:28:19254
255 bool Dequeue(Waiter* waiter, void* tag);
256
[email protected]20305ec2011-01-21 04:55:52257 base::Lock lock_;
[email protected]c891ab92009-03-26 18:28:19258 const bool manual_reset_;
259 bool signaled_;
260 std::list<Waiter*> waiters_;
[email protected]f2ebbf062012-04-06 03:14:30261
262 private:
263 friend class RefCountedThreadSafe<WaitableEventKernel>;
264 ~WaitableEventKernel();
[email protected]c891ab92009-03-26 18:28:19265 };
266
[email protected]a502bbe72011-01-07 18:06:45267 typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex;
[email protected]1c4947f2009-01-15 22:25:11268
269 // When dealing with arrays of WaitableEvent*, we want to sort by the address
270 // of the WaitableEvent in order to have a globally consistent locking order.
271 // In that case we keep them, in sorted order, in an array of pairs where the
272 // second element is the index of the WaitableEvent in the original,
273 // unsorted, array.
[email protected]550a1a42009-01-15 23:40:24274 static size_t EnqueueMany(WaiterAndIndex* waitables,
275 size_t count, Waiter* waiter);
[email protected]a502bbe72011-01-07 18:06:45276
277 bool SignalAll();
278 bool SignalOne();
279 void Enqueue(Waiter* waiter);
280
281 scoped_refptr<WaitableEventKernel> kernel_;
[email protected]b2e97292008-09-02 18:20:34282#endif
283
Gabriel Charette5db1ab82018-11-07 05:14:06284 // Whether a thread invoking Wait() on this WaitableEvent should be considered
285 // blocked as opposed to idle (and potentially replaced if part of a pool).
286 bool waiting_is_blocking_ = true;
287
[email protected]b2e97292008-09-02 18:20:34288 DISALLOW_COPY_AND_ASSIGN(WaitableEvent);
289};
290
291} // namespace base
292
[email protected]44f9c952011-01-02 06:05:39293#endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_