xref: /aosp_15_r20/external/cronet/base/task/thread_pool/semaphore/semaphore_default.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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)21 Semaphore::Semaphore(int count) : native_handle_(count) {
22   native_handle().condition_var.declare_only_used_while_idle();
23 }
24 
25 Semaphore::~Semaphore() = default;
26 
Signal()27 void Semaphore::Signal() {
28   AutoLock lock(native_handle().lock);
29   ++native_handle().value;
30   native_handle().condition_var.Signal();
31 }
32 
Wait()33 void 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)41 bool 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