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