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 <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | |
9 #include <vector> | 8 #include <vector> |
10 | 9 |
11 #include "base/debug/activity_tracker.h" | 10 #include "base/debug/activity_tracker.h" |
12 #include "base/logging.h" | 11 #include "base/logging.h" |
13 #include "base/synchronization/condition_variable.h" | 12 #include "base/synchronization/condition_variable.h" |
14 #include "base/synchronization/lock.h" | 13 #include "base/synchronization/lock.h" |
15 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
16 #include "base/threading/thread_restrictions.h" | 15 #include "base/threading/thread_restrictions.h" |
17 | 16 |
18 // ----------------------------------------------------------------------------- | 17 // ----------------------------------------------------------------------------- |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 // The set of waitables must be distinct. Since we have just sorted by | 259 // The set of waitables must be distinct. Since we have just sorted by |
261 // address, we can check this cheaply by comparing pairs of consecutive | 260 // address, we can check this cheaply by comparing pairs of consecutive |
262 // elements. | 261 // elements. |
263 for (size_t i = 0; i < waitables.size() - 1; ++i) { | 262 for (size_t i = 0; i < waitables.size() - 1; ++i) { |
264 DCHECK(waitables[i].first != waitables[i+1].first); | 263 DCHECK(waitables[i].first != waitables[i+1].first); |
265 } | 264 } |
266 | 265 |
267 SyncWaiter sw; | 266 SyncWaiter sw; |
268 | 267 |
269 const size_t r = EnqueueMany(&waitables[0], count, &sw); | 268 const size_t r = EnqueueMany(&waitables[0], count, &sw); |
270 if (r < count) { | 269 if (r) { |
271 // One of the events is already signaled. The SyncWaiter has not been | 270 // One of the events is already signaled. The SyncWaiter has not been |
272 // enqueued anywhere. | 271 // enqueued anywhere. EnqueueMany returns the count of remaining waitables |
273 return waitables[r].second; | 272 // when the signaled one was seen, so the index of the signaled event is |
| 273 // @count - @r. |
| 274 return waitables[count - r].second; |
274 } | 275 } |
275 | 276 |
276 // At this point, we hold the locks on all the WaitableEvents and we have | 277 // At this point, we hold the locks on all the WaitableEvents and we have |
277 // enqueued our waiter in them all. | 278 // enqueued our waiter in them all. |
278 sw.lock()->Acquire(); | 279 sw.lock()->Acquire(); |
279 // Release the WaitableEvent locks in the reverse order | 280 // Release the WaitableEvent locks in the reverse order |
280 for (size_t i = 0; i < count; ++i) { | 281 for (size_t i = 0; i < count; ++i) { |
281 waitables[count - (1 + i)].first->kernel_->lock_.Release(); | 282 waitables[count - (1 + i)].first->kernel_->lock_.Release(); |
282 } | 283 } |
283 | 284 |
(...skipping 27 matching lines...) Expand all Loading... |
311 raw_waitables[i]->kernel_->lock_.Acquire(); | 312 raw_waitables[i]->kernel_->lock_.Acquire(); |
312 raw_waitables[i]->kernel_->lock_.Release(); | 313 raw_waitables[i]->kernel_->lock_.Release(); |
313 signaled_index = i; | 314 signaled_index = i; |
314 } | 315 } |
315 } | 316 } |
316 | 317 |
317 return signaled_index; | 318 return signaled_index; |
318 } | 319 } |
319 | 320 |
320 // ----------------------------------------------------------------------------- | 321 // ----------------------------------------------------------------------------- |
321 // If return value == count: | 322 // If return value == 0: |
322 // The locks of the WaitableEvents have been taken in order and the Waiter has | 323 // The locks of the WaitableEvents have been taken in order and the Waiter has |
323 // been enqueued in the wait-list of each. None of the WaitableEvents are | 324 // been enqueued in the wait-list of each. None of the WaitableEvents are |
324 // currently signaled | 325 // currently signaled |
325 // else: | 326 // else: |
326 // None of the WaitableEvent locks are held. The Waiter has not been enqueued | 327 // None of the WaitableEvent locks are held. The Waiter has not been enqueued |
327 // in any of them and the return value is the index of the WaitableEvent which | 328 // in any of them and the return value is the index of the first WaitableEvent |
328 // was signaled with the lowest input index from the original WaitMany call. | 329 // which was signaled, from the end of the array. |
329 // ----------------------------------------------------------------------------- | 330 // ----------------------------------------------------------------------------- |
330 // static | 331 // static |
331 size_t WaitableEvent::EnqueueMany(std::pair<WaitableEvent*, size_t>* waitables, | 332 size_t WaitableEvent::EnqueueMany |
332 size_t count, | 333 (std::pair<WaitableEvent*, size_t>* waitables, |
333 Waiter* waiter) { | 334 size_t count, Waiter* waiter) { |
334 size_t winner = count; | 335 if (!count) |
335 size_t winner_index = count; | 336 return 0; |
336 for (size_t i = 0; i < count; ++i) { | 337 |
337 auto& kernel = waitables[i].first->kernel_; | 338 waitables[0].first->kernel_->lock_.Acquire(); |
338 kernel->lock_.Acquire(); | 339 if (waitables[0].first->kernel_->signaled_) { |
339 if (kernel->signaled_ && waitables[i].second < winner) { | 340 if (!waitables[0].first->kernel_->manual_reset_) |
340 winner = waitables[i].second; | 341 waitables[0].first->kernel_->signaled_ = false; |
341 winner_index = i; | 342 waitables[0].first->kernel_->lock_.Release(); |
| 343 return count; |
342 } | 344 } |
343 } | |
344 | 345 |
345 // No events signaled. All locks acquired. Enqueue the Waiter on all of them | 346 const size_t r = EnqueueMany(waitables + 1, count - 1, waiter); |
346 // and return. | 347 if (r) { |
347 if (winner == count) { | 348 waitables[0].first->kernel_->lock_.Release(); |
348 for (size_t i = 0; i < count; ++i) | 349 } else { |
349 waitables[i].first->Enqueue(waiter); | 350 waitables[0].first->Enqueue(waiter); |
350 return count; | 351 } |
351 } | |
352 | 352 |
353 // Unlock in reverse order and possibly clear the chosen winner's signal | 353 return r; |
354 // before returning its index. | |
355 for (auto* w = waitables + count - 1; w >= waitables; --w) { | |
356 auto& kernel = w->first->kernel_; | |
357 if (w->second == winner) { | |
358 if (!kernel->manual_reset_) | |
359 kernel->signaled_ = false; | |
360 } | |
361 kernel->lock_.Release(); | |
362 } | |
363 | |
364 return winner_index; | |
365 } | 354 } |
366 | 355 |
367 // ----------------------------------------------------------------------------- | 356 // ----------------------------------------------------------------------------- |
368 | 357 |
369 | 358 |
370 // ----------------------------------------------------------------------------- | 359 // ----------------------------------------------------------------------------- |
371 // Private functions... | 360 // Private functions... |
372 | 361 |
373 WaitableEvent::WaitableEventKernel::WaitableEventKernel( | 362 WaitableEvent::WaitableEventKernel::WaitableEventKernel( |
374 ResetPolicy reset_policy, | 363 ResetPolicy reset_policy, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 return true; | 418 return true; |
430 } | 419 } |
431 } | 420 } |
432 | 421 |
433 return false; | 422 return false; |
434 } | 423 } |
435 | 424 |
436 // ----------------------------------------------------------------------------- | 425 // ----------------------------------------------------------------------------- |
437 | 426 |
438 } // namespace base | 427 } // namespace base |
OLD | NEW |