xref: /aosp_15_r20/external/webrtc/rtc_base/race_checker.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 #include "rtc_base/race_checker.h"
12 
13 namespace rtc {
14 
RaceChecker()15 RaceChecker::RaceChecker() {}
16 
17 // Note that the implementation here is in itself racy, but we pretend it does
18 // not matter because we want this useful in release builds without having to
19 // pay the cost of using atomics. A race hitting the race checker is likely to
20 // cause access_count_ to diverge from zero and therefore cause the ThreadRef
21 // comparison to fail, signaling a race, although it may not be in the exact
22 // spot where a race *first* appeared in the code we're trying to protect. There
23 // is also a chance that an actual race is missed, however the probability of
24 // that has been considered small enough to be an acceptable trade off.
Acquire() const25 bool RaceChecker::Acquire() const {
26   const PlatformThreadRef current_thread = CurrentThreadRef();
27   // Set new accessing thread if this is a new use.
28   const int current_access_count = access_count_;
29   access_count_ = access_count_ + 1;
30   if (current_access_count == 0)
31     accessing_thread_ = current_thread;
32   // If this is being used concurrently this check will fail for the second
33   // thread entering since it won't set the thread. Recursive use of checked
34   // methods are OK since the accessing thread remains the same.
35   const PlatformThreadRef accessing_thread = accessing_thread_;
36   return IsThreadRefEqual(accessing_thread, current_thread);
37 }
38 
Release() const39 void RaceChecker::Release() const {
40   access_count_ = access_count_ - 1;
41 }
42 
43 namespace internal {
RaceCheckerScope(const RaceChecker * race_checker)44 RaceCheckerScope::RaceCheckerScope(const RaceChecker* race_checker)
45     : race_checker_(race_checker), race_check_ok_(race_checker->Acquire()) {}
46 
RaceDetected() const47 bool RaceCheckerScope::RaceDetected() const {
48   return !race_check_ok_;
49 }
50 
~RaceCheckerScope()51 RaceCheckerScope::~RaceCheckerScope() {
52   race_checker_->Release();
53 }
54 
55 }  // namespace internal
56 }  // namespace rtc
57