OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <algorithm> | 5 #include <algorithm> |
6 #include <vector> | 6 #include <vector> |
7 | 7 |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/synchronization/waitable_event.h" | 9 #include "base/synchronization/waitable_event.h" |
10 #include "base/synchronization/condition_variable.h" | 10 #include "base/synchronization/condition_variable.h" |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
190 const bool return_value = sw.fired(); | 190 const bool return_value = sw.fired(); |
191 | 191 |
192 // We can't acquire @lock_ before releasing the SyncWaiter lock (because | 192 // We can't acquire @lock_ before releasing the SyncWaiter lock (because |
193 // of locking order), however, in between the two a signal could be fired | 193 // of locking order), however, in between the two a signal could be fired |
194 // and @sw would accept it, however we will still return false, so the | 194 // and @sw would accept it, however we will still return false, so the |
195 // signal would be lost on an auto-reset WaitableEvent. Thus we call | 195 // signal would be lost on an auto-reset WaitableEvent. Thus we call |
196 // Disable which makes sw::Fire return false. | 196 // Disable which makes sw::Fire return false. |
197 sw.Disable(); | 197 sw.Disable(); |
198 sw.lock()->Release(); | 198 sw.lock()->Release(); |
199 | 199 |
200 // This is a bug that has been enshrined in the interface of | |
201 // WaitableEvent now: |Dequeue| is called even when |sw.fired()| is true, | |
202 // even though it'll always return false in that case. However, taking | |
203 // the lock ensures that |Signal| has completed before we return and | |
204 // means that a WaitableEvent can synchronise its own destruction. | |
200 kernel_->lock_.Acquire(); | 205 kernel_->lock_.Acquire(); |
201 kernel_->Dequeue(&sw, &sw); | 206 kernel_->Dequeue(&sw, &sw); |
202 kernel_->lock_.Release(); | 207 kernel_->lock_.Release(); |
203 | 208 |
204 return return_value; | 209 return return_value; |
205 } | 210 } |
206 | 211 |
207 if (finite_time) { | 212 if (finite_time) { |
208 const TimeDelta max_wait(end_time - current_time); | 213 const TimeDelta max_wait(end_time - current_time); |
209 sw.cv()->TimedWait(max_wait); | 214 sw.cv()->TimedWait(max_wait); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
283 // remove our SyncWaiter from the wait-list | 288 // remove our SyncWaiter from the wait-list |
284 for (size_t i = 0; i < count; ++i) { | 289 for (size_t i = 0; i < count; ++i) { |
285 if (raw_waitables[i] != signaled_event) { | 290 if (raw_waitables[i] != signaled_event) { |
286 raw_waitables[i]->kernel_->lock_.Acquire(); | 291 raw_waitables[i]->kernel_->lock_.Acquire(); |
287 // There's no possible ABA issue with the address of the SyncWaiter here | 292 // There's no possible ABA issue with the address of the SyncWaiter here |
288 // because it lives on the stack. Thus the tag value is just the pointer | 293 // because it lives on the stack. Thus the tag value is just the pointer |
289 // value again. | 294 // value again. |
290 raw_waitables[i]->kernel_->Dequeue(&sw, &sw); | 295 raw_waitables[i]->kernel_->Dequeue(&sw, &sw); |
291 raw_waitables[i]->kernel_->lock_.Release(); | 296 raw_waitables[i]->kernel_->lock_.Release(); |
292 } else { | 297 } else { |
298 // By taking this lock here we ensure that |Signal| has completed by the | |
willchan no longer on Chromium
2014/08/05 17:26:27
Non-obvious on a first read that Signal() is holdi
yhirano
2014/08/06 11:49:49
Done.
| |
299 // time we return. This matches the behaviour of |Wait| and |TimedWait|. | |
300 raw_waitables[i]->kernel_->lock_.Acquire(); | |
301 raw_waitables[i]->kernel_->lock_.Release(); | |
293 signaled_index = i; | 302 signaled_index = i; |
294 } | 303 } |
295 } | 304 } |
296 | 305 |
297 return signaled_index; | 306 return signaled_index; |
298 } | 307 } |
299 | 308 |
300 // ----------------------------------------------------------------------------- | 309 // ----------------------------------------------------------------------------- |
301 // If return value == 0: | 310 // If return value == 0: |
302 // The locks of the WaitableEvents have been taken in order and the Waiter has | 311 // The locks of the WaitableEvents have been taken in order and the Waiter has |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
398 return true; | 407 return true; |
399 } | 408 } |
400 } | 409 } |
401 | 410 |
402 return false; | 411 return false; |
403 } | 412 } |
404 | 413 |
405 // ----------------------------------------------------------------------------- | 414 // ----------------------------------------------------------------------------- |
406 | 415 |
407 } // namespace base | 416 } // namespace base |
OLD | NEW |