diff options
| author | Nick Mathewson <[email protected]> | 2016-02-26 07:06:05 +0100 |
|---|---|---|
| committer | Nick Mathewson <[email protected]> | 2016-02-26 07:13:17 +0100 |
| commit | d00a3762cd9813446a97ae8a5b3a621d20cd608d (patch) | |
| tree | c92a269993effa2d7a9668875ef2ebb5accb4573 | |
| parent | 51e9aae0c12e7bea45d9d18a1a7282aee22ba557 (diff) | |
Correct and simplify timeouts_readd()
William Ahern tells me that the intent here is that timeout_readd()
should always reschedule the timeout at the first time in the future
that is an even multiple of to->interval, as if we had called:
do {
to->expires += to->interval;
} while (to->expires <= T->curtime);
But of course, that's not efficient. The implementation strategy
used in this patch simplifies the calculation down to a single %
operation, plus a few additions and subtractions.
To verify the correctness of the formula used here, note first that
0 <= r < to->interval, and so
0 < to->interval - r <= to->interval. Since
expires' = curtime + (interval - r),
curtime < expires' <= curtime + interval,
and so the new expiration time is no more than one interval after
curtime.
Note second that since
r = (curtime - expires) % interval,
expires' = curtime + (interval - r), we have
(expires' - expires) % interval =
(curtime + (interval - r) - expires) % interval =
(curtime - r - expires) % interval =
(curtime - (curtime-expires) % interval - expires) % interval =
(curtime - curtime + expires - expires) % interval =
0.
And so the new expiration time is an even multiple of interval from
the original expiration time.
Since we have both properties we wanted, this formula should be right.
| -rw-r--r-- | timeout.c | 19 |
1 files changed, 7 insertions, 12 deletions
@@ -358,18 +358,13 @@ static void timeouts_readd(struct timeouts *T, struct timeout *to) { to->expires += to->interval; if (to->expires <= T->curtime) { - if (to->expires < T->curtime) { - timeout_t n = T->curtime - to->expires; - timeout_t q = n / to->interval; - timeout_t r = n % to->interval; - - if (r) - to->expires += (to->interval * q) + (to->interval - r); - else - to->expires += (to->interval * q); - } else { - to->expires += to->interval; - } + /* If we've missed the next firing of this timeout, reschedule + * it to occur at the next multiple of its interval after + * the last time that it fired. + */ + timeout_t n = T->curtime - to->expires; + timeout_t r = n % to->interval; + to->expires = T->curtime + (to->interval - r); } timeouts_sched(T, to, to->expires); |
