serialqueue: Improve timing of sleep durations

If any callback is invoked from the pollreactor then obtain a new
eventtime before calculating a sleep duration.  This improves the
timing of events.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2021-02-12 13:18:08 -05:00
parent d7bacae29d
commit 730ef9d347
1 changed files with 10 additions and 4 deletions

View File

@ -123,24 +123,27 @@ pollreactor_update_timer(struct pollreactor *pr, int pos, double waketime)
// Internal code to invoke timer callbacks // Internal code to invoke timer callbacks
static int static int
pollreactor_check_timers(struct pollreactor *pr, double eventtime) pollreactor_check_timers(struct pollreactor *pr, double eventtime, int busy)
{ {
if (eventtime >= pr->next_timer) { if (eventtime >= pr->next_timer) {
// Find and run pending timers
pr->next_timer = PR_NEVER; pr->next_timer = PR_NEVER;
int i; int i;
for (i=0; i<pr->num_timers; i++) { for (i=0; i<pr->num_timers; i++) {
struct pollreactor_timer *timer = &pr->timers[i]; struct pollreactor_timer *timer = &pr->timers[i];
double t = timer->waketime; double t = timer->waketime;
if (eventtime >= t) { if (eventtime >= t) {
busy = 1;
t = timer->callback(pr->callback_data, eventtime); t = timer->callback(pr->callback_data, eventtime);
timer->waketime = t; timer->waketime = t;
} }
if (t < pr->next_timer) if (t < pr->next_timer)
pr->next_timer = t; pr->next_timer = t;
} }
if (eventtime >= pr->next_timer)
return 0;
} }
if (busy)
return 0;
// Calculate sleep duration
double timeout = ceil((pr->next_timer - eventtime) * 1000.); double timeout = ceil((pr->next_timer - eventtime) * 1000.);
return timeout < 1. ? 1 : (timeout > 1000. ? 1000 : (int)timeout); return timeout < 1. ? 1 : (timeout > 1000. ? 1000 : (int)timeout);
} }
@ -150,11 +153,14 @@ static void
pollreactor_run(struct pollreactor *pr) pollreactor_run(struct pollreactor *pr)
{ {
double eventtime = get_monotonic(); double eventtime = get_monotonic();
int busy = 1;
while (! pr->must_exit) { while (! pr->must_exit) {
int timeout = pollreactor_check_timers(pr, eventtime); int timeout = pollreactor_check_timers(pr, eventtime, busy);
busy = 0;
int ret = poll(pr->fds, pr->num_fds, timeout); int ret = poll(pr->fds, pr->num_fds, timeout);
eventtime = get_monotonic(); eventtime = get_monotonic();
if (ret > 0) { if (ret > 0) {
busy = 1;
int i; int i;
for (i=0; i<pr->num_fds; i++) for (i=0; i<pr->num_fds; i++)
if (pr->fds[i].revents) if (pr->fds[i].revents)