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 |