Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1150)

Unified Diff: base/synchronization/condition_variable_win.cc

Issue 2388083002: Test MultiThreadConsumerTest.
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/synchronization/condition_variable_unittest.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/synchronization/condition_variable_win.cc
diff --git a/base/synchronization/condition_variable_win.cc b/base/synchronization/condition_variable_win.cc
index 8bece6eb34dbfc965ccee65b08051c54ad9fff79..17675d07dd2aa4d172bdcb12dc2c8c9a0ab715a5 100644
--- a/base/synchronization/condition_variable_win.cc
+++ b/base/synchronization/condition_variable_win.cc
@@ -10,6 +10,57 @@
namespace base {
+namespace {
+
+// Infinite timeout in milliseconds.
+static const int64_t kInfiniteTimeout =
+ TimeDelta::FromMilliseconds(INFINITE).InMilliseconds();
+
+// Number of tries after SleepConditionVariableSRW() fails.
+static const int kMaxNumberOfTriesAfterFailure = 10;
+
+// As per MSDN documentation (https://goo.gl/tPHPkY), condition variables are
+// subject to spurious wakeups (those not associated with an explicit wake) and
+// stolen wakeups (another thread manages to run before the woken thread). This
+// function checks whether it's a real timeout and if not it retries
+// kMaxNumberOfTriesAfterFailure times after which it crashes.
+void SleepConditionVariable(PCONDITION_VARIABLE cv,
+ PSRWLOCK srw_lock,
+ BOOL infinite_timeout,
+ DWORD timeout,
+ ULONG flags) {
+ base::Time time_start = base::Time::Now();
+ int num_tries_after_failure = 0;
+
+ while (!SleepConditionVariableSRW(cv, srw_lock, timeout, flags)) {
+ // Note: Use ERROR_TIMEOUT with GetLastError().
+ DWORD error = GetLastError();
+
+ num_tries_after_failure++;
+ CHECK_LE(num_tries_after_failure, kMaxNumberOfTriesAfterFailure)
+ << "SleepConditionVariableSRW() failed after max number of retries "
+ "with error code ("
+ << error << ").";
+
+ if (infinite_timeout) {
+ // Ideally for infinite timeout, we should not get ERROR_TIMEOUT error.
+ DCHECK_NE(error, static_cast<DWORD>(ERROR_TIMEOUT));
+ } else {
+ if (error == ERROR_TIMEOUT)
+ break;
+
+ // Compute remaining timeout.
+ int64_t time_delta = (base::Time::Now() - time_start).InMilliseconds();
+ timeout -= time_delta;
+ // Break here as if timeout has occurred, otherwise continue to wait
+ // for the remaining timeout.
+ if (timeout <= 0)
+ break;
+ }
+ }
+}
+}
+
ConditionVariable::ConditionVariable(Lock* user_lock)
: srwlock_(user_lock->lock_.native_handle())
#if DCHECK_IS_ON()
@@ -23,25 +74,28 @@ ConditionVariable::ConditionVariable(Lock* user_lock)
ConditionVariable::~ConditionVariable() = default;
void ConditionVariable::Wait() {
- TimedWait(TimeDelta::FromMilliseconds(INFINITE));
+ base::ThreadRestrictions::AssertWaitAllowed();
+
+#if DCHECK_IS_ON()
+ user_lock_->CheckHeldAndUnmark();
+#endif
+
+ SleepConditionVariable(&cv_, srwlock_, true, kInfiniteTimeout, 0);
+
+#if DCHECK_IS_ON()
+ user_lock_->CheckUnheldAndMark();
+#endif
}
void ConditionVariable::TimedWait(const TimeDelta& max_time) {
base::ThreadRestrictions::AssertWaitAllowed();
- DWORD timeout = static_cast<DWORD>(max_time.InMilliseconds());
#if DCHECK_IS_ON()
user_lock_->CheckHeldAndUnmark();
#endif
- if (!SleepConditionVariableSRW(&cv_, 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());
- }
+ SleepConditionVariable(&cv_, srwlock_, false,
+ static_cast<DWORD>(max_time.InMilliseconds()), 0);
#if DCHECK_IS_ON()
user_lock_->CheckUnheldAndMark();
« no previous file with comments | « base/synchronization/condition_variable_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698