1 // Copyright 2023 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // This file is a clone of "v8/src/base/platform/semaphore.cc" in v8. 6 // Keep in sync, especially when fixing bugs. 7 8 // Copyright 2013 the V8 project authors. All rights reserved. 9 // Use of this source code is governed by a BSD-style license that can be 10 // found in the LICENSE file. 11 12 #include "base/task/thread_pool/semaphore.h" 13 14 #include "base/synchronization/condition_variable.h" 15 #include "base/synchronization/lock.h" 16 #include "base/time/time.h" 17 18 namespace base { 19 namespace internal { 20 Semaphore(int count)21Semaphore::Semaphore(int count) : native_handle_(count) { 22 native_handle().condition_var.declare_only_used_while_idle(); 23 } 24 25 Semaphore::~Semaphore() = default; 26 Signal()27void Semaphore::Signal() { 28 AutoLock lock(native_handle().lock); 29 ++native_handle().value; 30 native_handle().condition_var.Signal(); 31 } 32 Wait()33void Semaphore::Wait() { 34 AutoLock lock(native_handle().lock); 35 while (native_handle().value < 1) { 36 native_handle().condition_var.Wait(); 37 } 38 --native_handle().value; 39 } 40 TimedWait(TimeDelta timeout)41bool Semaphore::TimedWait(TimeDelta timeout) { 42 AutoLock lock(native_handle().lock); 43 const TimeTicks before_wait = TimeTicks::Now(); 44 const TimeTicks wait_end = before_wait + timeout; 45 TimeDelta remaining_sleep = timeout; 46 while (native_handle().value < 1) { 47 native_handle().condition_var.TimedWait(remaining_sleep); 48 49 // Since condition variables experience spurious wakeups, adjust the 50 // remaining wait time to prepare for sleeping once more, and return if a 51 // timeout occurred. 52 remaining_sleep = wait_end - TimeTicks::Now(); 53 if (!remaining_sleep.is_positive()) { 54 return false; 55 } 56 } 57 // In this case, the lock has been successfully acquired with a positive 58 // semaphore value. 59 --native_handle().value; 60 return true; 61 } 62 63 } // namespace internal 64 } // namespace base 65