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 "rtc_base/thread_annotations.h" 12 13 #include "test/gtest.h" 14 15 namespace { 16 17 class RTC_LOCKABLE Lock { 18 public: EnterWrite() const19 void EnterWrite() const RTC_EXCLUSIVE_LOCK_FUNCTION() {} EnterRead() const20 void EnterRead() const RTC_SHARED_LOCK_FUNCTION() {} TryEnterWrite() const21 bool TryEnterWrite() const RTC_EXCLUSIVE_TRYLOCK_FUNCTION(true) { 22 return true; 23 } TryEnterRead() const24 bool TryEnterRead() const RTC_SHARED_TRYLOCK_FUNCTION(true) { return true; } Leave() const25 void Leave() const RTC_UNLOCK_FUNCTION() {} 26 }; 27 28 class RTC_SCOPED_LOCKABLE ScopeLock { 29 public: RTC_EXCLUSIVE_LOCK_FUNCTION(lock)30 explicit ScopeLock(const Lock& lock) RTC_EXCLUSIVE_LOCK_FUNCTION(lock) {} RTC_UNLOCK_FUNCTION()31 ~ScopeLock() RTC_UNLOCK_FUNCTION() {} 32 }; 33 34 class ThreadSafe { 35 public: ThreadSafe()36 ThreadSafe() { pt_protected_by_lock_ = new int; } 37 ~ThreadSafe()38 ~ThreadSafe() { delete pt_protected_by_lock_; } 39 LockInOrder()40 void LockInOrder() { 41 beforelock_.EnterWrite(); 42 lock_.EnterWrite(); 43 pt_lock_.EnterWrite(); 44 45 pt_lock_.Leave(); 46 lock_.Leave(); 47 beforelock_.Leave(); 48 } 49 UnprotectedFunction()50 void UnprotectedFunction() RTC_LOCKS_EXCLUDED(lock_, pt_lock_) { 51 // 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_; 55 pt_protected_by_lock_ = tmp; 56 } 57 ReadProtected()58 void ReadProtected() { 59 lock_.EnterRead(); 60 unprotected_ = protected_by_lock_; 61 lock_.Leave(); 62 63 if (pt_lock_.TryEnterRead()) { 64 unprotected_ = *pt_protected_by_lock_; 65 pt_lock_.Leave(); 66 } 67 } 68 WriteProtected()69 void WriteProtected() { 70 lock_.EnterWrite(); 71 protected_by_lock_ = unprotected_; 72 lock_.Leave(); 73 74 if (pt_lock_.TryEnterWrite()) { 75 *pt_protected_by_lock_ = unprotected_; 76 pt_lock_.Leave(); 77 } 78 } 79 CallReadProtectedFunction()80 void CallReadProtectedFunction() { 81 lock_.EnterRead(); 82 pt_lock_.EnterRead(); 83 ReadProtectedFunction(); 84 pt_lock_.Leave(); 85 lock_.Leave(); 86 } 87 CallWriteProtectedFunction()88 void CallWriteProtectedFunction() { 89 ScopeLock scope_lock(GetLock()); 90 ScopeLock pt_scope_lock(pt_lock_); 91 WriteProtectedFunction(); 92 } 93 94 private: ReadProtectedFunction()95 void ReadProtectedFunction() RTC_SHARED_LOCKS_REQUIRED(lock_, pt_lock_) { 96 unprotected_ = protected_by_lock_; 97 unprotected_ = *pt_protected_by_lock_; 98 } 99 WriteProtectedFunction()100 void WriteProtectedFunction() RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_, pt_lock_) { 101 int x = protected_by_lock_; 102 *pt_protected_by_lock_ = x; 103 protected_by_lock_ = unprotected_; 104 } 105 GetLock()106 const Lock& GetLock() RTC_LOCK_RETURNED(lock_) { return lock_; } 107 108 Lock beforelock_ RTC_ACQUIRED_BEFORE(lock_); 109 Lock lock_; 110 Lock pt_lock_ RTC_ACQUIRED_AFTER(lock_); 111 112 int unprotected_ = 0; 113 114 int protected_by_lock_ RTC_GUARDED_BY(lock_) = 0; 115 116 int* pt_protected_by_lock_ RTC_PT_GUARDED_BY(pt_lock_); 117 }; 118 119 } // namespace 120 TEST(ThreadAnnotationsTest,Test)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 } 132