blob: 949f042afa3f94f59855cd4acf8eebdf6d13e038 [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:
Yves Gerey665174f2018-06-19 15:03:05 +020035 ThreadSafe() { pt_protected_by_lock_ = new int; }
danilchap01404082016-10-24 06:07:25 -070036
Yves Gerey665174f2018-06-19 15:03:05 +020037 ~ThreadSafe() { delete pt_protected_by_lock_; }
danilchap01404082016-10-24 06:07:25 -070038
39 void LockInOrder() {
Danil Chapovalov37651992017-11-01 10:52:09 +010040 beforelock_.EnterWrite();
danilchap01404082016-10-24 06:07:25 -070041 lock_.EnterWrite();
42 pt_lock_.EnterWrite();
43
44 pt_lock_.Leave();
45 lock_.Leave();
Danil Chapovalov37651992017-11-01 10:52:09 +010046 beforelock_.Leave();
danilchap01404082016-10-24 06:07:25 -070047 }
48
Danil Chapovalov37651992017-11-01 10:52:09 +010049 void UnprotectedFunction() RTC_LOCKS_EXCLUDED(lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -070050 // Can access unprotected Value.
51 unprotected_ = 15;
52 // Can access pointers themself, but not data they point to.
53 int* tmp = pt_protected_by_lock_;
Danil Chapovalov37651992017-11-01 10:52:09 +010054 pt_protected_by_lock_ = tmp;
danilchap01404082016-10-24 06:07:25 -070055 }
56
57 void ReadProtected() {
58 lock_.EnterRead();
danilchap01404082016-10-24 06:07:25 -070059 unprotected_ = protected_by_lock_;
60 lock_.Leave();
61
62 if (pt_lock_.TryEnterRead()) {
danilchap01404082016-10-24 06:07:25 -070063 unprotected_ = *pt_protected_by_lock_;
64 pt_lock_.Leave();
65 }
danilchap01404082016-10-24 06:07:25 -070066 }
67
68 void WriteProtected() {
69 lock_.EnterWrite();
danilchap01404082016-10-24 06:07:25 -070070 protected_by_lock_ = unprotected_;
71 lock_.Leave();
72
73 if (pt_lock_.TryEnterWrite()) {
danilchap01404082016-10-24 06:07:25 -070074 *pt_protected_by_lock_ = unprotected_;
75 pt_lock_.Leave();
76 }
danilchap01404082016-10-24 06:07:25 -070077 }
78
79 void CallReadProtectedFunction() {
80 lock_.EnterRead();
81 pt_lock_.EnterRead();
82 ReadProtectedFunction();
83 pt_lock_.Leave();
84 lock_.Leave();
85 }
86
87 void CallWriteProtectedFunction() {
88 ScopeLock scope_lock(GetLock());
89 ScopeLock pt_scope_lock(pt_lock_);
90 WriteProtectedFunction();
91 }
92
93 private:
danilchap5301e3c2017-09-06 04:10:21 -070094 void ReadProtectedFunction() RTC_SHARED_LOCKS_REQUIRED(lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -070095 unprotected_ = protected_by_lock_;
96 unprotected_ = *pt_protected_by_lock_;
97 }
98
danilchap5301e3c2017-09-06 04:10:21 -070099 void WriteProtectedFunction() RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -0700100 int x = protected_by_lock_;
101 *pt_protected_by_lock_ = x;
102 protected_by_lock_ = unprotected_;
103 }
104
danilchap5301e3c2017-09-06 04:10:21 -0700105 const Lock& GetLock() RTC_LOCK_RETURNED(lock_) { return lock_; }
danilchap01404082016-10-24 06:07:25 -0700106
Danil Chapovalov37651992017-11-01 10:52:09 +0100107 Lock beforelock_ RTC_ACQUIRED_BEFORE(lock_);
danilchap01404082016-10-24 06:07:25 -0700108 Lock lock_;
danilchap5301e3c2017-09-06 04:10:21 -0700109 Lock pt_lock_ RTC_ACQUIRED_AFTER(lock_);
danilchap01404082016-10-24 06:07:25 -0700110
111 int unprotected_ = 0;
112
danilchap5301e3c2017-09-06 04:10:21 -0700113 int protected_by_lock_ RTC_GUARDED_BY(lock_) = 0;
danilchap01404082016-10-24 06:07:25 -0700114
danilchap5301e3c2017-09-06 04:10:21 -0700115 int* pt_protected_by_lock_ RTC_PT_GUARDED_BY(pt_lock_);
danilchap01404082016-10-24 06:07:25 -0700116};
117
118} // namespace
119
120TEST(ThreadAnnotationsTest, Test) {
121 // This test ensure thread annotations doesn't break compilation.
122 // Thus no run-time expectations.
123 ThreadSafe t;
124 t.LockInOrder();
125 t.UnprotectedFunction();
126 t.ReadProtected();
127 t.WriteProtected();
128 t.CallReadProtectedFunction();
129 t.CallWriteProtectedFunction();
130}