From 43a2fa01834fd18d0a7788a58c5efad1c445a021 Mon Sep 17 00:00:00 2001 From: Stephan Bosch Date: Wed, 1 Oct 2014 00:03:17 +0300 Subject: [PATCH] lib: Added support for setting timeouts at absolute time, rather than relative to current time. --- src/lib/ioloop-private.h | 2 ++ src/lib/ioloop.c | 37 ++++++++++++++++++++++++++++++++----- src/lib/ioloop.h | 7 +++++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/lib/ioloop-private.h b/src/lib/ioloop-private.h index db6753de43..bd81f35fcd 100644 --- a/src/lib/ioloop-private.h +++ b/src/lib/ioloop-private.h @@ -69,6 +69,8 @@ struct timeout { struct ioloop *ioloop; struct ioloop_context *ctx; + + unsigned int one_shot:1; }; struct ioloop_context_callback { diff --git a/src/lib/ioloop.c b/src/lib/ioloop.c index 35e592e689..37c00e2cea 100644 --- a/src/lib/ioloop.c +++ b/src/lib/ioloop.c @@ -194,15 +194,14 @@ static void timeout_update_next(struct timeout *timeout, struct timeval *tv_now) } } -#undef timeout_add -struct timeout *timeout_add(unsigned int msecs, unsigned int source_linenum, +static struct timeout * +timeout_add_common(unsigned int source_linenum, timeout_callback_t *callback, void *context) { struct timeout *timeout; timeout = i_new(struct timeout, 1); timeout->source_linenum = source_linenum; - timeout->msecs = msecs; timeout->ioloop = current_ioloop; timeout->callback = callback; @@ -213,6 +212,18 @@ struct timeout *timeout_add(unsigned int msecs, unsigned int source_linenum, io_loop_context_ref(timeout->ctx); } + return timeout; +} + +#undef timeout_add +struct timeout *timeout_add(unsigned int msecs, unsigned int source_linenum, + timeout_callback_t *callback, void *context) +{ + struct timeout *timeout; + + timeout = timeout_add_common(source_linenum, callback, context); + timeout->msecs = msecs; + timeout_update_next(timeout, timeout->ioloop->running ? NULL : &ioloop_timeval); priorityq_add(timeout->ioloop->timeouts, &timeout->item); @@ -227,6 +238,20 @@ timeout_add_short(unsigned int msecs, unsigned int source_linenum, return timeout_add(msecs, source_linenum, callback, context); } +#undef timeout_add_absolute +struct timeout *timeout_add_absolute(const struct timeval *time, + unsigned int source_linenum, + timeout_callback_t *callback, void *context) +{ + struct timeout *timeout; + + timeout = timeout_add_common(source_linenum, callback, context); + timeout->one_shot = TRUE; + + priorityq_add(timeout->ioloop->timeouts, &timeout->item); + return timeout; +} + static void timeout_free(struct timeout *timeout) { if (timeout->ctx != NULL) @@ -407,8 +432,10 @@ static void io_loop_handle_timeouts_real(struct ioloop *ioloop) if (timeout_get_wait_time(timeout, &tv, &tv_call) > 0) break; - /* update timeout's next_run and reposition it in the queue */ - timeout_reset_timeval(timeout, &tv_call); + if (!timeout->one_shot) { + /* update timeout's next_run and reposition it in the queue */ + timeout_reset_timeval(timeout, &tv_call); + } if (timeout->ctx != NULL) io_loop_context_activate(timeout->ctx); diff --git a/src/lib/ioloop.h b/src/lib/ioloop.h index 8cc5577a20..f1f131b0e8 100644 --- a/src/lib/ioloop.h +++ b/src/lib/ioloop.h @@ -97,6 +97,13 @@ timeout_add_short(unsigned int msecs, unsigned int source_linenum, timeout_add_short(msecs, __LINE__ + \ CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \ (io_callback_t *)callback, context) +struct timeout *timeout_add_absolute(const struct timeval *time, + unsigned int source_linenum, + timeout_callback_t *callback, void *context) ATTR_NULL(4); +#define timeout_add_absolute(time, callback, context) \ + timeout_add_absolute(time, __LINE__ + \ + CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \ + (io_callback_t *)callback, context) /* Remove timeout handler, and set timeout pointer to NULL. */ void timeout_remove(struct timeout **timeout); /* Reset timeout so it's next run after now+msecs. */ -- 2.47.3