xref: /aosp_15_r20/external/webrtc/rtc_base/event.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef RTC_BASE_EVENT_H_
12 #define RTC_BASE_EVENT_H_
13 
14 #include "api/units/time_delta.h"
15 
16 #if defined(WEBRTC_WIN)
17 #include <windows.h>
18 #elif defined(WEBRTC_POSIX)
19 #include <pthread.h>
20 #else
21 #error "Must define either WEBRTC_WIN or WEBRTC_POSIX."
22 #endif
23 
24 #include "rtc_base/synchronization/yield_policy.h"
25 
26 namespace rtc {
27 
28 // RTC_DISALLOW_WAIT() utility
29 //
30 // Sets a stack-scoped flag that disallows use of `rtc::Event::Wait` by means
31 // of raising a DCHECK when a call to `rtc::Event::Wait()` is made..
32 // This is useful to guard synchronization-free scopes against regressions.
33 //
34 // Example of what this would catch (`ScopeToProtect` calls `Foo`):
35 //
36 //  void Foo(TaskQueue* tq) {
37 //    Event event;
38 //    tq->PostTask([&event]() {
39 //      event.Set();
40 //    });
41 //    event.Wait(Event::kForever);  // <- Will trigger a DCHECK.
42 //  }
43 //
44 //  void ScopeToProtect() {
45 //    TaskQueue* tq = GetSomeTaskQueue();
46 //    RTC_DISALLOW_WAIT();  // Policy takes effect.
47 //    Foo(tq);
48 //  }
49 //
50 #if RTC_DCHECK_IS_ON
51 #define RTC_DISALLOW_WAIT() ScopedDisallowWait disallow_wait_##__LINE__
52 #else
53 #define RTC_DISALLOW_WAIT()
54 #endif
55 
56 class Event {
57  public:
58   // TODO(bugs.webrtc.org/14366): Consider removing this redundant alias.
59   static constexpr webrtc::TimeDelta kForever =
60       webrtc::TimeDelta::PlusInfinity();
61 
62   Event();
63   Event(bool manual_reset, bool initially_signaled);
64   Event(const Event&) = delete;
65   Event& operator=(const Event&) = delete;
66   ~Event();
67 
68   void Set();
69   void Reset();
70 
71   // Waits for the event to become signaled, but logs a warning if it takes more
72   // than `warn_after`, and gives up completely if it takes more than
73   // `give_up_after`. (If `warn_after >= give_up_after`, no warning will be
74   // logged.) Either or both may be `kForever`, which means wait indefinitely.
75   //
76   // Care is taken so that the underlying OS wait call isn't requested to sleep
77   // shorter than `give_up_after`.
78   //
79   // Returns true if the event was signaled, false if there was a timeout or
80   // some other error.
81   bool Wait(webrtc::TimeDelta give_up_after, webrtc::TimeDelta warn_after);
82 
83   // Waits with the given timeout and a reasonable default warning timeout.
Wait(webrtc::TimeDelta give_up_after)84   bool Wait(webrtc::TimeDelta give_up_after) {
85     return Wait(give_up_after, give_up_after.IsPlusInfinity()
86                                    ? webrtc::TimeDelta::Seconds(3)
87                                    : kForever);
88   }
89 
90  private:
91 #if defined(WEBRTC_WIN)
92   HANDLE event_handle_;
93 #elif defined(WEBRTC_POSIX)
94   pthread_mutex_t event_mutex_;
95   pthread_cond_t event_cond_;
96   const bool is_manual_reset_;
97   bool event_status_;
98 #endif
99 };
100 
101 // These classes are provided for compatibility with Chromium.
102 // The rtc::Event implementation is overriden inside of Chromium for the
103 // purposes of detecting when threads are blocked that shouldn't be as well as
104 // to use the more accurate event implementation that's there than is provided
105 // by default on some platforms (e.g. Windows).
106 // When building with standalone WebRTC, this class is a noop.
107 // For further information, please see the
108 // ScopedAllowBaseSyncPrimitives(ForTesting) classes in Chromium.
109 class ScopedAllowBaseSyncPrimitives {
110  public:
ScopedAllowBaseSyncPrimitives()111   ScopedAllowBaseSyncPrimitives() {}
~ScopedAllowBaseSyncPrimitives()112   ~ScopedAllowBaseSyncPrimitives() {}
113 };
114 
115 class ScopedAllowBaseSyncPrimitivesForTesting {
116  public:
ScopedAllowBaseSyncPrimitivesForTesting()117   ScopedAllowBaseSyncPrimitivesForTesting() {}
~ScopedAllowBaseSyncPrimitivesForTesting()118   ~ScopedAllowBaseSyncPrimitivesForTesting() {}
119 };
120 
121 #if RTC_DCHECK_IS_ON
122 class ScopedDisallowWait {
123  public:
124   ScopedDisallowWait() = default;
125 
126  private:
127   class DisallowYieldHandler : public YieldInterface {
128    public:
YieldExecution()129     void YieldExecution() override { RTC_DCHECK_NOTREACHED(); }
130   } handler_;
131   rtc::ScopedYieldPolicy policy{&handler_};
132 };
133 #endif
134 
135 }  // namespace rtc
136 
137 #endif  // RTC_BASE_EVENT_H_
138