blob: 1b296dadd9c095786a0802a388d5a913bc84deae [file] [log] [blame]
danilchap01404082016-10-24 06:07:25 -07001/*
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#include "rtc_base/thread_annotations.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "test/gtest.h"
danilchap01404082016-10-24 06:07:25 -070014
15namespace {
16
danilchap5301e3c2017-09-06 04:10:21 -070017class RTC_LOCKABLE Lock {
danilchap01404082016-10-24 06:07:25 -070018 public:
danilchap5301e3c2017-09-06 04:10:21 -070019 void EnterWrite() const RTC_EXCLUSIVE_LOCK_FUNCTION() {}
20 void EnterRead() const RTC_SHARED_LOCK_FUNCTION() {}
21 bool TryEnterWrite() const RTC_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
22 return true;
23 }
24 bool TryEnterRead() const RTC_SHARED_TRYLOCK_FUNCTION(true) { return true; }
25 void Leave() const RTC_UNLOCK_FUNCTION() {}
danilchap01404082016-10-24 06:07:25 -070026};
27
danilchap5301e3c2017-09-06 04:10:21 -070028class RTC_SCOPED_LOCKABLE ScopeLock {
danilchap01404082016-10-24 06:07:25 -070029 public:
danilchap5301e3c2017-09-06 04:10:21 -070030 explicit ScopeLock(const Lock& lock) RTC_EXCLUSIVE_LOCK_FUNCTION(lock) {}
31 ~ScopeLock() RTC_UNLOCK_FUNCTION() {}
danilchap01404082016-10-24 06:07:25 -070032};
33
34class ThreadSafe {
35 public:
Yves Gerey665174f2018-06-19 15:03:05 +020036 ThreadSafe() { pt_protected_by_lock_ = new int; }
danilchap01404082016-10-24 06:07:25 -070037
Yves Gerey665174f2018-06-19 15:03:05 +020038 ~ThreadSafe() { delete pt_protected_by_lock_; }
danilchap01404082016-10-24 06:07:25 -070039
40 void LockInOrder() {
Danil Chapovalov37651992017-11-01 10:52:09 +010041 beforelock_.EnterWrite();
danilchap01404082016-10-24 06:07:25 -070042 lock_.EnterWrite();
43 pt_lock_.EnterWrite();
44
45 pt_lock_.Leave();
46 lock_.Leave();
Danil Chapovalov37651992017-11-01 10:52:09 +010047 beforelock_.Leave();
danilchap01404082016-10-24 06:07:25 -070048 }
49
Danil Chapovalov37651992017-11-01 10:52:09 +010050 void UnprotectedFunction() RTC_LOCKS_EXCLUDED(lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -070051 // Can access unprotected Value.
52 unprotected_ = 15;
53 // Can access pointers themself, but not data they point to.
54 int* tmp = pt_protected_by_lock_;
Danil Chapovalov37651992017-11-01 10:52:09 +010055 pt_protected_by_lock_ = tmp;
danilchap01404082016-10-24 06:07:25 -070056 }
57
58 void ReadProtected() {
59 lock_.EnterRead();
danilchap01404082016-10-24 06:07:25 -070060 unprotected_ = protected_by_lock_;
61 lock_.Leave();
62
63 if (pt_lock_.TryEnterRead()) {
danilchap01404082016-10-24 06:07:25 -070064 unprotected_ = *pt_protected_by_lock_;
65 pt_lock_.Leave();
66 }
danilchap01404082016-10-24 06:07:25 -070067 }
68
69 void WriteProtected() {
70 lock_.EnterWrite();
danilchap01404082016-10-24 06:07:25 -070071 protected_by_lock_ = unprotected_;
72 lock_.Leave();
73
74 if (pt_lock_.TryEnterWrite()) {
danilchap01404082016-10-24 06:07:25 -070075 *pt_protected_by_lock_ = unprotected_;
76 pt_lock_.Leave();
77 }
danilchap01404082016-10-24 06:07:25 -070078 }
79
80 void CallReadProtectedFunction() {
81 lock_.EnterRead();
82 pt_lock_.EnterRead();
83 ReadProtectedFunction();
84 pt_lock_.Leave();
85 lock_.Leave();
86 }
87
88 void CallWriteProtectedFunction() {
89 ScopeLock scope_lock(GetLock());
90 ScopeLock pt_scope_lock(pt_lock_);
91 WriteProtectedFunction();
92 }
93
94 private:
danilchap5301e3c2017-09-06 04:10:21 -070095 void ReadProtectedFunction() RTC_SHARED_LOCKS_REQUIRED(lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -070096 unprotected_ = protected_by_lock_;
97 unprotected_ = *pt_protected_by_lock_;
98 }
99
danilchap5301e3c2017-09-06 04:10:21 -0700100 void WriteProtectedFunction() RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -0700101 int x = protected_by_lock_;
102 *pt_protected_by_lock_ = x;
103 protected_by_lock_ = unprotected_;
104 }
105
danilchap5301e3c2017-09-06 04:10:21 -0700106 const Lock& GetLock() RTC_LOCK_RETURNED(lock_) { return lock_; }
danilchap01404082016-10-24 06:07:25 -0700107
Danil Chapovalov37651992017-11-01 10:52:09 +0100108 Lock beforelock_ RTC_ACQUIRED_BEFORE(lock_);
danilchap01404082016-10-24 06:07:25 -0700109 Lock lock_;
danilchap5301e3c2017-09-06 04:10:21 -0700110 Lock pt_lock_ RTC_ACQUIRED_AFTER(lock_);
danilchap01404082016-10-24 06:07:25 -0700111
112 int unprotected_ = 0;
113
danilchap5301e3c2017-09-06 04:10:21 -0700114 int protected_by_lock_ RTC_GUARDED_BY(lock_) = 0;
danilchap01404082016-10-24 06:07:25 -0700115
danilchap5301e3c2017-09-06 04:10:21 -0700116 int* pt_protected_by_lock_ RTC_PT_GUARDED_BY(pt_lock_);
danilchap01404082016-10-24 06:07:25 -0700117};
118
119} // namespace
120
121TEST(ThreadAnnotationsTest, Test) {
122 // This test ensure thread annotations doesn't break compilation.
123 // Thus no run-time expectations.
124 ThreadSafe t;
125 t.LockInOrder();
126 t.UnprotectedFunction();
127 t.ReadProtected();
128 t.WriteProtected();
129 t.CallReadProtectedFunction();
130 t.CallWriteProtectedFunction();
131}