blob: 12f6a7dca2010b760756142300eb71d2eb4e33d9 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef RTC_BASE_EVENT_H_
12#define RTC_BASE_EVENT_H_
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000013
Markus Handell1d5be492022-08-18 13:49:09 +000014#include "api/units/time_delta.h"
Tommi2fc37572022-10-24 09:22:16 +020015
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020016#if defined(WEBRTC_WIN)
Patrik Höglunda8005cf2017-12-13 16:05:42 +010017#include <windows.h>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020018#elif defined(WEBRTC_POSIX)
19#include <pthread.h>
20#else
21#error "Must define either WEBRTC_WIN or WEBRTC_POSIX."
22#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000023
Tommi2fc37572022-10-24 09:22:16 +020024#include "rtc_base/synchronization/yield_policy.h"
25
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020026namespace rtc {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000027
Tommi2fc37572022-10-24 09:22:16 +020028// 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
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020056class Event {
57 public:
Markus Handell1d5be492022-08-18 13:49:09 +000058 // TODO(bugs.webrtc.org/14366): Consider removing this redundant alias.
59 static constexpr webrtc::TimeDelta kForever =
60 webrtc::TimeDelta::PlusInfinity();
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020061
Niels Möllerc572ff32018-11-07 08:43:50 +010062 Event();
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020063 Event(bool manual_reset, bool initially_signaled);
Niels Möllerc572ff32018-11-07 08:43:50 +010064 Event(const Event&) = delete;
65 Event& operator=(const Event&) = delete;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020066 ~Event();
67
68 void Set();
69 void Reset();
70
Karl Wibergfc47c862019-04-11 10:31:24 +020071 // Waits for the event to become signaled, but logs a warning if it takes more
Markus Handell1d5be492022-08-18 13:49:09 +000072 // 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`.
Karl Wibergfc47c862019-04-11 10:31:24 +020078 //
79 // Returns true if the event was signaled, false if there was a timeout or
80 // some other error.
Markus Handell1d5be492022-08-18 13:49:09 +000081 bool Wait(webrtc::TimeDelta give_up_after, webrtc::TimeDelta warn_after);
Karl Wibergfc47c862019-04-11 10:31:24 +020082
83 // Waits with the given timeout and a reasonable default warning timeout.
Markus Handell0cd0dd32022-08-19 12:42:31 +000084 bool Wait(webrtc::TimeDelta give_up_after) {
85 return Wait(give_up_after, give_up_after.IsPlusInfinity()
86 ? webrtc::TimeDelta::Seconds(3)
87 : kForever);
Karl Wibergfc47c862019-04-11 10:31:24 +020088 }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020089
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
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020099};
100
François Doray8ea977d2019-03-22 13:01:54 -0400101// These classes are provided for compatibility with Chromium.
Tommi39d93da2018-01-17 12:31:13 +0100102// 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.
François Doray8ea977d2019-03-22 13:01:54 -0400107// For further information, please see the
108// ScopedAllowBaseSyncPrimitives(ForTesting) classes in Chromium.
Tommi39d93da2018-01-17 12:31:13 +0100109class ScopedAllowBaseSyncPrimitives {
110 public:
111 ScopedAllowBaseSyncPrimitives() {}
112 ~ScopedAllowBaseSyncPrimitives() {}
113};
114
François Doray8ea977d2019-03-22 13:01:54 -0400115class ScopedAllowBaseSyncPrimitivesForTesting {
116 public:
117 ScopedAllowBaseSyncPrimitivesForTesting() {}
118 ~ScopedAllowBaseSyncPrimitivesForTesting() {}
119};
120
Tommi2fc37572022-10-24 09:22:16 +0200121#if RTC_DCHECK_IS_ON
122class ScopedDisallowWait {
123 public:
124 ScopedDisallowWait() = default;
125
126 private:
127 class DisallowYieldHandler : public YieldInterface {
128 public:
129 void YieldExecution() override { RTC_DCHECK_NOTREACHED(); }
130 } handler_;
131 rtc::ScopedYieldPolicy policy{&handler_};
132};
133#endif
134
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200135} // namespace rtc
136
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200137#endif // RTC_BASE_EVENT_H_