1*d9f75844SAndroid Build Coastguard Worker /* 2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3*d9f75844SAndroid Build Coastguard Worker * 4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license 5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source 6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found 7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may 8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree. 9*d9f75844SAndroid Build Coastguard Worker */ 10*d9f75844SAndroid Build Coastguard Worker 11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread_annotations.h" 12*d9f75844SAndroid Build Coastguard Worker 13*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h" 14*d9f75844SAndroid Build Coastguard Worker 15*d9f75844SAndroid Build Coastguard Worker namespace { 16*d9f75844SAndroid Build Coastguard Worker 17*d9f75844SAndroid Build Coastguard Worker class RTC_LOCKABLE Lock { 18*d9f75844SAndroid Build Coastguard Worker public: EnterWrite() const19*d9f75844SAndroid Build Coastguard Worker void EnterWrite() const RTC_EXCLUSIVE_LOCK_FUNCTION() {} EnterRead() const20*d9f75844SAndroid Build Coastguard Worker void EnterRead() const RTC_SHARED_LOCK_FUNCTION() {} TryEnterWrite() const21*d9f75844SAndroid Build Coastguard Worker bool TryEnterWrite() const RTC_EXCLUSIVE_TRYLOCK_FUNCTION(true) { 22*d9f75844SAndroid Build Coastguard Worker return true; 23*d9f75844SAndroid Build Coastguard Worker } TryEnterRead() const24*d9f75844SAndroid Build Coastguard Worker bool TryEnterRead() const RTC_SHARED_TRYLOCK_FUNCTION(true) { return true; } Leave() const25*d9f75844SAndroid Build Coastguard Worker void Leave() const RTC_UNLOCK_FUNCTION() {} 26*d9f75844SAndroid Build Coastguard Worker }; 27*d9f75844SAndroid Build Coastguard Worker 28*d9f75844SAndroid Build Coastguard Worker class RTC_SCOPED_LOCKABLE ScopeLock { 29*d9f75844SAndroid Build Coastguard Worker public: RTC_EXCLUSIVE_LOCK_FUNCTION(lock)30*d9f75844SAndroid Build Coastguard Worker explicit ScopeLock(const Lock& lock) RTC_EXCLUSIVE_LOCK_FUNCTION(lock) {} RTC_UNLOCK_FUNCTION()31*d9f75844SAndroid Build Coastguard Worker ~ScopeLock() RTC_UNLOCK_FUNCTION() {} 32*d9f75844SAndroid Build Coastguard Worker }; 33*d9f75844SAndroid Build Coastguard Worker 34*d9f75844SAndroid Build Coastguard Worker class ThreadSafe { 35*d9f75844SAndroid Build Coastguard Worker public: ThreadSafe()36*d9f75844SAndroid Build Coastguard Worker ThreadSafe() { pt_protected_by_lock_ = new int; } 37*d9f75844SAndroid Build Coastguard Worker ~ThreadSafe()38*d9f75844SAndroid Build Coastguard Worker ~ThreadSafe() { delete pt_protected_by_lock_; } 39*d9f75844SAndroid Build Coastguard Worker LockInOrder()40*d9f75844SAndroid Build Coastguard Worker void LockInOrder() { 41*d9f75844SAndroid Build Coastguard Worker beforelock_.EnterWrite(); 42*d9f75844SAndroid Build Coastguard Worker lock_.EnterWrite(); 43*d9f75844SAndroid Build Coastguard Worker pt_lock_.EnterWrite(); 44*d9f75844SAndroid Build Coastguard Worker 45*d9f75844SAndroid Build Coastguard Worker pt_lock_.Leave(); 46*d9f75844SAndroid Build Coastguard Worker lock_.Leave(); 47*d9f75844SAndroid Build Coastguard Worker beforelock_.Leave(); 48*d9f75844SAndroid Build Coastguard Worker } 49*d9f75844SAndroid Build Coastguard Worker UnprotectedFunction()50*d9f75844SAndroid Build Coastguard Worker void UnprotectedFunction() RTC_LOCKS_EXCLUDED(lock_, pt_lock_) { 51*d9f75844SAndroid Build Coastguard Worker // Can access unprotected Value. 52*d9f75844SAndroid Build Coastguard Worker unprotected_ = 15; 53*d9f75844SAndroid Build Coastguard Worker // Can access pointers themself, but not data they point to. 54*d9f75844SAndroid Build Coastguard Worker int* tmp = pt_protected_by_lock_; 55*d9f75844SAndroid Build Coastguard Worker pt_protected_by_lock_ = tmp; 56*d9f75844SAndroid Build Coastguard Worker } 57*d9f75844SAndroid Build Coastguard Worker ReadProtected()58*d9f75844SAndroid Build Coastguard Worker void ReadProtected() { 59*d9f75844SAndroid Build Coastguard Worker lock_.EnterRead(); 60*d9f75844SAndroid Build Coastguard Worker unprotected_ = protected_by_lock_; 61*d9f75844SAndroid Build Coastguard Worker lock_.Leave(); 62*d9f75844SAndroid Build Coastguard Worker 63*d9f75844SAndroid Build Coastguard Worker if (pt_lock_.TryEnterRead()) { 64*d9f75844SAndroid Build Coastguard Worker unprotected_ = *pt_protected_by_lock_; 65*d9f75844SAndroid Build Coastguard Worker pt_lock_.Leave(); 66*d9f75844SAndroid Build Coastguard Worker } 67*d9f75844SAndroid Build Coastguard Worker } 68*d9f75844SAndroid Build Coastguard Worker WriteProtected()69*d9f75844SAndroid Build Coastguard Worker void WriteProtected() { 70*d9f75844SAndroid Build Coastguard Worker lock_.EnterWrite(); 71*d9f75844SAndroid Build Coastguard Worker protected_by_lock_ = unprotected_; 72*d9f75844SAndroid Build Coastguard Worker lock_.Leave(); 73*d9f75844SAndroid Build Coastguard Worker 74*d9f75844SAndroid Build Coastguard Worker if (pt_lock_.TryEnterWrite()) { 75*d9f75844SAndroid Build Coastguard Worker *pt_protected_by_lock_ = unprotected_; 76*d9f75844SAndroid Build Coastguard Worker pt_lock_.Leave(); 77*d9f75844SAndroid Build Coastguard Worker } 78*d9f75844SAndroid Build Coastguard Worker } 79*d9f75844SAndroid Build Coastguard Worker CallReadProtectedFunction()80*d9f75844SAndroid Build Coastguard Worker void CallReadProtectedFunction() { 81*d9f75844SAndroid Build Coastguard Worker lock_.EnterRead(); 82*d9f75844SAndroid Build Coastguard Worker pt_lock_.EnterRead(); 83*d9f75844SAndroid Build Coastguard Worker ReadProtectedFunction(); 84*d9f75844SAndroid Build Coastguard Worker pt_lock_.Leave(); 85*d9f75844SAndroid Build Coastguard Worker lock_.Leave(); 86*d9f75844SAndroid Build Coastguard Worker } 87*d9f75844SAndroid Build Coastguard Worker CallWriteProtectedFunction()88*d9f75844SAndroid Build Coastguard Worker void CallWriteProtectedFunction() { 89*d9f75844SAndroid Build Coastguard Worker ScopeLock scope_lock(GetLock()); 90*d9f75844SAndroid Build Coastguard Worker ScopeLock pt_scope_lock(pt_lock_); 91*d9f75844SAndroid Build Coastguard Worker WriteProtectedFunction(); 92*d9f75844SAndroid Build Coastguard Worker } 93*d9f75844SAndroid Build Coastguard Worker 94*d9f75844SAndroid Build Coastguard Worker private: ReadProtectedFunction()95*d9f75844SAndroid Build Coastguard Worker void ReadProtectedFunction() RTC_SHARED_LOCKS_REQUIRED(lock_, pt_lock_) { 96*d9f75844SAndroid Build Coastguard Worker unprotected_ = protected_by_lock_; 97*d9f75844SAndroid Build Coastguard Worker unprotected_ = *pt_protected_by_lock_; 98*d9f75844SAndroid Build Coastguard Worker } 99*d9f75844SAndroid Build Coastguard Worker WriteProtectedFunction()100*d9f75844SAndroid Build Coastguard Worker void WriteProtectedFunction() RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_, pt_lock_) { 101*d9f75844SAndroid Build Coastguard Worker int x = protected_by_lock_; 102*d9f75844SAndroid Build Coastguard Worker *pt_protected_by_lock_ = x; 103*d9f75844SAndroid Build Coastguard Worker protected_by_lock_ = unprotected_; 104*d9f75844SAndroid Build Coastguard Worker } 105*d9f75844SAndroid Build Coastguard Worker GetLock()106*d9f75844SAndroid Build Coastguard Worker const Lock& GetLock() RTC_LOCK_RETURNED(lock_) { return lock_; } 107*d9f75844SAndroid Build Coastguard Worker 108*d9f75844SAndroid Build Coastguard Worker Lock beforelock_ RTC_ACQUIRED_BEFORE(lock_); 109*d9f75844SAndroid Build Coastguard Worker Lock lock_; 110*d9f75844SAndroid Build Coastguard Worker Lock pt_lock_ RTC_ACQUIRED_AFTER(lock_); 111*d9f75844SAndroid Build Coastguard Worker 112*d9f75844SAndroid Build Coastguard Worker int unprotected_ = 0; 113*d9f75844SAndroid Build Coastguard Worker 114*d9f75844SAndroid Build Coastguard Worker int protected_by_lock_ RTC_GUARDED_BY(lock_) = 0; 115*d9f75844SAndroid Build Coastguard Worker 116*d9f75844SAndroid Build Coastguard Worker int* pt_protected_by_lock_ RTC_PT_GUARDED_BY(pt_lock_); 117*d9f75844SAndroid Build Coastguard Worker }; 118*d9f75844SAndroid Build Coastguard Worker 119*d9f75844SAndroid Build Coastguard Worker } // namespace 120*d9f75844SAndroid Build Coastguard Worker TEST(ThreadAnnotationsTest,Test)121*d9f75844SAndroid Build Coastguard WorkerTEST(ThreadAnnotationsTest, Test) { 122*d9f75844SAndroid Build Coastguard Worker // This test ensure thread annotations doesn't break compilation. 123*d9f75844SAndroid Build Coastguard Worker // Thus no run-time expectations. 124*d9f75844SAndroid Build Coastguard Worker ThreadSafe t; 125*d9f75844SAndroid Build Coastguard Worker t.LockInOrder(); 126*d9f75844SAndroid Build Coastguard Worker t.UnprotectedFunction(); 127*d9f75844SAndroid Build Coastguard Worker t.ReadProtected(); 128*d9f75844SAndroid Build Coastguard Worker t.WriteProtected(); 129*d9f75844SAndroid Build Coastguard Worker t.CallReadProtectedFunction(); 130*d9f75844SAndroid Build Coastguard Worker t.CallWriteProtectedFunction(); 131*d9f75844SAndroid Build Coastguard Worker } 132