lock.h (2901B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 7 #ifndef BASE_LOCK_H_ 8 #define BASE_LOCK_H_ 9 10 #include "base/basictypes.h" 11 #include "base/lock_impl.h" 12 #include "base/platform_thread.h" 13 14 // A convenient wrapper for an OS specific critical section. 15 class Lock { 16 public: 17 // Optimized wrapper implementation 18 Lock() = default; 19 ~Lock() = default; 20 void Acquire() { lock_.Lock(); } 21 void Release() { lock_.Unlock(); } 22 23 // If the lock is not held, take it and return true. If the lock is already 24 // held by another thread, immediately return false. This must not be called 25 // by a thread already holding the lock (what happens is undefined and an 26 // assertion may fail). 27 bool Try() { return lock_.Try(); } 28 29 // Null implementation if not debug. 30 void AssertAcquired() const {} 31 32 // Whether Lock mitigates priority inversion when used from different thread 33 // priorities. 34 static bool HandlesMultipleThreadPriorities() { 35 #if defined(XP_UNIX) 36 // POSIX mitigates priority inversion by setting the priority of a thread 37 // holding a Lock to the maximum priority of any other thread waiting on it. 38 return base::internal::LockImpl::PriorityInheritanceAvailable(); 39 #else 40 // Windows mitigates priority inversion by randomly boosting the priority of 41 // ready threads. 42 // https://msdn.microsoft.com/library/windows/desktop/ms684831.aspx 43 return true; 44 #endif 45 } 46 47 // Both Windows and POSIX implementations of ConditionVariable need to be 48 // able to see our lock and tweak our debugging counters, as they release and 49 // acquire locks inside of their condition variable APIs. 50 friend class ConditionVariable; 51 52 private: 53 // Platform specific underlying lock implementation. 54 ::base::internal::LockImpl lock_; 55 56 DISALLOW_COPY_AND_ASSIGN(Lock); 57 }; 58 59 // A helper class that acquires the given Lock while the AutoLock is in scope. 60 class AutoLock { 61 public: 62 struct AlreadyAcquired {}; 63 64 explicit AutoLock(Lock& lock) : lock_(lock) { lock_.Acquire(); } 65 66 AutoLock(Lock& lock, const AlreadyAcquired&) : lock_(lock) { 67 lock_.AssertAcquired(); 68 } 69 70 ~AutoLock() { 71 lock_.AssertAcquired(); 72 lock_.Release(); 73 } 74 75 private: 76 Lock& lock_; 77 DISALLOW_COPY_AND_ASSIGN(AutoLock); 78 }; 79 80 // AutoUnlock is a helper that will Release() the |lock| argument in the 81 // constructor, and re-Acquire() it in the destructor. 82 class AutoUnlock { 83 public: 84 explicit AutoUnlock(Lock& lock) : lock_(lock) { 85 // We require our caller to have the lock. 86 lock_.AssertAcquired(); 87 lock_.Release(); 88 } 89 90 ~AutoUnlock() { lock_.Acquire(); } 91 92 private: 93 Lock& lock_; 94 DISALLOW_COPY_AND_ASSIGN(AutoUnlock); 95 }; 96 97 #endif // BASE_LOCK_H_