|  | // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "base/synchronization/condition_variable.h" | 
|  |  | 
|  | #include "base/synchronization/lock.h" | 
|  | #include "base/threading/scoped_blocking_call.h" | 
|  | #include "base/threading/thread_restrictions.h" | 
|  | #include "base/time/time.h" | 
|  |  | 
|  | #include <windows.h> | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | ConditionVariable::ConditionVariable(Lock* user_lock) | 
|  | : srwlock_(user_lock->lock_.native_handle()) | 
|  | #if DCHECK_IS_ON() | 
|  | , user_lock_(user_lock) | 
|  | #endif | 
|  | { | 
|  | DCHECK(user_lock); | 
|  | InitializeConditionVariable(reinterpret_cast<PCONDITION_VARIABLE>(&cv_)); | 
|  | } | 
|  |  | 
|  | ConditionVariable::~ConditionVariable() = default; | 
|  |  | 
|  | void ConditionVariable::Wait() { | 
|  | TimedWait(TimeDelta::FromMilliseconds(INFINITE)); | 
|  | } | 
|  |  | 
|  | void ConditionVariable::TimedWait(const TimeDelta& max_time) { | 
|  | internal::AssertBaseSyncPrimitivesAllowed(); | 
|  | ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK); | 
|  | DWORD timeout = static_cast<DWORD>(max_time.InMilliseconds()); | 
|  |  | 
|  | #if DCHECK_IS_ON() | 
|  | user_lock_->CheckHeldAndUnmark(); | 
|  | #endif | 
|  |  | 
|  | if (!SleepConditionVariableSRW(reinterpret_cast<PCONDITION_VARIABLE>(&cv_), | 
|  | reinterpret_cast<PSRWLOCK>(srwlock_), timeout, | 
|  | 0)) { | 
|  | // On failure, we only expect the CV to timeout. Any other error value means | 
|  | // that we've unexpectedly woken up. | 
|  | // Note that WAIT_TIMEOUT != ERROR_TIMEOUT. WAIT_TIMEOUT is used with the | 
|  | // WaitFor* family of functions as a direct return value. ERROR_TIMEOUT is | 
|  | // used with GetLastError(). | 
|  | DCHECK_EQ(static_cast<DWORD>(ERROR_TIMEOUT), GetLastError()); | 
|  | } | 
|  |  | 
|  | #if DCHECK_IS_ON() | 
|  | user_lock_->CheckUnheldAndMark(); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void ConditionVariable::Broadcast() { | 
|  | WakeAllConditionVariable(reinterpret_cast<PCONDITION_VARIABLE>(&cv_)); | 
|  | } | 
|  |  | 
|  | void ConditionVariable::Signal() { | 
|  | WakeConditionVariable(reinterpret_cast<PCONDITION_VARIABLE>(&cv_)); | 
|  | } | 
|  |  | 
|  | }  // namespace base |