1 /* 2 * Copyright (c) 2016 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_RACE_CHECKER_H_ 12 #define RTC_BASE_RACE_CHECKER_H_ 13 14 #include "rtc_base/checks.h" 15 #include "rtc_base/platform_thread_types.h" 16 #include "rtc_base/thread_annotations.h" 17 18 namespace rtc { 19 20 namespace internal { 21 class RaceCheckerScope; 22 } // namespace internal 23 24 // Best-effort race-checking implementation. This primitive uses no 25 // synchronization at all to be as-fast-as-possible in the non-racy case. 26 class RTC_LOCKABLE RaceChecker { 27 public: 28 friend class internal::RaceCheckerScope; 29 RaceChecker(); 30 31 private: 32 bool Acquire() const RTC_EXCLUSIVE_LOCK_FUNCTION(); 33 void Release() const RTC_UNLOCK_FUNCTION(); 34 35 // Volatile to prevent code being optimized away in Acquire()/Release(). 36 mutable volatile int access_count_ = 0; 37 mutable volatile PlatformThreadRef accessing_thread_; 38 }; 39 40 namespace internal { 41 class RTC_SCOPED_LOCKABLE RaceCheckerScope { 42 public: 43 explicit RaceCheckerScope(const RaceChecker* race_checker) 44 RTC_EXCLUSIVE_LOCK_FUNCTION(race_checker); 45 46 bool RaceDetected() const; 47 ~RaceCheckerScope() RTC_UNLOCK_FUNCTION(); 48 49 private: 50 const RaceChecker* const race_checker_; 51 const bool race_check_ok_; 52 }; 53 54 class RTC_SCOPED_LOCKABLE RaceCheckerScopeDoNothing { 55 public: RaceCheckerScopeDoNothing(const RaceChecker * race_checker)56 explicit RaceCheckerScopeDoNothing(const RaceChecker* race_checker) 57 RTC_EXCLUSIVE_LOCK_FUNCTION(race_checker) {} 58 RTC_UNLOCK_FUNCTION()59 ~RaceCheckerScopeDoNothing() RTC_UNLOCK_FUNCTION() {} 60 }; 61 62 } // namespace internal 63 } // namespace rtc 64 65 #define RTC_CHECK_RUNS_SERIALIZED(x) \ 66 rtc::internal::RaceCheckerScope race_checker(x); \ 67 RTC_CHECK(!race_checker.RaceDetected()) 68 69 #if RTC_DCHECK_IS_ON 70 #define RTC_DCHECK_RUNS_SERIALIZED(x) \ 71 rtc::internal::RaceCheckerScope race_checker(x); \ 72 RTC_DCHECK(!race_checker.RaceDetected()) 73 #else 74 #define RTC_DCHECK_RUNS_SERIALIZED(x) \ 75 rtc::internal::RaceCheckerScopeDoNothing race_checker(x) 76 #endif 77 78 #endif // RTC_BASE_RACE_CHECKER_H_ 79