From d13284da19d30159424b2f726cc403eda23a1e01 Mon Sep 17 00:00:00 2001 From: Bob Halley Date: Mon, 10 May 1999 22:50:31 +0000 Subject: [PATCH] allow timer to be inactive; use isc_task_purgerange --- lib/isc/include/isc/timer.h | 18 ++++++++------ lib/isc/timer.c | 49 ++++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/lib/isc/include/isc/timer.h b/lib/isc/include/isc/timer.h index f773af0d9f..03b52fc6b3 100644 --- a/lib/isc/include/isc/timer.h +++ b/lib/isc/include/isc/timer.h @@ -74,6 +74,7 @@ #include #include #include +#include #include ISC_LANG_BEGINDECLS @@ -86,18 +87,20 @@ typedef struct isc_timer isc_timer_t; typedef struct isc_timermgr isc_timermgr_t; typedef enum { - isc_timertype_ticker = 0, isc_timertype_once + isc_timertype_ticker = 0, + isc_timertype_once = 1, + isc_timertype_inactive = 2 } isc_timertype_t; typedef struct isc_timerevent { struct isc_event common; - /* XXX Anything else? XXX */ } isc_timerevent_t; -#define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 1) -#define ISC_TIMEREVENT_IDLE (ISC_EVENTCLASS_TIMER + 2) -#define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3) - +#define ISC_TIMEREVENT_FIRSTEVENT (ISC_EVENTCLASS_TIMER + 0) +#define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 1) +#define ISC_TIMEREVENT_IDLE (ISC_EVENTCLASS_TIMER + 2) +#define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3) +#define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535) /*** *** Timer and Timer Manager Functions @@ -140,7 +143,8 @@ isc_timer_create(isc_timermgr_t *manager, * * 'action' is a valid action * - * 'expires' and 'interval' may not both be 0 + * (type == isc_timertype_inactive && expires == NULL && interval == NULL) + * || ('expires' and 'interval' are not both 0) * * 'timerp' is a valid pointer, and *timerp == NULL * diff --git a/lib/isc/timer.c b/lib/isc/timer.c index ae615f1645..505e9280a0 100644 --- a/lib/isc/timer.c +++ b/lib/isc/timer.c @@ -98,6 +98,8 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { * Note: the caller must ensure locking. */ + REQUIRE(timer->type != isc_timertype_inactive); + /* * Compute the new due time. */ @@ -190,12 +192,15 @@ destroy(isc_timer_t *timer) { isc_timermgr_t *manager = timer->manager; /* - * The caller must ensure locking. + * The caller must ensure it is safe to destroy the timer. */ LOCK(&manager->lock); - isc_task_purge(timer->task, timer, ISC_TASKEVENT_ANYEVENT); + isc_task_purgerange(timer->task, + timer, + ISC_TASKEVENT_FIRSTEVENT, + ISC_TASKEVENT_LASTEVENT); deschedule(timer); UNLINK(manager->timers, timer, link); @@ -229,7 +234,9 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, REQUIRE(VALID_MANAGER(manager)); REQUIRE(task != NULL); REQUIRE(action != NULL); - REQUIRE(!(isc_time_isepoch(expires) && isc_interval_iszero(interval))); + REQUIRE((type == isc_timertype_inactive && + expires == NULL && interval == NULL) || + !(isc_time_isepoch(expires) && isc_interval_iszero(interval))); REQUIRE(timerp != NULL && *timerp == NULL); /* @@ -279,10 +286,13 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, * there are no external references to it yet. */ - result = schedule(timer, &now, ISC_TRUE); + if (type != isc_timertype_inactive) + result = schedule(timer, &now, ISC_TRUE); + else + result = ISC_R_SUCCESS; if (result == ISC_R_SUCCESS) APPEND(manager->timers, timer, link); - + UNLOCK(&manager->lock); if (result != ISC_R_SUCCESS) { @@ -316,7 +326,9 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, REQUIRE(VALID_TIMER(timer)); manager = timer->manager; REQUIRE(VALID_MANAGER(manager)); - REQUIRE(!(isc_time_isepoch(expires) && isc_interval_iszero(interval))); + REQUIRE((type == isc_timertype_inactive && + expires == NULL && interval == NULL) || + !(isc_time_isepoch(expires) && isc_interval_iszero(interval))); /* * Get current time. @@ -335,7 +347,10 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, LOCK(&timer->lock); if (purge) - isc_task_purge(timer->task, timer, ISC_TASKEVENT_ANYEVENT); + isc_task_purgerange(timer->task, + timer, + ISC_TASKEVENT_FIRSTEVENT, + ISC_TASKEVENT_LASTEVENT); timer->type = type; timer->expires = *expires; timer->interval = *interval; @@ -343,7 +358,11 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, isc_time_add(&now, interval, &timer->idle); else isc_time_settoepoch(&timer->idle); - result = schedule(timer, &now, ISC_TRUE); + if (type == isc_timertype_inactive) { + deschedule(timer); + result = ISC_R_SUCCESS; + } else + result = schedule(timer, &now, ISC_TRUE); UNLOCK(&timer->lock); UNLOCK(&manager->lock); @@ -364,7 +383,14 @@ isc_timer_touch(isc_timer_t *timer) { LOCK(&timer->lock); - INSIST(timer->type == isc_timertype_once); + /* + * We'd like to + * + * REQUIRE(timer->type == isc_timertype_once); + * + * but we cannot without locking the manager lock too, which we + * don't want to do. + */ result = isc_time_get(&now); if (result != ISC_R_SUCCESS) { @@ -430,8 +456,13 @@ dispatch(isc_timermgr_t *manager, isc_time_t *now) { isc_timer_t *timer; isc_result_t result; + /* + * The caller must be holding the manager lock. + */ + while (manager->nscheduled > 0 && !done) { timer = isc_heap_element(manager->heap, 1); + INSIST(timer->type != isc_timertype_inactive); if (isc_time_compare(now, &timer->due) >= 0) { if (timer->type == isc_timertype_ticker) { type = ISC_TIMEREVENT_TICK;