1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/condition_variable.h" 6*6777b538SAndroid Build Coastguard Worker 7*6777b538SAndroid Build Coastguard Worker #include <windows.h> 8*6777b538SAndroid Build Coastguard Worker 9*6777b538SAndroid Build Coastguard Worker #include <optional> 10*6777b538SAndroid Build Coastguard Worker 11*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h" 12*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h" 13*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h" 14*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h" 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Worker namespace base { 18*6777b538SAndroid Build Coastguard Worker ConditionVariable(Lock * user_lock)19*6777b538SAndroid Build Coastguard WorkerConditionVariable::ConditionVariable(Lock* user_lock) 20*6777b538SAndroid Build Coastguard Worker : srwlock_(user_lock->lock_.native_handle()) 21*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON() 22*6777b538SAndroid Build Coastguard Worker , user_lock_(user_lock) 23*6777b538SAndroid Build Coastguard Worker #endif 24*6777b538SAndroid Build Coastguard Worker { 25*6777b538SAndroid Build Coastguard Worker DCHECK(user_lock); 26*6777b538SAndroid Build Coastguard Worker InitializeConditionVariable(reinterpret_cast<PCONDITION_VARIABLE>(&cv_)); 27*6777b538SAndroid Build Coastguard Worker } 28*6777b538SAndroid Build Coastguard Worker 29*6777b538SAndroid Build Coastguard Worker ConditionVariable::~ConditionVariable() = default; 30*6777b538SAndroid Build Coastguard Worker Wait()31*6777b538SAndroid Build Coastguard Workervoid ConditionVariable::Wait() { 32*6777b538SAndroid Build Coastguard Worker TimedWait(TimeDelta::Max()); 33*6777b538SAndroid Build Coastguard Worker } 34*6777b538SAndroid Build Coastguard Worker TimedWait(const TimeDelta & max_time)35*6777b538SAndroid Build Coastguard Workervoid ConditionVariable::TimedWait(const TimeDelta& max_time) { 36*6777b538SAndroid Build Coastguard Worker std::optional<internal::ScopedBlockingCallWithBaseSyncPrimitives> 37*6777b538SAndroid Build Coastguard Worker scoped_blocking_call; 38*6777b538SAndroid Build Coastguard Worker if (waiting_is_blocking_) 39*6777b538SAndroid Build Coastguard Worker scoped_blocking_call.emplace(FROM_HERE, BlockingType::MAY_BLOCK); 40*6777b538SAndroid Build Coastguard Worker 41*6777b538SAndroid Build Coastguard Worker // Limit timeout to INFINITE. 42*6777b538SAndroid Build Coastguard Worker DWORD timeout = saturated_cast<DWORD>(max_time.InMilliseconds()); 43*6777b538SAndroid Build Coastguard Worker 44*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON() 45*6777b538SAndroid Build Coastguard Worker user_lock_->CheckHeldAndUnmark(); 46*6777b538SAndroid Build Coastguard Worker #endif 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard Worker if (!SleepConditionVariableSRW(reinterpret_cast<PCONDITION_VARIABLE>(&cv_), 49*6777b538SAndroid Build Coastguard Worker reinterpret_cast<PSRWLOCK>(srwlock_.get()), 50*6777b538SAndroid Build Coastguard Worker timeout, 0)) { 51*6777b538SAndroid Build Coastguard Worker // On failure, we only expect the CV to timeout. Any other error value means 52*6777b538SAndroid Build Coastguard Worker // that we've unexpectedly woken up. 53*6777b538SAndroid Build Coastguard Worker // Note that WAIT_TIMEOUT != ERROR_TIMEOUT. WAIT_TIMEOUT is used with the 54*6777b538SAndroid Build Coastguard Worker // WaitFor* family of functions as a direct return value. ERROR_TIMEOUT is 55*6777b538SAndroid Build Coastguard Worker // used with GetLastError(). 56*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(static_cast<DWORD>(ERROR_TIMEOUT), GetLastError()); 57*6777b538SAndroid Build Coastguard Worker } 58*6777b538SAndroid Build Coastguard Worker 59*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON() 60*6777b538SAndroid Build Coastguard Worker user_lock_->CheckUnheldAndMark(); 61*6777b538SAndroid Build Coastguard Worker #endif 62*6777b538SAndroid Build Coastguard Worker } 63*6777b538SAndroid Build Coastguard Worker Broadcast()64*6777b538SAndroid Build Coastguard Workervoid ConditionVariable::Broadcast() { 65*6777b538SAndroid Build Coastguard Worker WakeAllConditionVariable(reinterpret_cast<PCONDITION_VARIABLE>(&cv_)); 66*6777b538SAndroid Build Coastguard Worker } 67*6777b538SAndroid Build Coastguard Worker Signal()68*6777b538SAndroid Build Coastguard Workervoid ConditionVariable::Signal() { 69*6777b538SAndroid Build Coastguard Worker WakeConditionVariable(reinterpret_cast<PCONDITION_VARIABLE>(&cv_)); 70*6777b538SAndroid Build Coastguard Worker } 71*6777b538SAndroid Build Coastguard Worker 72*6777b538SAndroid Build Coastguard Worker } // namespace base 73