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