+void HHWheelTimer::scheduleNextTimeout() {
+ auto nextTick = calcNextTick();
+ int64_t tick = 1;
+
+ if (nextTick & WHEEL_MASK) {
+ auto bi = makeBitIterator(bitmap_.begin());
+ auto bi_end = makeBitIterator(bitmap_.end());
+ auto it = folly::findFirstSet(bi + (nextTick & WHEEL_MASK), bi_end);
+ if (it == bi_end) {
+ tick = WHEEL_SIZE - ((nextTick - 1) & WHEEL_MASK);
+ } else {
+ tick = std::distance(bi + (nextTick & WHEEL_MASK), it) + 1;
+ }
+ }
+
+ if (count_ > 0) {
+ if (!this->AsyncTimeout::isScheduled() ||
+ (expireTick_ > tick + nextTick - 1)) {
+ this->AsyncTimeout::scheduleTimeout(interval_ * tick);
+ expireTick_ = tick + nextTick - 1;
+ }
+ } else {
+ this->AsyncTimeout::cancelTimeout();
+ }
+}
+
+int64_t HHWheelTimer::calcNextTick() {
+ auto intervals = (getCurTime() - startTime_) / interval_;
+ // Slow eventbases will have skew between the actual time and the
+ // callback time. To avoid racing the next scheduleNextTimeout()
+ // call, always schedule new timeouts against the actual
+ // timeoutExpired() time.
+ if (!processingCallbacksGuard_) {
+ return intervals;
+ } else {
+ return lastTick_;
+ }
+}
+