OLD | NEW |
| (Empty) |
1 /* | |
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 | |
11 #include "webrtc/base/thread_annotations.h" | |
12 #include "webrtc/test/gtest.h" | |
13 | |
14 namespace { | |
15 | |
16 class LOCKABLE Lock { | |
17 public: | |
18 void EnterWrite() const EXCLUSIVE_LOCK_FUNCTION() {} | |
19 void EnterRead() const SHARED_LOCK_FUNCTION() {} | |
20 bool TryEnterWrite() const EXCLUSIVE_TRYLOCK_FUNCTION(true) { return true; } | |
21 bool TryEnterRead() const SHARED_TRYLOCK_FUNCTION(true) { return true; } | |
22 void Leave() const UNLOCK_FUNCTION() {} | |
23 }; | |
24 | |
25 class SCOPED_LOCKABLE ScopeLock { | |
26 public: | |
27 explicit ScopeLock(const Lock& lock) EXCLUSIVE_LOCK_FUNCTION(lock) {} | |
28 ~ScopeLock() UNLOCK_FUNCTION() {} | |
29 }; | |
30 | |
31 class ThreadSafe { | |
32 public: | |
33 ThreadSafe() { | |
34 pt_protected_by_lock_ = new int; | |
35 pt_protected_by_anything_ = new int; | |
36 } | |
37 | |
38 ~ThreadSafe() { | |
39 delete pt_protected_by_lock_; | |
40 delete pt_protected_by_anything_; | |
41 } | |
42 | |
43 void LockInOrder() { | |
44 anylock_.EnterWrite(); | |
45 lock_.EnterWrite(); | |
46 pt_lock_.EnterWrite(); | |
47 | |
48 pt_lock_.Leave(); | |
49 lock_.Leave(); | |
50 anylock_.Leave(); | |
51 } | |
52 | |
53 void UnprotectedFunction() LOCKS_EXCLUDED(anylock_, lock_, pt_lock_) { | |
54 // 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_; | |
58 pt_protected_by_lock_ = pt_protected_by_anything_; | |
59 pt_protected_by_anything_ = tmp; | |
60 } | |
61 | |
62 void ReadProtected() { | |
63 lock_.EnterRead(); | |
64 unprotected_ = protected_by_anything_; | |
65 unprotected_ = protected_by_lock_; | |
66 lock_.Leave(); | |
67 | |
68 if (pt_lock_.TryEnterRead()) { | |
69 unprotected_ = *pt_protected_by_anything_; | |
70 unprotected_ = *pt_protected_by_lock_; | |
71 pt_lock_.Leave(); | |
72 } | |
73 | |
74 anylock_.EnterRead(); | |
75 unprotected_ = protected_by_anything_; | |
76 unprotected_ = *pt_protected_by_anything_; | |
77 anylock_.Leave(); | |
78 } | |
79 | |
80 void WriteProtected() { | |
81 lock_.EnterWrite(); | |
82 protected_by_anything_ = unprotected_; | |
83 protected_by_lock_ = unprotected_; | |
84 lock_.Leave(); | |
85 | |
86 if (pt_lock_.TryEnterWrite()) { | |
87 *pt_protected_by_anything_ = unprotected_; | |
88 *pt_protected_by_lock_ = unprotected_; | |
89 pt_lock_.Leave(); | |
90 } | |
91 | |
92 anylock_.EnterWrite(); | |
93 protected_by_anything_ = unprotected_; | |
94 *pt_protected_by_anything_ = unprotected_; | |
95 anylock_.Leave(); | |
96 } | |
97 | |
98 void CallReadProtectedFunction() { | |
99 lock_.EnterRead(); | |
100 pt_lock_.EnterRead(); | |
101 ReadProtectedFunction(); | |
102 pt_lock_.Leave(); | |
103 lock_.Leave(); | |
104 } | |
105 | |
106 void CallWriteProtectedFunction() { | |
107 ScopeLock scope_lock(GetLock()); | |
108 ScopeLock pt_scope_lock(pt_lock_); | |
109 WriteProtectedFunction(); | |
110 } | |
111 | |
112 private: | |
113 void ReadProtectedFunction() SHARED_LOCKS_REQUIRED(lock_, pt_lock_) { | |
114 unprotected_ = protected_by_lock_; | |
115 unprotected_ = *pt_protected_by_lock_; | |
116 } | |
117 | |
118 void WriteProtectedFunction() EXCLUSIVE_LOCKS_REQUIRED(lock_, pt_lock_) { | |
119 int x = protected_by_lock_; | |
120 *pt_protected_by_lock_ = x; | |
121 protected_by_lock_ = unprotected_; | |
122 } | |
123 | |
124 const Lock& GetLock() LOCK_RETURNED(lock_) { return lock_; } | |
125 | |
126 Lock anylock_ ACQUIRED_BEFORE(lock_); | |
127 Lock lock_; | |
128 Lock pt_lock_ ACQUIRED_AFTER(lock_); | |
129 | |
130 int unprotected_ = 0; | |
131 | |
132 int protected_by_lock_ GUARDED_BY(lock_) = 0; | |
133 int protected_by_anything_ GUARDED_VAR = 0; | |
134 | |
135 int* pt_protected_by_lock_ PT_GUARDED_BY(pt_lock_); | |
136 int* pt_protected_by_anything_ PT_GUARDED_VAR; | |
137 }; | |
138 | |
139 } // namespace | |
140 | |
141 TEST(ThreadAnnotationsTest, Test) { | |
142 // This test ensure thread annotations doesn't break compilation. | |
143 // Thus no run-time expectations. | |
144 ThreadSafe t; | |
145 t.LockInOrder(); | |
146 t.UnprotectedFunction(); | |
147 t.ReadProtected(); | |
148 t.WriteProtected(); | |
149 t.CallReadProtectedFunction(); | |
150 t.CallWriteProtectedFunction(); | |
151 } | |
OLD | NEW |