blob: 73567e98d8ac07db766e81c897db34c0d3ad8dec [file] [log] [blame]
Peter Boström02bafc62016-07-01 12:45:15 +02001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef RTC_BASE_RACE_CHECKER_H_
12#define RTC_BASE_RACE_CHECKER_H_
Peter Boström02bafc62016-07-01 12:45:15 +020013
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "rtc_base/checks.h"
15#include "rtc_base/platform_thread.h"
16#include "rtc_base/thread_annotations.h"
Peter Boström02bafc62016-07-01 12:45:15 +020017
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020018namespace rtc {
19
20namespace internal {
21class 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.
danilchap3c6abd22017-09-06 05:46:29 -070026class RTC_LOCKABLE RaceChecker {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020027 public:
28 friend class internal::RaceCheckerScope;
29 RaceChecker();
30
31 private:
danilchap3c6abd22017-09-06 05:46:29 -070032 bool Acquire() const RTC_EXCLUSIVE_LOCK_FUNCTION();
33 void Release() const RTC_UNLOCK_FUNCTION();
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020034
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
40namespace internal {
danilchap3c6abd22017-09-06 05:46:29 -070041class RTC_SCOPED_LOCKABLE RaceCheckerScope {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020042 public:
43 explicit RaceCheckerScope(const RaceChecker* race_checker)
danilchap3c6abd22017-09-06 05:46:29 -070044 RTC_EXCLUSIVE_LOCK_FUNCTION(race_checker);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020045
46 bool RaceDetected() const;
danilchap3c6abd22017-09-06 05:46:29 -070047 ~RaceCheckerScope() RTC_UNLOCK_FUNCTION();
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020048
49 private:
50 const RaceChecker* const race_checker_;
51 const bool race_check_ok_;
52};
53
danilchap3c6abd22017-09-06 05:46:29 -070054class RTC_SCOPED_LOCKABLE RaceCheckerScopeDoNothing {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020055 public:
56 explicit RaceCheckerScopeDoNothing(const RaceChecker* race_checker)
danilchap3c6abd22017-09-06 05:46:29 -070057 RTC_EXCLUSIVE_LOCK_FUNCTION(race_checker) {}
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020058
danilchap3c6abd22017-09-06 05:46:29 -070059 ~RaceCheckerScopeDoNothing() RTC_UNLOCK_FUNCTION() {}
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020060};
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
Peter Boström02bafc62016-07-01 12:45:15 +020077
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020078#endif // RTC_BASE_RACE_CHECKER_H_