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.h" 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 #ifndef BASE_TASK_THREAD_POOL_SEMAPHORE_H_ 13 #define BASE_TASK_THREAD_POOL_SEMAPHORE_H_ 14 15 #include "base/base_export.h" 16 #include "build/build_config.h" 17 18 #if BUILDFLAG(IS_WIN) 19 #include <windows.h> 20 #elif BUILDFLAG(IS_MAC) || BUILDFLAG(IS_IOS) 21 #include <dispatch/dispatch.h> 22 #elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL) || BUILDFLAG(IS_FUCHSIA) 23 #include <semaphore.h> 24 #else 25 #include "base/synchronization/condition_variable.h" 26 #include "base/synchronization/lock.h" 27 #endif 28 29 namespace base { 30 class TimeDelta; 31 namespace internal { 32 33 // ---------------------------------------------------------------------------- 34 // Semaphore 35 // 36 // A semaphore object is a synchronization object that maintains a count. The 37 // count is decremented each time a thread completes a wait for the semaphore 38 // object and incremented each time a thread signals the semaphore. When the 39 // count reaches zero, threads waiting for the semaphore blocks until the 40 // count becomes non-zero. 41 42 class BASE_EXPORT Semaphore { 43 public: 44 explicit Semaphore(int count); 45 Semaphore(const Semaphore&) = delete; 46 Semaphore& operator=(const Semaphore&) = delete; 47 ~Semaphore(); 48 49 // Increments the semaphore counter. 50 void Signal(); 51 52 // Decrements the semaphore counter if it is positive, or blocks until it 53 // becomes positive and then decrements the counter. 54 // 55 // Wait's return "happens-after" |Signal| has completed. This means that it's 56 // safe for a WaitableEvent to synchronise its own destruction, like this: 57 // 58 // Semaphore* s = new Semaphore; 59 // SendToOtherThread(s); 60 // s->Wait(); 61 // delete s; 62 void Wait(); 63 64 // Like Wait() but returns after `timeout` time has passed. If the call times 65 // out, the return value is false and the counter is unchanged. Otherwise the 66 // semaphore counter is decremented and true is returned. 67 // 68 // Note: Timeout is checked to be no more than DWORD-size (24 days). 69 [[nodiscard]] bool TimedWait(TimeDelta timeout); 70 71 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_IOS) 72 using NativeHandle = dispatch_semaphore_t; 73 #elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL) || BUILDFLAG(IS_FUCHSIA) 74 using NativeHandle = sem_t; 75 #elif BUILDFLAG(IS_WIN) 76 using NativeHandle = HANDLE; 77 #else // default implementation 78 using NativeHandle = struct DefaultSemaphore { 79 private: 80 friend class Semaphore; DefaultSemaphoreDefaultSemaphore81 DefaultSemaphore(int count) : condition_var(&lock), value(count) {} 82 83 Lock lock; 84 ConditionVariable condition_var GUARDED_BY(lock); 85 int value GUARDED_BY(lock); 86 }; 87 #endif 88 89 private: native_handle()90 NativeHandle& native_handle() { return native_handle_; } native_handle()91 const NativeHandle& native_handle() const { return native_handle_; } 92 93 NativeHandle native_handle_; 94 }; 95 96 } // namespace internal 97 } // namespace base 98 99 #endif // BASE_TASK_THREAD_POOL_SEMAPHORE_H_ 100