summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/rtc_base/race_checker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/rtc_base/race_checker.cc')
-rw-r--r--third_party/libwebrtc/rtc_base/race_checker.cc56
1 files changed, 56 insertions, 0 deletions
diff --git a/third_party/libwebrtc/rtc_base/race_checker.cc b/third_party/libwebrtc/rtc_base/race_checker.cc
new file mode 100644
index 0000000000..f0d4e868c2
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/race_checker.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/race_checker.h"
+
+namespace rtc {
+
+RaceChecker::RaceChecker() {}
+
+// Note that the implementation here is in itself racy, but we pretend it does
+// not matter because we want this useful in release builds without having to
+// pay the cost of using atomics. A race hitting the race checker is likely to
+// cause access_count_ to diverge from zero and therefore cause the ThreadRef
+// comparison to fail, signaling a race, although it may not be in the exact
+// spot where a race *first* appeared in the code we're trying to protect. There
+// is also a chance that an actual race is missed, however the probability of
+// that has been considered small enough to be an acceptable trade off.
+bool RaceChecker::Acquire() const {
+ const PlatformThreadRef current_thread = CurrentThreadRef();
+ // Set new accessing thread if this is a new use.
+ const int current_access_count = access_count_;
+ access_count_ = access_count_ + 1;
+ if (current_access_count == 0)
+ accessing_thread_ = current_thread;
+ // If this is being used concurrently this check will fail for the second
+ // thread entering since it won't set the thread. Recursive use of checked
+ // methods are OK since the accessing thread remains the same.
+ const PlatformThreadRef accessing_thread = accessing_thread_;
+ return IsThreadRefEqual(accessing_thread, current_thread);
+}
+
+void RaceChecker::Release() const {
+ access_count_ = access_count_ - 1;
+}
+
+namespace internal {
+RaceCheckerScope::RaceCheckerScope(const RaceChecker* race_checker)
+ : race_checker_(race_checker), race_check_ok_(race_checker->Acquire()) {}
+
+bool RaceCheckerScope::RaceDetected() const {
+ return !race_check_ok_;
+}
+
+RaceCheckerScope::~RaceCheckerScope() {
+ race_checker_->Release();
+}
+
+} // namespace internal
+} // namespace rtc