blob: a6ba771f90c212b9b5ef64253b5d78501b2f2656 [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
11#ifndef WEBRTC_BASE_RACE_CHECKER_H_
12#define WEBRTC_BASE_RACE_CHECKER_H_
13
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020014#include "webrtc/base/checks.h"
15#include "webrtc/base/platform_thread.h"
16#include "webrtc/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.
26class LOCKABLE RaceChecker {
27 public:
28 friend class internal::RaceCheckerScope;
29 RaceChecker();
30
31 private:
32 bool Acquire() const EXCLUSIVE_LOCK_FUNCTION();
33 void Release() const 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
40namespace internal {
41class SCOPED_LOCKABLE RaceCheckerScope {
42 public:
43 explicit RaceCheckerScope(const RaceChecker* race_checker)
44 EXCLUSIVE_LOCK_FUNCTION(race_checker);
45
46 bool RaceDetected() const;
47 ~RaceCheckerScope() UNLOCK_FUNCTION();
48
49 private:
50 const RaceChecker* const race_checker_;
51 const bool race_check_ok_;
52};
53
54class SCOPED_LOCKABLE RaceCheckerScopeDoNothing {
55 public:
56 explicit RaceCheckerScopeDoNothing(const RaceChecker* race_checker)
57 EXCLUSIVE_LOCK_FUNCTION(race_checker) {}
58
59 ~RaceCheckerScopeDoNothing() 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
Peter Boström02bafc62016-07-01 12:45:15 +020077
78#endif // WEBRTC_BASE_RACE_CHECKER_H_