| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_LOCK_H_ | 5 #ifndef BASE_LOCK_H_ |
| 6 #define BASE_LOCK_H_ | 6 #define BASE_LOCK_H_ |
| 7 | 7 |
| 8 #include "base/lock_impl.h" | 8 #include "base/lock_impl.h" |
| 9 | 9 |
| 10 // A convenient wrapper for a critical section. | 10 // A convenient wrapper for an OS specific critical section. |
| 11 // | 11 // |
| 12 // NOTE: A thread may acquire the same lock multiple times, but it must call | 12 // NOTE: Although windows critical sections support recursive locks, we do not |
| 13 // Release for each call to Acquire in order to finally release the lock. | 13 // allow this, and we will commonly fire a DCHECK() if a thread attempts to |
| 14 // acquire the lock a second time (while already holding it). |
| 14 // | 15 // |
| 15 // Complication: UnitTest for DeathTests catch DCHECK exceptions, so we need | 16 // Complication: UnitTest for DeathTests catch DCHECK exceptions, so we need |
| 16 // to write code assuming DCHECK will throw. This means we need to save any | 17 // to write code assuming DCHECK will throw. This means we need to save any |
| 17 // assertable value in a local until we can safely throw. | 18 // assertable value in a local until we can safely throw. |
| 19 |
| 18 class Lock { | 20 class Lock { |
| 19 public: | 21 public: |
| 20 Lock(); | 22 Lock(); |
| 21 ~Lock(); | 23 ~Lock(); |
| 22 void Acquire(); | 24 void Acquire(); |
| 23 void Release(); | 25 void Release(); |
| 24 // If the lock is not held, take it and return true. If the lock is already | 26 // If the lock is not held, take it and return true. If the lock is already |
| 25 // held by something else, immediately return false. | 27 // held by another thread, immediately return false. |
| 26 bool Try(); | 28 bool Try(); |
| 27 | 29 |
| 28 // Return the underlying lock implementation. | 30 // Return the underlying lock implementation. |
| 29 // TODO(awalker): refactor lock and condition variables so that this is | 31 // TODO(awalker): refactor lock and condition variables so that this is |
| 30 // unnecessary. | 32 // unnecessary. |
| 31 LockImpl* lock_impl() { return &lock_; } | 33 LockImpl* lock_impl() { return &lock_; } |
| 32 | 34 |
| 33 private: | 35 private: |
| 34 LockImpl lock_; // User-supplied underlying lock implementation. | 36 LockImpl lock_; // User-supplied underlying lock implementation. |
| 35 | 37 |
| 36 // All private data is implicitly protected by spin_lock_. | 38 #ifndef NDEBUG |
| 37 // Be VERY careful to only access under that lock. | 39 // All private data is implicitly protected by lock_. |
| 40 // Be VERY careful to only access members under that lock. |
| 38 int32 recursion_count_shadow_; | 41 int32 recursion_count_shadow_; |
| 39 | 42 bool recursion_used_; // Allow debugging to continued after a DCHECK(). |
| 40 // Allow access to GetCurrentThreadRecursionCount() | 43 int32 acquisition_count_; // Number of times lock was acquired. |
| 41 friend class AutoUnlock; | 44 int32 contention_count_; // Number of times there was contention. |
| 42 int32 GetCurrentThreadRecursionCount(); | |
| 43 | |
| 44 #ifndef NDEBUG | |
| 45 // Even in Debug mode, the expensive tallies won't be calculated by default. | |
| 46 bool recursion_used_; | |
| 47 int32 acquisition_count_; | |
| 48 | |
| 49 int32 contention_count_; | |
| 50 #endif // NDEBUG | 45 #endif // NDEBUG |
| 51 | 46 |
| 52 DISALLOW_COPY_AND_ASSIGN(Lock); | 47 DISALLOW_COPY_AND_ASSIGN(Lock); |
| 53 }; | 48 }; |
| 54 | 49 |
| 55 // A helper class that acquires the given Lock while the AutoLock is in scope. | 50 // A helper class that acquires the given Lock while the AutoLock is in scope. |
| 56 class AutoLock { | 51 class AutoLock { |
| 57 public: | 52 public: |
| 58 explicit AutoLock(Lock& lock) : lock_(lock) { | 53 explicit AutoLock(Lock& lock) : lock_(lock) { |
| 59 lock_.Acquire(); | 54 lock_.Acquire(); |
| 60 } | 55 } |
| 61 | 56 |
| 62 ~AutoLock() { | 57 ~AutoLock() { |
| 63 lock_.Release(); | 58 lock_.Release(); |
| 64 } | 59 } |
| 65 | 60 |
| 66 private: | 61 private: |
| 67 Lock& lock_; | 62 Lock& lock_; |
| 68 DISALLOW_COPY_AND_ASSIGN(AutoLock); | 63 DISALLOW_COPY_AND_ASSIGN(AutoLock); |
| 69 }; | 64 }; |
| 70 | 65 |
| 71 // AutoUnlock is a helper class for ConditionVariable instances | 66 // AutoUnlock is a helper class for ConditionVariable that will Release() the |
| 72 // that is analogous to AutoLock. It provides for nested Releases | 67 // lock argument in the constructor, and re-Acquire() it in the destructor. |
| 73 // of a lock for the Wait functionality of a ConditionVariable class. | |
| 74 // The destructor automatically does the corresponding Acquire | |
| 75 // calls (to return to the initial nested lock state). | |
| 76 | |
| 77 // Instances of AutoUnlock can ***ONLY*** validly be constructed if the | |
| 78 // caller currently holds the lock provided as the constructor's argument. | |
| 79 // If that ***REQUIREMENT*** is violated in debug mode, a DCHECK will | |
| 80 // be generated in the Lock class. In production (non-debug), | |
| 81 // the results are undefined (and probably bad) if the caller | |
| 82 // is not already holding the indicated lock. | |
| 83 class ConditionVariable; | 68 class ConditionVariable; |
| 84 class AutoUnlock { | 69 class AutoUnlock { |
| 85 private: // Everything is private, so only our friend can use us. | 70 private: // Everything is private, so only our friend can use us. |
| 86 friend class ConditionVariable; // The only user of this class. | 71 friend class ConditionVariable; // The only user of this class. |
| 87 explicit AutoUnlock(Lock& lock); | 72 |
| 88 ~AutoUnlock(); | 73 explicit AutoUnlock(Lock& lock) : lock_(&lock) { |
| 74 // We require our caller to have the lock. |
| 75 lock_->Release(); |
| 76 } |
| 77 |
| 78 ~AutoUnlock() { |
| 79 lock_->Acquire(); |
| 80 } |
| 89 | 81 |
| 90 Lock* lock_; | 82 Lock* lock_; |
| 91 int release_count_; | |
| 92 }; | 83 }; |
| 93 | 84 |
| 94 #endif // BASE_LOCK_H_ | 85 #endif // BASE_LOCK_H_ |
| 95 | 86 |
| OLD | NEW |