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#endif
17
18#if defined(OS_POSIX)
19#include <list>
20#include <utility>
21#include "base/memory/ref_counted.h"
22#include "base/synchronization/lock.h"
23#endif
24
25namespace base {
26
27class TimeDelta;
28
29// A WaitableEvent can be a useful thread synchronization tool when you want to
30// allow one thread to wait for another thread to finish some work. For
31// non-Windows systems, this can only be used from within a single address
32// space.
33//
34// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to
35// protect a simple boolean value.  However, if you find yourself using a
36// WaitableEvent in conjunction with a Lock to wait for a more complex state
37// change (e.g., for an item to be added to a queue), then you should probably
38// be using a ConditionVariable instead of a WaitableEvent.
39//
40// NOTE: On Windows, this class provides a subset of the functionality afforded
41// by a Windows event object.  This is intentional.  If you are writing Windows
42// specific code and you need other features of a Windows event, then you might
43// be better off just using an Windows event directly.
44class BASE_EXPORT WaitableEvent {
45 public:
46  // Indicates whether a WaitableEvent should automatically reset the event
47  // state after a single waiting thread has been released or remain signaled
48  // until Reset() is manually invoked.
49  enum class ResetPolicy { MANUAL, AUTOMATIC };
50
51  // Indicates whether a new WaitableEvent should start in a signaled state or
52  // not.
53  enum class InitialState { SIGNALED, NOT_SIGNALED };
54
55  // Constructs a WaitableEvent with policy and initial state as detailed in
56  // the above enums.
57  WaitableEvent(ResetPolicy reset_policy, InitialState initial_state);
58
59#if defined(OS_WIN)
60  // Create a WaitableEvent from an Event HANDLE which has already been
61  // created. This objects takes ownership of the HANDLE and will close it when
62  // deleted.
63  explicit WaitableEvent(win::ScopedHandle event_handle);
64#endif
65
66  ~WaitableEvent();
67
68  // Put the event in the un-signaled state.
69  void Reset();
70
71  // Put the event in the signaled state.  Causing any thread blocked on Wait
72  // to be woken up.
73  void Signal();
74
75  // Returns true if the event is in the signaled state, else false.  If this
76  // is not a manual reset event, then this test will cause a reset.
77  bool IsSignaled();
78
79  // Wait indefinitely for the event to be signaled. Wait's return "happens
80  // after" |Signal| has completed. This means that it's safe for a
81  // WaitableEvent to synchronise its own destruction, like this:
82  //
83  //   WaitableEvent *e = new WaitableEvent;
84  //   SendToOtherThread(e);
85  //   e->Wait();
86  //   delete e;
87  void Wait();
88
89  // Wait up until max_time has passed for the event to be signaled.  Returns
90  // true if the event was signaled.  If this method returns false, then it
91  // does not necessarily mean that max_time was exceeded.
92  //
93  // TimedWait can synchronise its own destruction like |Wait|.
94  bool TimedWait(const TimeDelta& max_time);
95
96#if defined(OS_WIN)
97  HANDLE handle() const { return handle_.Get(); }
98#endif
99
100  // Wait, synchronously, on multiple events.
101  //   waitables: an array of WaitableEvent pointers
102  //   count: the number of elements in @waitables
103  //
104  // returns: the index of a WaitableEvent which has been signaled.
105  //
106  // You MUST NOT delete any of the WaitableEvent objects while this wait is
107  // happening, however WaitMany's return "happens after" the |Signal| call
108  // that caused it has completed, like |Wait|.
109  static size_t WaitMany(WaitableEvent** waitables, size_t count);
110
111  // For asynchronous waiting, see WaitableEventWatcher
112
113  // This is a private helper class. It's here because it's used by friends of
114  // this class (such as WaitableEventWatcher) to be able to enqueue elements
115  // of the wait-list
116  class Waiter {
117   public:
118    // Signal the waiter to wake up.
119    //
120    // Consider the case of a Waiter which is in multiple WaitableEvent's
121    // wait-lists. Each WaitableEvent is automatic-reset and two of them are
122    // signaled at the same time. Now, each will wake only the first waiter in
123    // the wake-list before resetting. However, if those two waiters happen to
124    // be the same object (as can happen if another thread didn't have a chance
125    // to dequeue the waiter from the other wait-list in time), two auto-resets
126    // will have happened, but only one waiter has been signaled!
127    //
128    // Because of this, a Waiter may "reject" a wake by returning false. In
129    // this case, the auto-reset WaitableEvent shouldn't act as if anything has
130    // been notified.
131    virtual bool Fire(WaitableEvent* signaling_event) = 0;
132
133    // Waiters may implement this in order to provide an extra condition for
134    // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the
135    // pointers match then this function is called as a final check. See the
136    // comments in ~Handle for why.
137    virtual bool Compare(void* tag) = 0;
138
139   protected:
140    virtual ~Waiter() {}
141  };
142
143 private:
144  friend class WaitableEventWatcher;
145
146#if defined(OS_WIN)
147  win::ScopedHandle handle_;
148#else
149  // On Windows, one can close a HANDLE which is currently being waited on. The
150  // MSDN documentation says that the resulting behaviour is 'undefined', but
151  // it doesn't crash. However, if we were to include the following members
152  // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an
153  // event which gets deleted. This mismatch has bitten us several times now,
154  // so we have a kernel of the WaitableEvent, which is reference counted.
155  // WaitableEventWatchers may then take a reference and thus match the Windows
156  // behaviour.
157  struct WaitableEventKernel :
158      public RefCountedThreadSafe<WaitableEventKernel> {
159   public:
160    WaitableEventKernel(ResetPolicy reset_policy, InitialState initial_state);
161
162    bool Dequeue(Waiter* waiter, void* tag);
163
164    base::Lock lock_;
165    const bool manual_reset_;
166    bool signaled_;
167    std::list<Waiter*> waiters_;
168
169   private:
170    friend class RefCountedThreadSafe<WaitableEventKernel>;
171    ~WaitableEventKernel();
172  };
173
174  typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex;
175
176  // When dealing with arrays of WaitableEvent*, we want to sort by the address
177  // of the WaitableEvent in order to have a globally consistent locking order.
178  // In that case we keep them, in sorted order, in an array of pairs where the
179  // second element is the index of the WaitableEvent in the original,
180  // unsorted, array.
181  static size_t EnqueueMany(WaiterAndIndex* waitables,
182                            size_t count, Waiter* waiter);
183
184  bool SignalAll();
185  bool SignalOne();
186  void Enqueue(Waiter* waiter);
187
188  scoped_refptr<WaitableEventKernel> kernel_;
189#endif
190
191  DISALLOW_COPY_AND_ASSIGN(WaitableEvent);
192};
193
194}  // namespace base
195
196#endif  // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_
197