blob: cff1e12ccfd6a2ce6f12ee3f6bcdaf0c4b0edf97 [file] [log] [blame]
[email protected]b2e97292008-09-02 18:20:341// Copyright (c) 2006-2008 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_WAITABLE_EVENT_H_
6#define BASE_WAITABLE_EVENT_H_
7
8#include "base/basictypes.h"
9
10#if defined(OS_WIN)
[email protected]1c4947f2009-01-15 22:25:1111#include <windows.h>
12#endif
13
14#if defined(OS_POSIX)
15#include <list>
16#include <utility>
[email protected]b2e97292008-09-02 18:20:3417#include "base/condition_variable.h"
18#include "base/lock.h"
[email protected]1c4947f2009-01-15 22:25:1119#include "base/ref_counted.h"
[email protected]b2e97292008-09-02 18:20:3420#endif
21
[email protected]1c4947f2009-01-15 22:25:1122#include "base/message_loop.h"
23
[email protected]b2e97292008-09-02 18:20:3424namespace base {
25
[email protected]e1acf6f2008-10-27 20:43:3326class TimeDelta;
27
[email protected]b2e97292008-09-02 18:20:3428// A WaitableEvent can be a useful thread synchronization tool when you want to
[email protected]1c4947f2009-01-15 22:25:1129// allow one thread to wait for another thread to finish some work. For
30// non-Windows systems, this can only be used from within a single address
31// space.
[email protected]b2e97292008-09-02 18:20:3432//
33// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to
34// protect a simple boolean value. However, if you find yourself using a
35// WaitableEvent in conjunction with a Lock to wait for a more complex state
36// change (e.g., for an item to be added to a queue), then you should probably
37// be using a ConditionVariable instead of a WaitableEvent.
38//
39// NOTE: On Windows, this class provides a subset of the functionality afforded
40// by a Windows event object. This is intentional. If you are writing Windows
41// specific code and you need other features of a Windows event, then you might
42// be better off just using an Windows event directly.
[email protected]b2e97292008-09-02 18:20:3443class WaitableEvent {
44 public:
45 // If manual_reset is true, then to set the event state to non-signaled, a
46 // consumer must call the Reset method. If this parameter is false, then the
47 // system automatically resets the event state to non-signaled after a single
48 // waiting thread has been released.
49 WaitableEvent(bool manual_reset, bool initially_signaled);
50
[email protected]1c4947f2009-01-15 22:25:1151#if defined(OS_WIN)
52 // Create a WaitableEvent from an Event HANDLE which has already been
53 // created. This objects takes ownership of the HANDLE and will close it when
54 // deleted.
55 explicit WaitableEvent(HANDLE event_handle);
56#endif
57
[email protected]b2e97292008-09-02 18:20:3458 // WARNING: Destroying a WaitableEvent while threads are waiting on it is not
59 // supported. Doing so will cause crashes or other instability.
60 ~WaitableEvent();
61
62 // Put the event in the un-signaled state.
63 void Reset();
64
65 // Put the event in the signaled state. Causing any thread blocked on Wait
66 // to be woken up.
67 void Signal();
68
69 // Returns true if the event is in the signaled state, else false. If this
70 // is not a manual reset event, then this test will cause a reset.
71 bool IsSignaled();
72
73 // Wait indefinitely for the event to be signaled. Returns true if the event
74 // was signaled, else false is returned to indicate that waiting failed.
75 bool Wait();
76
77 // Wait up until max_time has passed for the event to be signaled. Returns
78 // true if the event was signaled. If this method returns false, then it
79 // does not necessarily mean that max_time was exceeded.
80 bool TimedWait(const TimeDelta& max_time);
81
[email protected]b2e97292008-09-02 18:20:3482#if defined(OS_WIN)
[email protected]1c4947f2009-01-15 22:25:1183 HANDLE handle() const { return handle_; }
84#endif
85
86 // Wait, synchronously, on multiple events.
87 // waitables: an array of WaitableEvent pointers
88 // count: the number of elements in @waitables
89 //
90 // returns: the index of a WaitableEvent which has been signaled.
91 static size_t WaitMany(WaitableEvent** waitables, size_t count);
92
93 // For asynchronous waiting, see WaitableEventWatcher
94
95 // This is a private helper class. It's here because it's used by friends of
96 // this class (such as WaitableEventWatcher) to be able to enqueue elements
97 // of the wait-list
98 class Waiter {
99 public:
100 // Signal the waiter to wake up.
101 //
102 // Consider the case of a Waiter which is in multiple WaitableEvent's
103 // wait-lists. Each WaitableEvent is automatic-reset and two of them are
104 // signaled at the same time. Now, each will wake only the first waiter in
105 // the wake-list before resetting. However, if those two waiters happen to
106 // be the same object (as can happen if another thread didn't have a chance
107 // to dequeue the waiter from the other wait-list in time), two auto-resets
108 // will have happened, but only one waiter has been signaled!
109 //
110 // Because of this, a Waiter may "reject" a wake by returning false. In
111 // this case, the auto-reset WaitableEvent shouldn't act as if anything has
112 // been notified.
113 virtual bool Fire(WaitableEvent* signaling_event) = 0;
114
115 // Waiters may implement this in order to provide an extra condition for
116 // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the
117 // pointers match then this function is called as a final check. See the
118 // comments in ~Handle for why.
119 virtual bool Compare(void* tag) = 0;
120 };
121
122 private:
123 friend class WaitableEventWatcher;
124
125#if defined(OS_WIN)
126 HANDLE handle_;
[email protected]b2e97292008-09-02 18:20:34127#else
[email protected]1c4947f2009-01-15 22:25:11128 bool SignalAll();
129 bool SignalOne();
130 void Enqueue(Waiter* waiter);
131 bool Dequeue(Waiter* waiter, void* tag);
132
133 // When dealing with arrays of WaitableEvent*, we want to sort by the address
134 // of the WaitableEvent in order to have a globally consistent locking order.
135 // In that case we keep them, in sorted order, in an array of pairs where the
136 // second element is the index of the WaitableEvent in the original,
137 // unsorted, array.
138 typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex;
[email protected]550a1a42009-01-15 23:40:24139 static size_t EnqueueMany(WaiterAndIndex* waitables,
140 size_t count, Waiter* waiter);
[email protected]1c4947f2009-01-15 22:25:11141
142 Lock lock_;
[email protected]b2e97292008-09-02 18:20:34143 bool signaled_;
[email protected]1c4947f2009-01-15 22:25:11144 const bool manual_reset_;
145 std::list<Waiter*> waiters_;
[email protected]b2e97292008-09-02 18:20:34146#endif
147
148 DISALLOW_COPY_AND_ASSIGN(WaitableEvent);
149};
150
151} // namespace base
152
153#endif // BASE_WAITABLE_EVENT_H_