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