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