Commit b5759618 authored by Keith Birney's avatar Keith Birney Committed by Facebook Github Bot

Use consistent time_point in cascadeTimers

Summary: This fixes a timing issue that has been observed in rare cases under very heavy load.

Differential Revision: D18875069

fbshipit-source-id: cd47abfbd01c10e2568693f876dd3e6c2cb3bb24
parent 564a32e6
...@@ -205,17 +205,19 @@ void HHWheelTimerBase<Duration>::scheduleTimeout(Callback* callback) { ...@@ -205,17 +205,19 @@ void HHWheelTimerBase<Duration>::scheduleTimeout(Callback* callback) {
} }
template <class Duration> template <class Duration>
bool HHWheelTimerBase<Duration>::cascadeTimers(int bucket, int tick) { bool HHWheelTimerBase<Duration>::cascadeTimers(
int bucket,
int tick,
const std::chrono::steady_clock::time_point curTime) {
CallbackList cbs; CallbackList cbs;
cbs.swap(buckets_[bucket][tick]); cbs.swap(buckets_[bucket][tick]);
auto now = getCurTime(); auto nextTick = calcNextTick(curTime);
auto nextTick = calcNextTick(now);
while (!cbs.empty()) { while (!cbs.empty()) {
auto* cb = &cbs.front(); auto* cb = &cbs.front();
cbs.pop_front(); cbs.pop_front();
scheduleTimeoutImpl( scheduleTimeoutImpl(
cb, cb,
nextTick + timeToWheelTicks(cb->getTimeRemaining(now)), nextTick + timeToWheelTicks(cb->getTimeRemaining(curTime)),
expireTick_, expireTick_,
nextTick); nextTick);
} }
...@@ -231,7 +233,8 @@ void HHWheelTimerBase<Duration>::scheduleTimeoutInternal(Duration timeout) { ...@@ -231,7 +233,8 @@ void HHWheelTimerBase<Duration>::scheduleTimeoutInternal(Duration timeout) {
template <class Duration> template <class Duration>
void HHWheelTimerBase<Duration>::timeoutExpired() noexcept { void HHWheelTimerBase<Duration>::timeoutExpired() noexcept {
auto nextTick = calcNextTick(); auto curTime = getCurTime();
auto nextTick = calcNextTick(curTime);
// If the last smart pointer for "this" is reset inside the callback's // If the last smart pointer for "this" is reset inside the callback's
// timeoutExpired(), then the guard will detect that it is time to bail from // timeoutExpired(), then the guard will detect that it is time to bail from
...@@ -256,9 +259,11 @@ void HHWheelTimerBase<Duration>::timeoutExpired() noexcept { ...@@ -256,9 +259,11 @@ void HHWheelTimerBase<Duration>::timeoutExpired() noexcept {
if (idx == 0) { if (idx == 0) {
// Cascade timers // Cascade timers
if (cascadeTimers(1, (expireTick_ >> WHEEL_BITS) & WHEEL_MASK) && if (cascadeTimers(1, (expireTick_ >> WHEEL_BITS) & WHEEL_MASK, curTime) &&
cascadeTimers(2, (expireTick_ >> (2 * WHEEL_BITS)) & WHEEL_MASK)) { cascadeTimers(
cascadeTimers(3, (expireTick_ >> (3 * WHEEL_BITS)) & WHEEL_MASK); 2, (expireTick_ >> (2 * WHEEL_BITS)) & WHEEL_MASK, curTime)) {
cascadeTimers(
3, (expireTick_ >> (3 * WHEEL_BITS)) & WHEEL_MASK, curTime);
} }
} }
......
...@@ -299,7 +299,10 @@ class HHWheelTimerBase : private folly::AsyncTimeout, ...@@ -299,7 +299,10 @@ class HHWheelTimerBase : private folly::AsyncTimeout,
return t.count() / interval_.count(); return t.count() / interval_.count();
} }
bool cascadeTimers(int bucket, int tick); bool cascadeTimers(
int bucket,
int tick,
std::chrono::steady_clock::time_point curTime);
void scheduleTimeoutInternal(Duration timeout); void scheduleTimeoutInternal(Duration timeout);
int64_t expireTick_; int64_t expireTick_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment