1 // Copyright (c) 2011 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/synchronization/condition_variable.h" 6 7 #include "base/optional.h" 8 #include "base/synchronization/lock.h" 9 #include "base/threading/scoped_blocking_call.h" 10 #include "base/threading/thread_restrictions.h" 11 #include "base/time/time.h" 12 13 #include <windows.h> 14 15 namespace base { 16 ConditionVariable(Lock * user_lock)17ConditionVariable::ConditionVariable(Lock* user_lock) 18 : srwlock_(user_lock->lock_.native_handle()) 19 #if DCHECK_IS_ON() 20 , user_lock_(user_lock) 21 #endif 22 { 23 DCHECK(user_lock); 24 InitializeConditionVariable(reinterpret_cast<PCONDITION_VARIABLE>(&cv_)); 25 } 26 27 ConditionVariable::~ConditionVariable() = default; 28 Wait()29void ConditionVariable::Wait() { 30 TimedWait(TimeDelta::FromMilliseconds(INFINITE)); 31 } 32 TimedWait(const TimeDelta & max_time)33void ConditionVariable::TimedWait(const TimeDelta& max_time) { 34 Optional<internal::ScopedBlockingCallWithBaseSyncPrimitives> 35 scoped_blocking_call; 36 if (waiting_is_blocking_) 37 scoped_blocking_call.emplace(FROM_HERE, BlockingType::MAY_BLOCK); 38 39 DWORD timeout = static_cast<DWORD>(max_time.InMilliseconds()); 40 41 #if DCHECK_IS_ON() 42 user_lock_->CheckHeldAndUnmark(); 43 #endif 44 45 if (!SleepConditionVariableSRW(reinterpret_cast<PCONDITION_VARIABLE>(&cv_), 46 reinterpret_cast<PSRWLOCK>(srwlock_), timeout, 47 0)) { 48 // On failure, we only expect the CV to timeout. Any other error value means 49 // that we've unexpectedly woken up. 50 // Note that WAIT_TIMEOUT != ERROR_TIMEOUT. WAIT_TIMEOUT is used with the 51 // WaitFor* family of functions as a direct return value. ERROR_TIMEOUT is 52 // used with GetLastError(). 53 DCHECK_EQ(static_cast<DWORD>(ERROR_TIMEOUT), GetLastError()); 54 } 55 56 #if DCHECK_IS_ON() 57 user_lock_->CheckUnheldAndMark(); 58 #endif 59 } 60 Broadcast()61void ConditionVariable::Broadcast() { 62 WakeAllConditionVariable(reinterpret_cast<PCONDITION_VARIABLE>(&cv_)); 63 } 64 Signal()65void ConditionVariable::Signal() { 66 WakeConditionVariable(reinterpret_cast<PCONDITION_VARIABLE>(&cv_)); 67 } 68 69 } // namespace base 70