• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
LockImpl()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 
~LockImpl()23 LockImpl::~LockImpl() {
24   ::DeleteCriticalSection(&os_lock_);
25 }
26 
Try()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 
Lock()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 
Unlock()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
AssertAcquired() const69 void LockImpl::AssertAcquired() const {
70   DCHECK(recursion_count_shadow_ > 0);
71   DCHECK_EQ(owning_thread_id_, PlatformThread::CurrentId());
72 }
73 #endif
74