From c8d09aeb88e6ce8573b8fb2c11a2209131910c16 Mon Sep 17 00:00:00 2001 From: Lucian Petrut Date: Thu, 4 May 2023 14:27:56 +0000 Subject: [PATCH] common: avoid <1ms waits on Windows std::condition_variable::wait_for uses SleepConditionVariableSRW on Windows, which has millisecond precision. In order to avoid busy loops, we won't wait for less than one millisecond on Windows. Note that this situation is quite common since on Windows, "wait_for" often returns ~1ms before the specified timeout. Signed-off-by: Lucian Petrut --- src/common/Timer.cc | 16 ++++++++++++++-- src/common/ceph_timer.h | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/common/Timer.cc b/src/common/Timer.cc index 48c79d613d0..2a3277a2765 100644 --- a/src/common/Timer.cc +++ b/src/common/Timer.cc @@ -87,8 +87,20 @@ void CommonSafeTimer::timer_thread() auto p = schedule.begin(); // is the future now? - if (p->first > now) - break; + #if defined(_WIN32) + if (p->first - now > std::chrono::milliseconds(1)) { + // std::condition_variable::wait_for uses SleepConditionVariableSRW + // on Windows, which has millisecond precision. Deltas <1ms will + // lead to busy loops, which should be avoided. This situation is + // quite common since "wait_for" often returns ~1ms earlier than + // requested. + break; + } + #else // !_WIN32 + if (p->first > now) { + break; + } + #endif Context *callback = p->second; events.erase(callback); diff --git a/src/common/ceph_timer.h b/src/common/ceph_timer.h index 74fb4add851..bc324bfa243 100644 --- a/src/common/ceph_timer.h +++ b/src/common/ceph_timer.h @@ -105,8 +105,20 @@ class timer { while (!schedule.empty()) { auto p = schedule.begin(); // Should we wait for the future? - if (p->t > now) - break; + #if defined(_WIN32) + if (p->t - now > std::chrono::milliseconds(1)) { + // std::condition_variable::wait_for uses SleepConditionVariableSRW + // on Windows, which has millisecond precision. Deltas <1ms will + // lead to busy loops, which should be avoided. This situation is + // quite common since "wait_for" often returns ~1ms earlier than + // requested. + break; + } + #else // !_WIN32 + if (p->t > now) { + break; + } + #endif auto& e = *p; schedule.erase(e); -- 2.39.5