| Index: base/synchronization/waitable_event_posix.cc
|
| diff --git a/base/synchronization/waitable_event_posix.cc b/base/synchronization/waitable_event_posix.cc
|
| index 846fa06700e1dcb1c1c5976eb2397643c0698759..5dfff468ad6acb0f2c81df98bcc31564f7029506 100644
|
| --- a/base/synchronization/waitable_event_posix.cc
|
| +++ b/base/synchronization/waitable_event_posix.cc
|
| @@ -5,7 +5,6 @@
|
| #include <stddef.h>
|
|
|
| #include <algorithm>
|
| -#include <limits>
|
| #include <vector>
|
|
|
| #include "base/debug/activity_tracker.h"
|
| @@ -267,10 +266,12 @@
|
| SyncWaiter sw;
|
|
|
| const size_t r = EnqueueMany(&waitables[0], count, &sw);
|
| - if (r < count) {
|
| + if (r) {
|
| // One of the events is already signaled. The SyncWaiter has not been
|
| - // enqueued anywhere.
|
| - return waitables[r].second;
|
| + // enqueued anywhere. EnqueueMany returns the count of remaining waitables
|
| + // when the signaled one was seen, so the index of the signaled event is
|
| + // @count - @r.
|
| + return waitables[count - r].second;
|
| }
|
|
|
| // At this point, we hold the locks on all the WaitableEvents and we have
|
| @@ -318,50 +319,38 @@
|
| }
|
|
|
| // -----------------------------------------------------------------------------
|
| -// If return value == count:
|
| +// If return value == 0:
|
| // The locks of the WaitableEvents have been taken in order and the Waiter has
|
| // been enqueued in the wait-list of each. None of the WaitableEvents are
|
| // currently signaled
|
| // else:
|
| // None of the WaitableEvent locks are held. The Waiter has not been enqueued
|
| -// in any of them and the return value is the index of the WaitableEvent which
|
| -// was signaled with the lowest input index from the original WaitMany call.
|
| +// in any of them and the return value is the index of the first WaitableEvent
|
| +// which was signaled, from the end of the array.
|
| // -----------------------------------------------------------------------------
|
| // static
|
| -size_t WaitableEvent::EnqueueMany(std::pair<WaitableEvent*, size_t>* waitables,
|
| - size_t count,
|
| - Waiter* waiter) {
|
| - size_t winner = count;
|
| - size_t winner_index = count;
|
| - for (size_t i = 0; i < count; ++i) {
|
| - auto& kernel = waitables[i].first->kernel_;
|
| - kernel->lock_.Acquire();
|
| - if (kernel->signaled_ && waitables[i].second < winner) {
|
| - winner = waitables[i].second;
|
| - winner_index = i;
|
| - }
|
| - }
|
| -
|
| - // No events signaled. All locks acquired. Enqueue the Waiter on all of them
|
| - // and return.
|
| - if (winner == count) {
|
| - for (size_t i = 0; i < count; ++i)
|
| - waitables[i].first->Enqueue(waiter);
|
| - return count;
|
| - }
|
| -
|
| - // Unlock in reverse order and possibly clear the chosen winner's signal
|
| - // before returning its index.
|
| - for (auto* w = waitables + count - 1; w >= waitables; --w) {
|
| - auto& kernel = w->first->kernel_;
|
| - if (w->second == winner) {
|
| - if (!kernel->manual_reset_)
|
| - kernel->signaled_ = false;
|
| - }
|
| - kernel->lock_.Release();
|
| - }
|
| -
|
| - return winner_index;
|
| +size_t WaitableEvent::EnqueueMany
|
| + (std::pair<WaitableEvent*, size_t>* waitables,
|
| + size_t count, Waiter* waiter) {
|
| + if (!count)
|
| + return 0;
|
| +
|
| + waitables[0].first->kernel_->lock_.Acquire();
|
| + if (waitables[0].first->kernel_->signaled_) {
|
| + if (!waitables[0].first->kernel_->manual_reset_)
|
| + waitables[0].first->kernel_->signaled_ = false;
|
| + waitables[0].first->kernel_->lock_.Release();
|
| + return count;
|
| + }
|
| +
|
| + const size_t r = EnqueueMany(waitables + 1, count - 1, waiter);
|
| + if (r) {
|
| + waitables[0].first->kernel_->lock_.Release();
|
| + } else {
|
| + waitables[0].first->Enqueue(waiter);
|
| + }
|
| +
|
| + return r;
|
| }
|
|
|
| // -----------------------------------------------------------------------------
|
|
|