OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/synchronization/waitable_event.h" | 5 #include "base/synchronization/waitable_event.h" |
6 | 6 |
7 #include "base/synchronization/condition_variable.h" | 7 #include "base/synchronization/condition_variable.h" |
8 #include "base/synchronization/lock.h" | 8 #include "base/synchronization/lock.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 | 10 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 return &cv_; | 142 return &cv_; |
143 } | 143 } |
144 | 144 |
145 private: | 145 private: |
146 bool fired_; | 146 bool fired_; |
147 WaitableEvent* signaling_event_; // The WaitableEvent which woke us | 147 WaitableEvent* signaling_event_; // The WaitableEvent which woke us |
148 base::Lock lock_; | 148 base::Lock lock_; |
149 base::ConditionVariable cv_; | 149 base::ConditionVariable cv_; |
150 }; | 150 }; |
151 | 151 |
152 bool WaitableEvent::Wait() { | 152 void WaitableEvent::Wait() { |
153 return TimedWait(TimeDelta::FromSeconds(-1)); | 153 bool result = TimedWait(TimeDelta::FromSeconds(-1)); |
| 154 DCHECK(result) << "TimedWait() should never fail with infinite timeout"; |
154 } | 155 } |
155 | 156 |
156 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { | 157 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { |
157 const Time end_time(Time::Now() + max_time); | 158 const Time end_time(Time::Now() + max_time); |
158 const bool finite_time = max_time.ToInternalValue() >= 0; | 159 const bool finite_time = max_time.ToInternalValue() >= 0; |
159 | 160 |
160 kernel_->lock_.Acquire(); | 161 kernel_->lock_.Acquire(); |
161 if (kernel_->signaled_) { | 162 if (kernel_->signaled_) { |
162 if (!kernel_->manual_reset_) { | 163 if (!kernel_->manual_reset_) { |
163 // In this case we were signaled when we had no waiters. Now that | 164 // In this case we were signaled when we had no waiters. Now that |
164 // someone has waited upon us, we can automatically reset. | 165 // someone has waited upon us, we can automatically reset. |
165 kernel_->signaled_ = false; | 166 kernel_->signaled_ = false; |
166 } | |
167 | |
168 kernel_->lock_.Release(); | |
169 return true; | |
170 } | 167 } |
171 | 168 |
172 SyncWaiter sw; | 169 kernel_->lock_.Release(); |
173 sw.lock()->Acquire(); | 170 return true; |
| 171 } |
174 | 172 |
175 Enqueue(&sw); | 173 SyncWaiter sw; |
| 174 sw.lock()->Acquire(); |
| 175 |
| 176 Enqueue(&sw); |
176 kernel_->lock_.Release(); | 177 kernel_->lock_.Release(); |
177 // We are violating locking order here by holding the SyncWaiter lock but not | 178 // We are violating locking order here by holding the SyncWaiter lock but not |
178 // the WaitableEvent lock. However, this is safe because we don't lock @lock_ | 179 // the WaitableEvent lock. However, this is safe because we don't lock @lock_ |
179 // again before unlocking it. | 180 // again before unlocking it. |
180 | 181 |
181 for (;;) { | 182 for (;;) { |
182 const Time current_time(Time::Now()); | 183 const Time current_time(Time::Now()); |
183 | 184 |
184 if (sw.fired() || (finite_time && current_time >= end_time)) { | 185 if (sw.fired() || (finite_time && current_time >= end_time)) { |
185 const bool return_value = sw.fired(); | 186 const bool return_value = sw.fired(); |
186 | 187 |
187 // We can't acquire @lock_ before releasing the SyncWaiter lock (because | 188 // We can't acquire @lock_ before releasing the SyncWaiter lock (because |
188 // of locking order), however, in between the two a signal could be fired | 189 // of locking order), however, in between the two a signal could be fired |
189 // and @sw would accept it, however we will still return false, so the | 190 // and @sw would accept it, however we will still return false, so the |
190 // signal would be lost on an auto-reset WaitableEvent. Thus we call | 191 // signal would be lost on an auto-reset WaitableEvent. Thus we call |
191 // Disable which makes sw::Fire return false. | 192 // Disable which makes sw::Fire return false. |
192 sw.Disable(); | 193 sw.Disable(); |
193 sw.lock()->Release(); | 194 sw.lock()->Release(); |
194 | 195 |
195 kernel_->lock_.Acquire(); | 196 kernel_->lock_.Acquire(); |
196 kernel_->Dequeue(&sw, &sw); | 197 kernel_->Dequeue(&sw, &sw); |
197 kernel_->lock_.Release(); | 198 kernel_->lock_.Release(); |
198 | 199 |
199 return return_value; | 200 return return_value; |
200 } | 201 } |
201 | 202 |
202 if (finite_time) { | 203 if (finite_time) { |
203 const TimeDelta max_wait(end_time - current_time); | 204 const TimeDelta max_wait(end_time - current_time); |
204 sw.cv()->TimedWait(max_wait); | 205 sw.cv()->TimedWait(max_wait); |
205 } else { | 206 } else { |
206 sw.cv()->Wait(); | 207 sw.cv()->Wait(); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 return true; | 393 return true; |
393 } | 394 } |
394 } | 395 } |
395 | 396 |
396 return false; | 397 return false; |
397 } | 398 } |
398 | 399 |
399 // ----------------------------------------------------------------------------- | 400 // ----------------------------------------------------------------------------- |
400 | 401 |
401 } // namespace base | 402 } // namespace base |
OLD | NEW |