defaultTimeout_(defaultTimeoutMS),
nextTick_(1),
count_(0),
- catchupEveryN_(DEFAULT_CATCHUP_EVERY_N),
- expirationsSinceCatchup_(0),
processingCallbacksGuard_(nullptr) {}
HHWheelTimer::~HHWheelTimer() {
// timeoutExpired() can only be invoked directly from the event base loop.
// It should never be invoked recursively.
//
- milliseconds catchup = now_ + interval_;
- // If catchup is enabled, we may have missed multiple intervals, use
- // currentTime() to check exactly.
- if (++expirationsSinceCatchup_ >= catchupEveryN_) {
- catchup = std::chrono::duration_cast<milliseconds>(
+ milliseconds catchup = std::chrono::duration_cast<milliseconds>(
std::chrono::steady_clock::now().time_since_epoch());
- expirationsSinceCatchup_ = 0;
- }
while (now_ < catchup) {
now_ += interval_;
return count_;
}
- /**
- * This turns on more exact timing. By default the wheel timer
- * increments its cached time only once everyN (default) ticks.
- *
- * With catchupEveryN at 1, timeouts will only be delayed until the
- * next tick, at which point all overdue timeouts are called. The
- * wheel timer is approximately 2x slower with this set to 1.
- *
- * Load testing in opt mode showed skew was about 1% with no catchup.
- */
- void setCatchupEveryN(uint32_t everyN) {
- catchupEveryN_ = everyN;
- }
-
bool isDetachable() const {
return !folly::AsyncTimeout::isScheduled();
}
uint64_t count_;
std::chrono::milliseconds now_;
- static constexpr uint32_t DEFAULT_CATCHUP_EVERY_N = 10;
-
- uint32_t catchupEveryN_;
- uint32_t expirationsSinceCatchup_;
bool* processingCallbacksGuard_;
};
milliseconds interval(10);
milliseconds atMostEveryN(3);
StackWheelTimer t(&eventBase, atMostEveryN);
- t.setCatchupEveryN(70);
// Create 60 timeouts to be added to ts1 at 1ms intervals.
uint32_t numTimeouts = 60;
ASSERT_EQ(t.count(), 0);
// Check that the timeout was delayed by sleep
- T_CHECK_TIMEOUT(start, t1.timestamps[0], milliseconds(15), milliseconds(1));
- T_CHECK_TIMEOUT(start, end, milliseconds(15), milliseconds(1));
-
- // Try it again, this time with catchup timing every loop
- t.setCatchupEveryN(1);
+ T_CHECK_TIMEOUT(start, t1.timestamps[0], milliseconds(10), milliseconds(1));
+ T_CHECK_TIMEOUT(start, end, milliseconds(10), milliseconds(1));
eventBase.runInLoop([](){usleep(10000);});
t.scheduleTimeout(&t2, milliseconds(5));