OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/waitable_event.h" | 5 #include "base/waitable_event.h" |
6 | 6 |
7 #include "base/condition_variable.h" | 7 #include "base/condition_variable.h" |
8 #include "base/lock.h" | 8 #include "base/lock.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 // firing a waiter and so we can store that pointer to find out which event | 28 // firing a waiter and so we can store that pointer to find out which event |
29 // triggered. | 29 // triggered. |
30 // ----------------------------------------------------------------------------- | 30 // ----------------------------------------------------------------------------- |
31 | 31 |
32 namespace base { | 32 namespace base { |
33 | 33 |
34 // ----------------------------------------------------------------------------- | 34 // ----------------------------------------------------------------------------- |
35 // This is just an abstract base class for waking the two types of waiters | 35 // This is just an abstract base class for waking the two types of waiters |
36 // ----------------------------------------------------------------------------- | 36 // ----------------------------------------------------------------------------- |
37 WaitableEvent::WaitableEvent(bool manual_reset, bool initially_signaled) | 37 WaitableEvent::WaitableEvent(bool manual_reset, bool initially_signaled) |
38 : signaled_(false), | 38 : signaled_(initially_signaled), |
39 manual_reset_(manual_reset) { | 39 manual_reset_(manual_reset) { |
40 DCHECK(!initially_signaled) << "Not implemented"; | |
41 } | 40 } |
42 | 41 |
43 WaitableEvent::~WaitableEvent() { | 42 WaitableEvent::~WaitableEvent() { |
44 DCHECK(waiters_.empty()) << "Deleting WaitableEvent with listeners!"; | 43 if (!waiters_.empty()) { |
| 44 LOG(ERROR) << "Destroying a WaitableEvent (" << this << ") with " |
| 45 << waiters_.size() << " waiters"; |
| 46 NOTREACHED() << "Aborting."; |
| 47 } |
45 } | 48 } |
46 | 49 |
47 void WaitableEvent::Reset() { | 50 void WaitableEvent::Reset() { |
48 AutoLock locked(lock_); | 51 AutoLock locked(lock_); |
49 signaled_ = false; | 52 signaled_ = false; |
50 } | 53 } |
51 | 54 |
52 void WaitableEvent::Signal() { | 55 void WaitableEvent::Signal() { |
53 AutoLock locked(lock_); | 56 AutoLock locked(lock_); |
54 | 57 |
(...skipping 26 matching lines...) Expand all Loading... |
81 // ----------------------------------------------------------------------------- | 84 // ----------------------------------------------------------------------------- |
82 // This is an synchronous waiter. The thread is waiting on the given condition | 85 // This is an synchronous waiter. The thread is waiting on the given condition |
83 // variable and the fired flag in this object. | 86 // variable and the fired flag in this object. |
84 // ----------------------------------------------------------------------------- | 87 // ----------------------------------------------------------------------------- |
85 class SyncWaiter : public WaitableEvent::Waiter { | 88 class SyncWaiter : public WaitableEvent::Waiter { |
86 public: | 89 public: |
87 SyncWaiter(ConditionVariable* cv, Lock* lock) | 90 SyncWaiter(ConditionVariable* cv, Lock* lock) |
88 : fired_(false), | 91 : fired_(false), |
89 cv_(cv), | 92 cv_(cv), |
90 lock_(lock), | 93 lock_(lock), |
91 signaling_event_(NULL) { } | 94 signaling_event_(NULL) { |
| 95 } |
92 | 96 |
93 bool Fire(WaitableEvent *signaling_event) { | 97 bool Fire(WaitableEvent *signaling_event) { |
94 lock_->Acquire(); | 98 lock_->Acquire(); |
95 const bool previous_value = fired_; | 99 const bool previous_value = fired_; |
96 fired_ = true; | 100 fired_ = true; |
97 if (!previous_value) | 101 if (!previous_value) |
98 signaling_event_ = signaling_event; | 102 signaling_event_ = signaling_event; |
99 lock_->Release(); | 103 lock_->Release(); |
100 | 104 |
101 if (previous_value) | 105 if (previous_value) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 | 141 |
138 private: | 142 private: |
139 bool fired_; | 143 bool fired_; |
140 ConditionVariable *const cv_; | 144 ConditionVariable *const cv_; |
141 Lock *const lock_; | 145 Lock *const lock_; |
142 WaitableEvent* signaling_event_; // The WaitableEvent which woke us | 146 WaitableEvent* signaling_event_; // The WaitableEvent which woke us |
143 }; | 147 }; |
144 | 148 |
145 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { | 149 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { |
146 const Time end_time(Time::Now() + max_time); | 150 const Time end_time(Time::Now() + max_time); |
| 151 const bool finite_time = max_time.ToInternalValue() >= 0; |
147 | 152 |
148 lock_.Acquire(); | 153 lock_.Acquire(); |
149 if (signaled_) { | 154 if (signaled_) { |
150 if (!manual_reset_) { | 155 if (!manual_reset_) { |
151 // In this case we were signaled when we had no waiters. Now that | 156 // In this case we were signaled when we had no waiters. Now that |
152 // someone has waited upon us, we can automatically reset. | 157 // someone has waited upon us, we can automatically reset. |
153 signaled_ = false; | 158 signaled_ = false; |
154 } | 159 } |
155 | 160 |
156 lock_.Release(); | 161 lock_.Release(); |
157 return true; | 162 return true; |
158 } | 163 } |
159 | 164 |
160 Lock lock; | 165 Lock lock; |
161 lock.Acquire(); | 166 lock.Acquire(); |
162 ConditionVariable cv(&lock); | 167 ConditionVariable cv(&lock); |
163 SyncWaiter sw(&cv, &lock); | 168 SyncWaiter sw(&cv, &lock); |
164 | 169 |
165 Enqueue(&sw); | 170 Enqueue(&sw); |
166 lock_.Release(); | 171 lock_.Release(); |
167 // We are violating locking order here by holding the SyncWaiter lock but not | 172 // We are violating locking order here by holding the SyncWaiter lock but not |
168 // the WaitableEvent lock. However, this is safe because we don't lock @lock_ | 173 // the WaitableEvent lock. However, this is safe because we don't lock @lock_ |
169 // again before unlocking it. | 174 // again before unlocking it. |
170 | 175 |
171 for (;;) { | 176 for (;;) { |
172 if (sw.fired()) { | 177 const Time current_time(Time::Now()); |
| 178 |
| 179 if (sw.fired() || (finite_time && current_time >= end_time)) { |
| 180 const bool return_value = sw.fired(); |
| 181 |
| 182 // We can't acquire @lock_ before releasing @lock (because of locking |
| 183 // order), however, inbetween the two a signal could be fired and @sw |
| 184 // would accept it, however we will still return false, so the signal |
| 185 // would be lost on an auto-reset WaitableEvent. Thus we call Disable |
| 186 // which makes sw::Fire return false. |
| 187 sw.Disable(); |
173 lock.Release(); | 188 lock.Release(); |
174 return true; | 189 |
| 190 lock_.Acquire(); |
| 191 Dequeue(&sw, &sw); |
| 192 lock_.Release(); |
| 193 |
| 194 return return_value; |
175 } | 195 } |
176 | 196 |
177 if (max_time.ToInternalValue() < 0) { | 197 if (finite_time) { |
| 198 const TimeDelta max_wait(end_time - current_time); |
| 199 cv.TimedWait(max_wait); |
| 200 } else { |
178 cv.Wait(); | 201 cv.Wait(); |
179 } else { | |
180 const Time current_time(Time::Now()); | |
181 if (current_time >= end_time) { | |
182 // We can't acquire @lock_ before releasing @lock (because of locking | |
183 // order), however, inbetween the two a signal could be fired and @sw | |
184 // would accept it, however we will still return false, so the signal | |
185 // would be lost on an auto-reset WaitableEvent. Thus we call Disable | |
186 // which makes sw::Fire return false. | |
187 sw.Disable(); | |
188 lock.Release(); | |
189 | |
190 lock_.Acquire(); | |
191 Dequeue(&sw, &sw); | |
192 lock_.Release(); | |
193 return false; | |
194 } | |
195 const TimeDelta max_wait(end_time - current_time); | |
196 | |
197 cv.TimedWait(max_wait); | |
198 } | 202 } |
199 } | 203 } |
200 } | 204 } |
201 | 205 |
202 bool WaitableEvent::Wait() { | 206 bool WaitableEvent::Wait() { |
203 return TimedWait(TimeDelta::FromSeconds(-1)); | 207 return TimedWait(TimeDelta::FromSeconds(-1)); |
204 } | 208 } |
205 | 209 |
206 // ----------------------------------------------------------------------------- | 210 // ----------------------------------------------------------------------------- |
207 | 211 |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 return true; | 387 return true; |
384 } | 388 } |
385 } | 389 } |
386 | 390 |
387 return false; | 391 return false; |
388 } | 392 } |
389 | 393 |
390 // ----------------------------------------------------------------------------- | 394 // ----------------------------------------------------------------------------- |
391 | 395 |
392 } // namespace base | 396 } // namespace base |
OLD | NEW |