• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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