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 <windows.h>
15
16 #include "base/check.h"
17 #include "base/time/time.h"
18
19 namespace base {
20 namespace internal {
21
Semaphore(int count)22 Semaphore::Semaphore(int count) {
23 CHECK_GE(count, 0);
24 native_handle_ = ::CreateSemaphoreA(
25 nullptr, count, std::numeric_limits<LONG>::max(), nullptr);
26 CHECK(!!native_handle_);
27 }
28
~Semaphore()29 Semaphore::~Semaphore() {
30 const bool result = CloseHandle(native_handle_);
31 CHECK(result);
32 }
33
Signal()34 void Semaphore::Signal() {
35 const bool result = ReleaseSemaphore(native_handle_, 1, nullptr);
36 CHECK(result);
37 }
38
Wait()39 void Semaphore::Wait() {
40 const DWORD result = WaitForSingleObject(native_handle_, INFINITE);
41 CHECK_EQ(result, WAIT_OBJECT_0);
42 }
43
TimedWait(TimeDelta timeout)44 bool Semaphore::TimedWait(TimeDelta timeout) {
45 const DWORD wait_ms = saturated_cast<DWORD>(timeout.InMilliseconds());
46 const TimeTicks start = TimeTicks::Now();
47 DWORD result;
48 // WaitForSingleObject has been shown to experience spurious wakeups (on the
49 // order of 10ms before when it was supposed to wake up), so retry until at
50 // least |timeout| has passed.
51 do {
52 result = WaitForSingleObject(native_handle_, wait_ms);
53 if (result == WAIT_OBJECT_0) {
54 return true;
55 }
56 } while (TimeTicks::Now() <= start + timeout);
57 CHECK_EQ(result, static_cast<DWORD>(WAIT_TIMEOUT));
58 return false;
59 }
60
61 } // namespace internal
62 } // namespace base
63