// 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/numerics/safe_conversions.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 "third_party/abseil-cpp/absl/types/optional.h" #include 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(&cv_)); } ConditionVariable::~ConditionVariable() = default; void ConditionVariable::Wait() { TimedWait(TimeDelta::Max()); } void ConditionVariable::TimedWait(const TimeDelta& max_time) { absl::optional scoped_blocking_call; if (waiting_is_blocking_) scoped_blocking_call.emplace(FROM_HERE, BlockingType::MAY_BLOCK); // Limit timeout to INFINITE. DWORD timeout = saturated_cast(max_time.InMilliseconds()); #if DCHECK_IS_ON() user_lock_->CheckHeldAndUnmark(); #endif if (!SleepConditionVariableSRW(reinterpret_cast(&cv_), reinterpret_cast(srwlock_.get()), 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(ERROR_TIMEOUT), GetLastError()); } #if DCHECK_IS_ON() user_lock_->CheckUnheldAndMark(); #endif } void ConditionVariable::Broadcast() { WakeAllConditionVariable(reinterpret_cast(&cv_)); } void ConditionVariable::Signal() { WakeConditionVariable(reinterpret_cast(&cv_)); } } // namespace base