condition_variable_win.cc 2.2 KB

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