Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(511)

Side by Side Diff: base/synchronization/waitable_event_posix.cc

Issue 2761993004: Revert of Ensure consistent return ordering in base::WaitableEvent::WaitMany (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/synchronization/waitable_event.h ('k') | base/synchronization/waitable_event_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « base/synchronization/waitable_event.h ('k') | base/synchronization/waitable_event_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698