michael@0: // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "base/lock_impl.h" michael@0: #include "base/logging.h" michael@0: michael@0: // NOTE: Although windows critical sections support recursive locks, we do not michael@0: // allow this, and we will commonly fire a DCHECK() if a thread attempts to michael@0: // acquire the lock a second time (while already holding it). michael@0: michael@0: LockImpl::LockImpl() { michael@0: #ifndef NDEBUG michael@0: recursion_count_shadow_ = 0; michael@0: recursion_used_ = false; michael@0: owning_thread_id_ = 0; michael@0: #endif // NDEBUG michael@0: // The second parameter is the spin count, for short-held locks it avoid the michael@0: // contending thread from going to sleep which helps performance greatly. michael@0: ::InitializeCriticalSectionAndSpinCount(&os_lock_, 2000); michael@0: } michael@0: michael@0: LockImpl::~LockImpl() { michael@0: ::DeleteCriticalSection(&os_lock_); michael@0: } michael@0: michael@0: bool LockImpl::Try() { michael@0: if (::TryEnterCriticalSection(&os_lock_) != FALSE) { michael@0: #ifndef NDEBUG michael@0: // ONLY access data after locking. michael@0: owning_thread_id_ = PlatformThread::CurrentId(); michael@0: DCHECK_NE(owning_thread_id_, 0); michael@0: recursion_count_shadow_++; michael@0: if (2 == recursion_count_shadow_ && !recursion_used_) { michael@0: recursion_used_ = true; michael@0: DCHECK(false); // Catch accidental redundant lock acquisition. michael@0: } michael@0: #endif michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: void LockImpl::Lock() { michael@0: ::EnterCriticalSection(&os_lock_); michael@0: #ifndef NDEBUG michael@0: // ONLY access data after locking. michael@0: owning_thread_id_ = PlatformThread::CurrentId(); michael@0: DCHECK_NE(owning_thread_id_, 0); michael@0: recursion_count_shadow_++; michael@0: if (2 == recursion_count_shadow_ && !recursion_used_) { michael@0: recursion_used_ = true; michael@0: DCHECK(false); // Catch accidental redundant lock acquisition. michael@0: } michael@0: #endif // NDEBUG michael@0: } michael@0: michael@0: void LockImpl::Unlock() { michael@0: #ifndef NDEBUG michael@0: --recursion_count_shadow_; // ONLY access while lock is still held. michael@0: DCHECK(0 <= recursion_count_shadow_); michael@0: owning_thread_id_ = 0; michael@0: #endif // NDEBUG michael@0: ::LeaveCriticalSection(&os_lock_); michael@0: } michael@0: michael@0: // In non-debug builds, this method is declared as an empty inline method. michael@0: #ifndef NDEBUG michael@0: void LockImpl::AssertAcquired() const { michael@0: DCHECK(recursion_count_shadow_ > 0); michael@0: DCHECK_EQ(owning_thread_id_, PlatformThread::CurrentId()); michael@0: } michael@0: #endif