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 "base/base_export.h"
9#include "base/basictypes.h"
10
11#if defined(OS_WIN)
12#include <windows.h>
13#endif
14
15#if defined(OS_POSIX)
16#include <list>
17#include <utility>
18#include "base/memory/ref_counted.h"
19#include "base/synchronization/lock.h"
20#endif
21
22namespace base {
23
24// This replaces INFINITE from Win32
25static const int kNoTimeout = -1;
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  // If manual_reset is true, then to set the event state to non-signaled, a
47  // consumer must call the Reset method.  If this parameter is false, then the
48  // system automatically resets the event state to non-signaled after a single
49  // waiting thread has been released.
50  WaitableEvent(bool manual_reset, bool initially_signaled);
51
52#if defined(OS_WIN)
53  // Create a WaitableEvent from an Event HANDLE which has already been
54  // created. This objects takes ownership of the HANDLE and will close it when
55  // deleted.
56  explicit WaitableEvent(HANDLE event_handle);
57
58  // Releases ownership of the handle from this object.
59  HANDLE Release();
60#endif
61
62  ~WaitableEvent();
63
64  // Put the event in the un-signaled state.
65  void Reset();
66
67  // Put the event in the signaled state.  Causing any thread blocked on Wait
68  // to be woken up.
69  void Signal();
70
71  // Returns true if the event is in the signaled state, else false.  If this
72  // is not a manual reset event, then this test will cause a reset.
73  bool IsSignaled();
74
75  // Wait indefinitely for the event to be signaled.
76  void Wait();
77
78  // Wait up until max_time has passed for the event to be signaled.  Returns
79  // true if the event was signaled.  If this method returns false, then it
80  // does not necessarily mean that max_time was exceeded.
81  bool TimedWait(const TimeDelta& max_time);
82
83#if defined(OS_WIN)
84  HANDLE handle() const { return handle_; }
85#endif
86
87  // Wait, synchronously, on multiple events.
88  //   waitables: an array of WaitableEvent pointers
89  //   count: the number of elements in @waitables
90  //
91  // returns: the index of a WaitableEvent which has been signaled.
92  //
93  // You MUST NOT delete any of the WaitableEvent objects while this wait is
94  // happening.
95  static size_t WaitMany(WaitableEvent** waitables, size_t count);
96
97  // For asynchronous waiting, see WaitableEventWatcher
98
99  // This is a private helper class. It's here because it's used by friends of
100  // this class (such as WaitableEventWatcher) to be able to enqueue elements
101  // of the wait-list
102  class Waiter {
103   public:
104    // Signal the waiter to wake up.
105    //
106    // Consider the case of a Waiter which is in multiple WaitableEvent's
107    // wait-lists. Each WaitableEvent is automatic-reset and two of them are
108    // signaled at the same time. Now, each will wake only the first waiter in
109    // the wake-list before resetting. However, if those two waiters happen to
110    // be the same object (as can happen if another thread didn't have a chance
111    // to dequeue the waiter from the other wait-list in time), two auto-resets
112    // will have happened, but only one waiter has been signaled!
113    //
114    // Because of this, a Waiter may "reject" a wake by returning false. In
115    // this case, the auto-reset WaitableEvent shouldn't act as if anything has
116    // been notified.
117    virtual bool Fire(WaitableEvent* signaling_event) = 0;
118
119    // Waiters may implement this in order to provide an extra condition for
120    // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the
121    // pointers match then this function is called as a final check. See the
122    // comments in ~Handle for why.
123    virtual bool Compare(void* tag) = 0;
124
125   protected:
126    virtual ~Waiter() {}
127  };
128
129 private:
130  friend class WaitableEventWatcher;
131
132#if defined(OS_WIN)
133  HANDLE handle_;
134#else
135  // On Windows, one can close a HANDLE which is currently being waited on. The
136  // MSDN documentation says that the resulting behaviour is 'undefined', but
137  // it doesn't crash. However, if we were to include the following members
138  // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an
139  // event which gets deleted. This mismatch has bitten us several times now,
140  // so we have a kernel of the WaitableEvent, which is reference counted.
141  // WaitableEventWatchers may then take a reference and thus match the Windows
142  // behaviour.
143  struct WaitableEventKernel :
144      public RefCountedThreadSafe<WaitableEventKernel> {
145   public:
146    WaitableEventKernel(bool manual_reset, bool initially_signaled);
147
148    bool Dequeue(Waiter* waiter, void* tag);
149
150    base::Lock lock_;
151    const bool manual_reset_;
152    bool signaled_;
153    std::list<Waiter*> waiters_;
154
155   private:
156    friend class RefCountedThreadSafe<WaitableEventKernel>;
157    ~WaitableEventKernel();
158  };
159
160  typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex;
161
162  // When dealing with arrays of WaitableEvent*, we want to sort by the address
163  // of the WaitableEvent in order to have a globally consistent locking order.
164  // In that case we keep them, in sorted order, in an array of pairs where the
165  // second element is the index of the WaitableEvent in the original,
166  // unsorted, array.
167  static size_t EnqueueMany(WaiterAndIndex* waitables,
168                            size_t count, Waiter* waiter);
169
170  bool SignalAll();
171  bool SignalOne();
172  void Enqueue(Waiter* waiter);
173
174  scoped_refptr<WaitableEventKernel> kernel_;
175#endif
176
177  DISALLOW_COPY_AND_ASSIGN(WaitableEvent);
178};
179
180}  // namespace base
181
182#endif  // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_
183