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