|
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 |
|
3 // found in the LICENSE file. |
|
4 |
|
5 #include "base/lock_impl.h" |
|
6 #include "base/logging.h" |
|
7 |
|
8 // NOTE: Although windows critical sections support recursive locks, we do not |
|
9 // allow this, and we will commonly fire a DCHECK() if a thread attempts to |
|
10 // acquire the lock a second time (while already holding it). |
|
11 |
|
12 LockImpl::LockImpl() { |
|
13 #ifndef NDEBUG |
|
14 recursion_count_shadow_ = 0; |
|
15 recursion_used_ = false; |
|
16 owning_thread_id_ = 0; |
|
17 #endif // NDEBUG |
|
18 // The second parameter is the spin count, for short-held locks it avoid the |
|
19 // contending thread from going to sleep which helps performance greatly. |
|
20 ::InitializeCriticalSectionAndSpinCount(&os_lock_, 2000); |
|
21 } |
|
22 |
|
23 LockImpl::~LockImpl() { |
|
24 ::DeleteCriticalSection(&os_lock_); |
|
25 } |
|
26 |
|
27 bool LockImpl::Try() { |
|
28 if (::TryEnterCriticalSection(&os_lock_) != FALSE) { |
|
29 #ifndef NDEBUG |
|
30 // ONLY access data after locking. |
|
31 owning_thread_id_ = PlatformThread::CurrentId(); |
|
32 DCHECK_NE(owning_thread_id_, 0); |
|
33 recursion_count_shadow_++; |
|
34 if (2 == recursion_count_shadow_ && !recursion_used_) { |
|
35 recursion_used_ = true; |
|
36 DCHECK(false); // Catch accidental redundant lock acquisition. |
|
37 } |
|
38 #endif |
|
39 return true; |
|
40 } |
|
41 return false; |
|
42 } |
|
43 |
|
44 void LockImpl::Lock() { |
|
45 ::EnterCriticalSection(&os_lock_); |
|
46 #ifndef NDEBUG |
|
47 // ONLY access data after locking. |
|
48 owning_thread_id_ = PlatformThread::CurrentId(); |
|
49 DCHECK_NE(owning_thread_id_, 0); |
|
50 recursion_count_shadow_++; |
|
51 if (2 == recursion_count_shadow_ && !recursion_used_) { |
|
52 recursion_used_ = true; |
|
53 DCHECK(false); // Catch accidental redundant lock acquisition. |
|
54 } |
|
55 #endif // NDEBUG |
|
56 } |
|
57 |
|
58 void LockImpl::Unlock() { |
|
59 #ifndef NDEBUG |
|
60 --recursion_count_shadow_; // ONLY access while lock is still held. |
|
61 DCHECK(0 <= recursion_count_shadow_); |
|
62 owning_thread_id_ = 0; |
|
63 #endif // NDEBUG |
|
64 ::LeaveCriticalSection(&os_lock_); |
|
65 } |
|
66 |
|
67 // In non-debug builds, this method is declared as an empty inline method. |
|
68 #ifndef NDEBUG |
|
69 void LockImpl::AssertAcquired() const { |
|
70 DCHECK(recursion_count_shadow_ > 0); |
|
71 DCHECK_EQ(owning_thread_id_, PlatformThread::CurrentId()); |
|
72 } |
|
73 #endif |