blob: 2dc2ee7a54335c629925e40ff1889ce229780816 [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"
12#include "test/gtest.h"
danilchap01404082016-10-24 06:07:25 -070013
14namespace {
15
danilchap5301e3c2017-09-06 04:10:21 -070016class RTC_LOCKABLE Lock {
danilchap01404082016-10-24 06:07:25 -070017 public:
danilchap5301e3c2017-09-06 04:10:21 -070018 void EnterWrite() const RTC_EXCLUSIVE_LOCK_FUNCTION() {}
19 void EnterRead() const RTC_SHARED_LOCK_FUNCTION() {}
20 bool TryEnterWrite() const RTC_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
21 return true;
22 }
23 bool TryEnterRead() const RTC_SHARED_TRYLOCK_FUNCTION(true) { return true; }
24 void Leave() const RTC_UNLOCK_FUNCTION() {}
danilchap01404082016-10-24 06:07:25 -070025};
26
danilchap5301e3c2017-09-06 04:10:21 -070027class RTC_SCOPED_LOCKABLE ScopeLock {
danilchap01404082016-10-24 06:07:25 -070028 public:
danilchap5301e3c2017-09-06 04:10:21 -070029 explicit ScopeLock(const Lock& lock) RTC_EXCLUSIVE_LOCK_FUNCTION(lock) {}
30 ~ScopeLock() RTC_UNLOCK_FUNCTION() {}
danilchap01404082016-10-24 06:07:25 -070031};
32
33class ThreadSafe {
34 public:
35 ThreadSafe() {
36 pt_protected_by_lock_ = new int;
37 pt_protected_by_anything_ = new int;
38 }
39
40 ~ThreadSafe() {
41 delete pt_protected_by_lock_;
42 delete pt_protected_by_anything_;
43 }
44
45 void LockInOrder() {
46 anylock_.EnterWrite();
47 lock_.EnterWrite();
48 pt_lock_.EnterWrite();
49
50 pt_lock_.Leave();
51 lock_.Leave();
52 anylock_.Leave();
53 }
54
danilchap5301e3c2017-09-06 04:10:21 -070055 void UnprotectedFunction() RTC_LOCKS_EXCLUDED(anylock_, lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -070056 // Can access unprotected Value.
57 unprotected_ = 15;
58 // Can access pointers themself, but not data they point to.
59 int* tmp = pt_protected_by_lock_;
60 pt_protected_by_lock_ = pt_protected_by_anything_;
61 pt_protected_by_anything_ = tmp;
62 }
63
64 void ReadProtected() {
65 lock_.EnterRead();
66 unprotected_ = protected_by_anything_;
67 unprotected_ = protected_by_lock_;
68 lock_.Leave();
69
70 if (pt_lock_.TryEnterRead()) {
71 unprotected_ = *pt_protected_by_anything_;
72 unprotected_ = *pt_protected_by_lock_;
73 pt_lock_.Leave();
74 }
75
76 anylock_.EnterRead();
77 unprotected_ = protected_by_anything_;
78 unprotected_ = *pt_protected_by_anything_;
79 anylock_.Leave();
80 }
81
82 void WriteProtected() {
83 lock_.EnterWrite();
84 protected_by_anything_ = unprotected_;
85 protected_by_lock_ = unprotected_;
86 lock_.Leave();
87
88 if (pt_lock_.TryEnterWrite()) {
89 *pt_protected_by_anything_ = unprotected_;
90 *pt_protected_by_lock_ = unprotected_;
91 pt_lock_.Leave();
92 }
93
94 anylock_.EnterWrite();
95 protected_by_anything_ = unprotected_;
96 *pt_protected_by_anything_ = unprotected_;
97 anylock_.Leave();
98 }
99
100 void CallReadProtectedFunction() {
101 lock_.EnterRead();
102 pt_lock_.EnterRead();
103 ReadProtectedFunction();
104 pt_lock_.Leave();
105 lock_.Leave();
106 }
107
108 void CallWriteProtectedFunction() {
109 ScopeLock scope_lock(GetLock());
110 ScopeLock pt_scope_lock(pt_lock_);
111 WriteProtectedFunction();
112 }
113
114 private:
danilchap5301e3c2017-09-06 04:10:21 -0700115 void ReadProtectedFunction() RTC_SHARED_LOCKS_REQUIRED(lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -0700116 unprotected_ = protected_by_lock_;
117 unprotected_ = *pt_protected_by_lock_;
118 }
119
danilchap5301e3c2017-09-06 04:10:21 -0700120 void WriteProtectedFunction() RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -0700121 int x = protected_by_lock_;
122 *pt_protected_by_lock_ = x;
123 protected_by_lock_ = unprotected_;
124 }
125
danilchap5301e3c2017-09-06 04:10:21 -0700126 const Lock& GetLock() RTC_LOCK_RETURNED(lock_) { return lock_; }
danilchap01404082016-10-24 06:07:25 -0700127
danilchap5301e3c2017-09-06 04:10:21 -0700128 Lock anylock_ RTC_ACQUIRED_BEFORE(lock_);
danilchap01404082016-10-24 06:07:25 -0700129 Lock lock_;
danilchap5301e3c2017-09-06 04:10:21 -0700130 Lock pt_lock_ RTC_ACQUIRED_AFTER(lock_);
danilchap01404082016-10-24 06:07:25 -0700131
132 int unprotected_ = 0;
133
danilchap5301e3c2017-09-06 04:10:21 -0700134 int protected_by_lock_ RTC_GUARDED_BY(lock_) = 0;
135 int protected_by_anything_ RTC_GUARDED_VAR = 0;
danilchap01404082016-10-24 06:07:25 -0700136
danilchap5301e3c2017-09-06 04:10:21 -0700137 int* pt_protected_by_lock_ RTC_PT_GUARDED_BY(pt_lock_);
138 int* pt_protected_by_anything_ RTC_PT_GUARDED_VAR;
danilchap01404082016-10-24 06:07:25 -0700139};
140
141} // namespace
142
143TEST(ThreadAnnotationsTest, Test) {
144 // This test ensure thread annotations doesn't break compilation.
145 // Thus no run-time expectations.
146 ThreadSafe t;
147 t.LockInOrder();
148 t.UnprotectedFunction();
149 t.ReadProtected();
150 t.WriteProtected();
151 t.CallReadProtectedFunction();
152 t.CallWriteProtectedFunction();
153}