1 // Copyright 2024 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 #ifndef BASE_SYNCHRONIZATION_CANCELABLE_EVENT_H_ 6 #define BASE_SYNCHRONIZATION_CANCELABLE_EVENT_H_ 7 8 #include "base/base_export.h" 9 #include "base/compiler_specific.h" 10 #include "base/time/time.h" 11 12 #if BUILDFLAG(IS_WIN) 13 #include <windows.h> 14 #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) 15 #include <semaphore.h> 16 #else 17 #include "base/synchronization/waitable_event.h" 18 #endif 19 20 namespace base { 21 22 // A CancelableEvent functions as a 0-1 semaphore. It does not start signaled. 23 // It must not be signaled twice. 24 // 25 // Cancel() can only succeed on Windows, Linux, ChromeOS, and Android. 26 class BASE_EXPORT CancelableEvent { 27 public: 28 CancelableEvent(); 29 ~CancelableEvent(); 30 31 // Puts the event in the signaled state. Causes the thread blocked on 32 // Wait() (if there is one) to be woken up. 33 void Signal(); 34 35 // Cancels a signal, if possible. Returns whether canceling a signal was 36 // successful or not. On success, no thread will wake up. On failure, either 37 // no signal was sent in the first place, or a waiting thread already consumed 38 // the signal. 39 [[nodiscard]] bool Cancel(); 40 41 // Waits for this event to be Signal()ed until `wait_delta` has elapsed 42 // (real-time; ignores time overrides). Returns true if Signal() occurs or 43 // false if `wait_delta` elapses without a Signal(). 44 // 45 // TimedWait() can synchronise its own destruction. 46 NOT_TAIL_CALLED bool TimedWait(TimeDelta wait_delta); 47 Wait()48 void Wait() { TimedWait(TimeDelta::Max()); } 49 50 #if BUILDFLAG(IS_WIN) 51 using NativeHandle = HANDLE; 52 #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) 53 using NativeHandle = sem_t; 54 #else 55 using NativeHandle = WaitableEvent; 56 #endif 57 58 // Declares that this CancelableEvent will only ever be used by a thread that 59 // is idle at the bottom of its stack and waiting for work (in particular, it 60 // is not synchronously waiting on this event before resuming ongoing 61 // work). This is useful to avoid telling base-internals that this thread is 62 // "blocked" when it's merely idle and ready to do work. As such, this is only 63 // expected to be used by thread and thread pool impls. In such cases 64 // wakeup.flow events aren't emitted on `Signal`/`Wait`, because threading 65 // implementations are responsible for emitting the cause of their wakeup from 66 // idle. declare_only_used_while_idle()67 void declare_only_used_while_idle() { only_used_while_idle_ = true; } 68 69 private: 70 void SignalImpl(); 71 bool CancelImpl(); 72 bool TimedWaitImpl(TimeDelta wait_delta); 73 74 bool only_used_while_idle_ = false; 75 76 NativeHandle native_handle_; 77 }; 78 79 } // namespace base 80 81 #endif // BASE_SYNCHRONIZATION_CANCELABLE_EVENT_H_ 82