blob: d8a4af1ac3500ffc460a4e300af4ff786066f2da [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;
danilchap01404082016-10-24 06:07:25 -070037 }
38
39 ~ThreadSafe() {
40 delete pt_protected_by_lock_;
danilchap01404082016-10-24 06:07:25 -070041 }
42
43 void LockInOrder() {
Danil Chapovalov37651992017-11-01 10:52:09 +010044 beforelock_.EnterWrite();
danilchap01404082016-10-24 06:07:25 -070045 lock_.EnterWrite();
46 pt_lock_.EnterWrite();
47
48 pt_lock_.Leave();
49 lock_.Leave();
Danil Chapovalov37651992017-11-01 10:52:09 +010050 beforelock_.Leave();
danilchap01404082016-10-24 06:07:25 -070051 }
52
Danil Chapovalov37651992017-11-01 10:52:09 +010053 void UnprotectedFunction() RTC_LOCKS_EXCLUDED(lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -070054 // Can access unprotected Value.
55 unprotected_ = 15;
56 // Can access pointers themself, but not data they point to.
57 int* tmp = pt_protected_by_lock_;
Danil Chapovalov37651992017-11-01 10:52:09 +010058 pt_protected_by_lock_ = tmp;
danilchap01404082016-10-24 06:07:25 -070059 }
60
61 void ReadProtected() {
62 lock_.EnterRead();
danilchap01404082016-10-24 06:07:25 -070063 unprotected_ = protected_by_lock_;
64 lock_.Leave();
65
66 if (pt_lock_.TryEnterRead()) {
danilchap01404082016-10-24 06:07:25 -070067 unprotected_ = *pt_protected_by_lock_;
68 pt_lock_.Leave();
69 }
danilchap01404082016-10-24 06:07:25 -070070 }
71
72 void WriteProtected() {
73 lock_.EnterWrite();
danilchap01404082016-10-24 06:07:25 -070074 protected_by_lock_ = unprotected_;
75 lock_.Leave();
76
77 if (pt_lock_.TryEnterWrite()) {
danilchap01404082016-10-24 06:07:25 -070078 *pt_protected_by_lock_ = unprotected_;
79 pt_lock_.Leave();
80 }
danilchap01404082016-10-24 06:07:25 -070081 }
82
83 void CallReadProtectedFunction() {
84 lock_.EnterRead();
85 pt_lock_.EnterRead();
86 ReadProtectedFunction();
87 pt_lock_.Leave();
88 lock_.Leave();
89 }
90
91 void CallWriteProtectedFunction() {
92 ScopeLock scope_lock(GetLock());
93 ScopeLock pt_scope_lock(pt_lock_);
94 WriteProtectedFunction();
95 }
96
97 private:
danilchap5301e3c2017-09-06 04:10:21 -070098 void ReadProtectedFunction() RTC_SHARED_LOCKS_REQUIRED(lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -070099 unprotected_ = protected_by_lock_;
100 unprotected_ = *pt_protected_by_lock_;
101 }
102
danilchap5301e3c2017-09-06 04:10:21 -0700103 void WriteProtectedFunction() RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_, pt_lock_) {
danilchap01404082016-10-24 06:07:25 -0700104 int x = protected_by_lock_;
105 *pt_protected_by_lock_ = x;
106 protected_by_lock_ = unprotected_;
107 }
108
danilchap5301e3c2017-09-06 04:10:21 -0700109 const Lock& GetLock() RTC_LOCK_RETURNED(lock_) { return lock_; }
danilchap01404082016-10-24 06:07:25 -0700110
Danil Chapovalov37651992017-11-01 10:52:09 +0100111 Lock beforelock_ RTC_ACQUIRED_BEFORE(lock_);
danilchap01404082016-10-24 06:07:25 -0700112 Lock lock_;
danilchap5301e3c2017-09-06 04:10:21 -0700113 Lock pt_lock_ RTC_ACQUIRED_AFTER(lock_);
danilchap01404082016-10-24 06:07:25 -0700114
115 int unprotected_ = 0;
116
danilchap5301e3c2017-09-06 04:10:21 -0700117 int protected_by_lock_ RTC_GUARDED_BY(lock_) = 0;
danilchap01404082016-10-24 06:07:25 -0700118
danilchap5301e3c2017-09-06 04:10:21 -0700119 int* pt_protected_by_lock_ RTC_PT_GUARDED_BY(pt_lock_);
danilchap01404082016-10-24 06:07:25 -0700120};
121
122} // namespace
123
124TEST(ThreadAnnotationsTest, Test) {
125 // This test ensure thread annotations doesn't break compilation.
126 // Thus no run-time expectations.
127 ThreadSafe t;
128 t.LockInOrder();
129 t.UnprotectedFunction();
130 t.ReadProtected();
131 t.WriteProtected();
132 t.CallReadProtectedFunction();
133 t.CallWriteProtectedFunction();
134}