diff options
author | Chris Hall (GMCH) <chris.hall@highwayman.com> | 2009-12-08 11:32:36 +0000 |
---|---|---|
committer | Chris Hall (GMCH) <chris.hall@highwayman.com> | 2009-12-08 11:32:36 +0000 |
commit | e60547f53337d552e28088d2f3c1b3296efb43c7 (patch) | |
tree | d750ab0c28e847c8f1139361791319f667274774 | |
parent | 2c282bd4752f5eae9d5e40d687fdc6af2f203c91 (diff) | |
download | quagga-e60547f53337d552e28088d2f3c1b3296efb43c7.tar.bz2 quagga-e60547f53337d552e28088d2f3c1b3296efb43c7.tar.xz |
Added qtimer_pile_top_time() to lib/qtimers.c
For use when preparing for pselect or other timed wait.
Simplified the handling of pending unsets.
Tidied up in heap.c & .h.
-rw-r--r-- | lib/heap.c | 113 | ||||
-rw-r--r-- | lib/heap.h | 46 | ||||
-rw-r--r-- | lib/qtimers.c | 100 | ||||
-rw-r--r-- | lib/qtimers.h | 30 |
4 files changed, 177 insertions, 112 deletions
@@ -60,7 +60,7 @@ * ---------------------------- * Comparison function for heap. * - * int heap_cmp(...** a, ...**) ... + * int heap_cmp(...** a, ...** b) ... * * Must return -1, 0, +1 : where -1 => a < b, 0 => a == b & +1 => a > b * @@ -90,6 +90,9 @@ heap_setup(heap h, int new_vector, vector_index size, heap_cmp* cmp, * * ... = heap_new_init_simple(NULL, 0, (heap_cmp*)my_cmp) * + * See: #define heap_init_new_simple(h, size, cmp) + * #define heap_init_new_backlinked(h, size, cmp, offset) + * * NB: when initialising an existing heap structure it is ESSENTIAL that * any previous heap and its contents have been released, because this * function simply discards whatever was there before. (This function may @@ -107,15 +110,17 @@ heap_setup(heap h, int new_vector, vector_index size, heap_cmp* cmp, * a field of type heap_backlink_t in the item structure, and it is the * offset of that which must be initialised here, eg: * - * ... = heap_new_init_backlink(NULL, 0, (heap_cmp*)my_cmp, + * ... = heap_new_init_backlinked(NULL, 0, (heap_cmp*)my_cmp, * offset_of(struct xxx_heap_item, backlink)) ; * * This adds a little extra work to every change in the heap -- keeping the * backlink of any moved item up to date. But avoids a linear search for * every heap_delete_item or heap_update_item. + * + * Returns the heap which has been initialised. */ heap -heap_init_new(heap h, vector_index size, heap_cmp* cmp, +heap_init_new(heap h, unsigned int size, heap_cmp* cmp, int with_backlink, unsigned int backlink_offset) { if (h == NULL) @@ -126,16 +131,21 @@ heap_init_new(heap h, vector_index size, heap_cmp* cmp, return heap_setup(h, 1, size, cmp, with_backlink, backlink_offset) ; } ; -/* Re-Initialize heap (or create a new one, if h == NULL). +/* Reinitialise heap (or create a new one, if h == NULL). * * Allocates heap structure if none given -- allocating vector if size != 0. * Otherwise, re-initialise the heap and any vector (reusing its memory). * - * NB: when re-initialising an existing heap it is the caller's + * See: #define heap_re_init_simple(h, size, cmp) + * #define heap_re_init_backlinked(h, size, cmp, offset) + * + * NB: when reinitialising an existing heap it is the caller's * responsibility to release any item values *before* doing this. + * + * Returns the heap that has been reinitialised. */ heap -heap_re_init(heap h, vector_index size, heap_cmp* cmp, +heap_re_init(heap h, unsigned int size, heap_cmp* cmp, int with_backlink, unsigned int backlink_offset) { if (h == NULL) @@ -147,7 +157,7 @@ heap_re_init(heap h, vector_index size, heap_cmp* cmp, /* Release heap contents (underlying vector), and (if required) release the * heap structure. * - * Return NULL if releases heap, otherwise the address of the heap. + * Returns NULL if releases heap, otherwise the reset heap. * * If does not release the heap, it retains the comparison function and any * backlink setting -- so heap can be reused without reinitialising it. @@ -158,7 +168,7 @@ heap_re_init(heap h, vector_index size, heap_cmp* cmp, heap heap_reset(heap h, int free_structure) { - vector_reset(&h->v, 0) ; + vector_reset_keep(&h->v) ; /* vector structure is embedded in the heap */ if (free_structure) XFREE(MTYPE_VECTOR, h) ; /* sets h = NULL */ @@ -169,7 +179,7 @@ heap_reset(heap h, int free_structure) /* Common set-up for heap_init_new() & heap_reset(). */ static heap -heap_setup(heap h, int new_vector, vector_index size, heap_cmp* cmp, +heap_setup(heap h, int new_vector, unsigned int size, heap_cmp* cmp, int with_backlink, unsigned int backlink_offset) { assert(cmp != NULL) ; /* or there will be tears */ @@ -191,9 +201,12 @@ heap_setup(heap h, int new_vector, vector_index size, heap_cmp* cmp, * If heap is empty, release the underlying vector, and (if required) release * the heap structure. * + * See: #define heap_ream_free(h) heap_ream(h, 1) + * #define heap_ream_keep(h) heap_ream(h, 0) + * * Useful for emptying out and resetting/discarding a heap: * - * while ((p_v = heap_ream(h, 1))) + * while ((p_v = heap_ream_free(h))) * ... do what's required to release the item p_v * * Returns NULL when heap is empty (and structure has been freed, if required). @@ -226,7 +239,7 @@ heap_ream(heap h, int free_structure) /* Pop item off the heap. * - * Returns NULL if heap is empty. + * Returns the popped value, which is NULL if the heap was (and still is) empty. */ p_vector_item heap_pop_item(heap h) @@ -247,9 +260,9 @@ heap_pop_item(heap h) /* Pop one item off the heap and promptly push another. * - * In this combination the pop is essentially free. + * In this combination, the pop is essentially free. * - * Returns NULL if heap was empty. + * Returns the popped value, which is NULL if the heap was (and still is) empty. */ p_vector_item heap_pop_push_item(heap h, p_vector_item p_v) @@ -285,15 +298,13 @@ heap_delete_item(heap h, p_vector_item p_v) p_vector_item p_x ; vector_index i ; - i = heap_find_item(h, p_v) ; - - p_x = vector_pop_item(&h->v) ; /* extract last item, if any */ + i = heap_find_item(h, p_v) ; /* index of item to be deleted */ - if (i == h->v.end) - return ; /* stop now if deleting last item */ + p_x = vector_pop_item(&h->v) ; /* extract last item, if any */ - heap_bubble(h, i, p_x) ; /* move what was last into position */ - /* updating any backlink */ + if (i < h->v.end) /* if not deleting the last item... */ + heap_bubble(h, i, p_x) ; /* ...reinsert what was last, at the delete */ + /* position, updating any backlink */ } ; /*============================================================================== @@ -303,7 +314,10 @@ heap_delete_item(heap h, p_vector_item p_v) /* Push entire vector onto heap copying or moving items as required. * * Copy or move vector to end of heap's vector, then move each - * (non-NULL) item into heap order. + * (non-NULL) item into heap order (discarding any NULL items). + * + * See: #define heap_push_vector_copy(h, v) + * #define heap_push_vector_move(h, v) */ void heap_push_vector(heap h, vector v, int move_vector) @@ -311,6 +325,7 @@ heap_push_vector(heap h, vector v, int move_vector) vector_index i = h->v.end ; vector_index e ; vector_index n = v->end ; + p_vector_item p_v ; if (move_vector) vector_move_append(&h->v, v) ; @@ -319,7 +334,7 @@ heap_push_vector(heap h, vector v, int move_vector) e = i ; /* old end of the heap. */ while (n--) { - p_vector_item p_v = h->v.p_items[i++] ; + p_v = h->v.p_items[i++] ; if (p_v != NULL) heap_bubble_up(h, e++, p_v) ; /* move new item into position in heap */ /* setting any backlink */ @@ -334,6 +349,9 @@ heap_push_vector(heap h, vector v, int move_vector) * * Moves or copies the contents of the heap. * + * See: #define heap_pop_vector_copy(v, h) + * #define heap_pop_vector_move(v, h) + * * NB: when creating new vector, will be exactly the required size. * * NB: if re-initialising existing vector, it is the caller's responsibility @@ -406,18 +424,23 @@ heap_bubble(heap h, vector_index i, p_vector_item p_v) private void heap_bubble_up(heap h, vector_index i, p_vector_item p_v) { - p_vector_item* ha = h->v.p_items ; /* underlying array */ + p_vector_item* ha = h->v.p_items ; /* underlying array */ + vector_index ip ; /* index of parent */ + p_vector_item p_p ; /* pointer to parent item */ + dassert(ha != NULL) ; while (i != 0) { - vector_index ip = HEAP_UP(i) ; - p_vector_item p_p = &ha[ip] ; /* pointer to parent */ + ip = HEAP_UP(i) ; + p_p = &ha[ip] ; /* get parent */ + + if (h->cmp(&p_v, &p_p) >= 0) + break ; /* stop when value >= parent */ - if (h->cmp(&p_p, &p_v) <= 0) - break ; /* stop when parent is <= us */ ha[i] = p_p ; /* move parent down... */ heap_set_backlink(h, p_p, i) ; /* ...updating any backlink */ + i = ip ; /* move up the heap */ } ; @@ -433,38 +456,40 @@ heap_bubble_up(heap h, vector_index i, p_vector_item p_v) private void heap_bubble_down(heap h, vector_index i, p_vector_item p_v) { - vector_index e = h->v.end ; /* end of heap */ - p_vector_item* ha = h->v.p_items ; /* underlying array */ + vector_index e = h->v.end ; /* end of heap */ + vector_index ic ; /* index of child */ + vector_index is ; /* index of sibling */ + p_vector_item p_c ; /* pointer to child */ + p_vector_item p_s ; /* pointer to sibling */ + + p_vector_item* ha = h->v.p_items ; /* underlying array */ dassert(ha != NULL) ; while (1) { - vector_index ic ; /* index of child */ - vector_index is ; /* index of sibling */ - p_vector_item p_c ; /* pointer to child */ - p_vector_item p_s ; /* pointer to sibling */ - ic = HEAP_DOWN(i) ; if (ic >= e) - break ; /* Quit if run out of heap ! */ - p_c = &ha[ic] ; + break ; /* Quit if run out of heap ! */ + p_c = &ha[ic] ; /* get left hand child */ is = ic + 1 ; - if (is < e) + if (is < e) /* is there a right hand child ? */ { - p_s = &ha[is] ; + p_s = &ha[is] ; /* get right hand child */ if (h->cmp(&p_s, &p_c) < 0) { - ic = is ; /* select smaller sibling */ + ic = is ; /* select smaller sibling */ p_c = p_s ; } ; } ; if (h->cmp(&p_v, &p_c) <= 0) - break ; /* stop when we are <= both children */ - ha[i] = p_c ; /* move smaller child up */ - heap_set_backlink(h, p_c, i) ; /* ...updating any backlink */ - i = ic ; /* move down the heap */ + break ; /* stop when <= both children */ + + ha[i] = p_c ; /* move smaller child up */ + heap_set_backlink(h, p_c, i) ; /* ...updating any backlink */ + + i = ic ; /* move down the heap */ } ; ha[i] = p_v ; /* place in new position... */ @@ -483,7 +508,7 @@ heap_find_item(heap h, p_vector_item p_v) { for (i = 0 ; i < h->v.end ; ++i) if (h->v.p_items[i] == p_v) - break ; + return i ; } ; assert((i < h->v.end) && (h->v.p_items[i] == p_v)) ; @@ -24,11 +24,19 @@ #define Inline static inline #endif +/*============================================================================== + * Data structures etc. + */ + typedef int heap_cmp(p_vector_item* a, p_vector_item*) ; enum heap_state { Heap_Has_Backlink = 0x01, /* Set if backlink set */ -}; +} ; + +typedef vector_index heap_backlink_t ; + +typedef struct heap* heap ; struct heap { @@ -38,39 +46,37 @@ struct heap unsigned int backlink_offset ; struct vector v ; -}; - -typedef struct heap* heap; - -typedef vector_index heap_backlink_t ; +} ; -/* Prototypes. */ +/*============================================================================== + * Prototypes. + */ -extern heap heap_init_new(heap h, vector_index size, heap_cmp* cmp, +extern heap heap_init_new(heap h, unsigned int size, heap_cmp* cmp, int with_backlink, unsigned int backlink_offset) ; #define heap_init_new_simple(h, size, cmp) \ heap_init_new(h, size, cmp, 0, 0) -#define heap_init_new_backlinked(h, size, cmp, off) \ - heap_init_new(h, size, cmp, 1, off) +#define heap_init_new_backlinked(h, size, cmp, offset) \ + heap_init_new(h, size, cmp, 1, offset) -extern heap heap_re_init(heap h, vector_index size, heap_cmp* cmp, +extern heap heap_re_init(heap h, unsigned int size, heap_cmp* cmp, int with_backlink, unsigned int backlink_offset) ; #define heap_re_init_simple(h, size, cmp) \ heap_re_init(h, size, cmp, 0, 0) -#define heap_re_init_backlinked(h, size, cmp, off) \ - heap_re_init(h, size, cmp, 1, off) +#define heap_re_init_backlinked(h, size, cmp, offset) \ + heap_re_init(h, size, cmp, 1, offset) extern heap heap_reset(heap h, int free_structure) ; extern p_vector_item heap_ream(heap h, int free_structure) ; /* Reset heap and free the heap structure. */ -#define heap_reset_free(h) heap_reset(h, 1) ; +#define heap_reset_free(h) heap_reset(h, 1) /* Reset heap but keep the heap structure. */ -#define heap_reset_keep(h) heap_reset(h, 0) ; +#define heap_reset_keep(h) heap_reset(h, 0) /* Ream out heap and free the heap structure. */ -#define heap_ream_free(h) heap_ream(h, 1) ; +#define heap_ream_free(h) heap_ream(h, 1) /* Ream out heap but keep the heap structure. */ -#define heap_ream_keep(h) heap_ream(h, 0) ; +#define heap_ream_keep(h) heap_ream(h, 0) Inline void heap_push_item(heap h, p_vector_item p_v) ; extern p_vector_item heap_pop_item(heap h) ; @@ -92,8 +98,6 @@ extern vector heap_pop_vector(vector v, heap h, int move_heap) ; #define heap_pop_vector_move(v, h) \ heap_pop_vector(v, h, 1) -extern vector heap_vector(heap h, int unset_heap_order) ; - /*============================================================================== * This are extern only for use in Inline and other friends */ @@ -146,10 +150,8 @@ heap_update_top_item(heap h) } ; /* Update heap to reflect new value of given item. - * - * See notes on backlink, above. */ -void +Inline void heap_update_item(heap h, p_vector_item p_v) { heap_bubble(h, heap_find_item(h, p_v), p_v) ; diff --git a/lib/qtimers.c b/lib/qtimers.c index 6d3932fc..f4959983 100644 --- a/lib/qtimers.c +++ b/lib/qtimers.c @@ -44,8 +44,8 @@ * Timers are triggered by calling qtimer_dispatch_next(). This is given the * current qtimer time (see below), and it dispatches the first timer whose * time has come (or been passed). Dispatching a timer means calling its - * action function (see below). Each call of qtimer_dispatch_next triggers at - * most one timer. + * action function (see below). Each call of qtimer_dispatch_next() triggers + * at most one timer. * * Time Base * --------- @@ -65,7 +65,8 @@ * timer (which may, or may not, be the current qtimer time). * * During an action function timers may be set/unset, actions changed, and so - * on... there are no restrictions. + * on... there are no restrictions EXCEPT that the qtimer structure may NOT be + * freed. */ static int @@ -92,7 +93,7 @@ qtimer_pile_init_new(qtimer_pile qtp) if (qtp == NULL) qtp = XCALLOC(MTYPE_QTIMER_PILE, sizeof(struct qtimer_pile)) ; else - memset(qtp, 0, sizeof(struct qtimer_pile)) ; + memset(qtp, 0, sizeof(struct qtimer_pile)) ; /* Zeroising has initialised: * @@ -109,6 +110,23 @@ qtimer_pile_init_new(qtimer_pile qtp) return qtp ; } ; +/* Get the timer time for the first timer due to go off in the given pile. + * + * The caller must provide a maximum acceptable time. If the qtimer pile is + * empty, or the top entry times out after the maximum time, then the maximum + * is returned. + */ +qtime_t +qtimer_pile_top_time(qtimer_pile qtp, qtime_t max_time) +{ + qtimer qtr = heap_top_item(&qtp->timers) ; + + if ((qtr == NULL) || (qtr->time >= max_time)) + return max_time ; + else + return qtr->time ; +} ; + /* Dispatch the next timer whose time is <= the given "upto" time. * * The upto time must be a qtimer time (!) -- see qtimer_time_now(). @@ -124,18 +142,15 @@ qtimer_pile_dispatch_next(qtimer_pile qtp, qtime_t upto) { qtimer qtr ; - if (qtp->unset_pending != NULL) - qtimer_unset(qtp->unset_pending) ; /* just in case recurse through here */ - qtr = heap_top_item(&qtp->timers) ; if ((qtr != NULL) && (qtr->time <= upto)) { - qtp->unset_pending = qtr ; /* delay unset of top item, pro tem...*/ + qtr->state = qtr_state_unset_pending ; qtr->action(qtr, qtr->timer_info, upto) ; - if (qtp->unset_pending != NULL) /* ...now must unset if not yet done */ - qtimer_unset(qtp->unset_pending) ; + if (qtr->state == qtr_state_unset_pending) + qtimer_unset(qtr) ; return 1 ; } @@ -147,9 +162,12 @@ qtimer_pile_dispatch_next(qtimer_pile qtp, qtime_t upto) * * If pile is empty, release the qtimer_pile structure, if required. * + * See: #define qtimer_pile_ream_free(qtp) + * #define qtimer_pile_ream_keep(qtp) + * * Useful for emptying out and discarding a pile of timers: * - * while ((p_qtr = qtimer_pile_ream(qtp, 1))) + * while ((p_qtr = qtimer_pile_ream_free(qtp))) * ... do what's required to release the item p_qtr * * Returns NULL when timer pile is empty (and has been released, if required). @@ -166,15 +184,10 @@ qtimer_pile_ream(qtimer_pile qtp, int free_structure) qtr = heap_ream_keep(&qtp->timers) ; /* ream, keeping the heap structure */ if (qtr != NULL) - qtr->active = 0 ; /* already removed from pile */ + qtr->state = qtr_state_inactive ; /* has been removed from pile */ else - { - if (free_structure) - XFREE(MTYPE_QTIMER_PILE, qtp) ; - else - qtp->unset_pending = NULL ; /* heap is empty, so this is last thing */ - /* to be tidied up. */ - } ; + if (free_structure) /* pile is empty, may now free it */ + XFREE(MTYPE_QTIMER_PILE, qtp) ; return qtr ; } ; @@ -186,7 +199,7 @@ qtimer_pile_ream(qtimer_pile qtp, int free_structure) /* Initialise qtimer structure -- allocating one if required. * * Associates qtimer with the given pile of timers, and sets up the action and - * the timer_info ready for use. + * the timer_info. * * Once initialised, the timer may be set. * @@ -199,20 +212,22 @@ qtimer_init_new(qtimer qtr, qtimer_pile qtp, if (qtr == NULL) qtr = XCALLOC(MTYPE_QTIMER, sizeof(struct qtimer)) ; else - memset(qtr, 0, sizeof(struct qtimer)) ; + memset(qtr, 0, sizeof(struct qtimer)) ; /* Zeroising has initialised: * * pile -- NULL -- not in any pile (yet) * backlink -- unset * - * active -- not active + * state -- not active * * time -- unset * action -- NULL -- no action set (yet) * timer_info -- NULL -- no timer info set (yet) */ + confirm(qtr_state_inactive == 0) ; + qtr->pile = qtp ; qtr->action = action ; qtr->timer_info = timer_info ; @@ -223,11 +238,15 @@ qtimer_init_new(qtimer qtr, qtimer_pile qtp, /* Free given timer. * * Unsets it first if it is active. + * + * The timer MAY NOT be currently the subject of qtimer_pile_dispatch_next(). */ void qtimer_free(qtimer qtr) { - if (qtr->active) + assert(qtr->state != qtr_state_unset_pending) ; + + if (qtr->state != qtr_state_inactive) qtimer_unset(qtr) ; XFREE(MTYPE_QTIMER, qtr) ; @@ -241,7 +260,7 @@ qtimer_free(qtimer qtr) void qtimer_set_pile(qtimer qtr, qtimer_pile qtp) { - if ((qtr->active) && (qtr->pile != qtp)) + if (qtr_is_active(qtr) && (qtr->pile != qtp)) qtimer_unset(qtr) ; qtr->pile = qtp ; } @@ -266,12 +285,17 @@ qtimer_set_info(qtimer qtr, void* timer_info) * * Setting a -ve time => qtimer_unset. * + * Sets any given action -- if the action given is NULL, retains previously set + * action. + * * If the timer is already active, sets the new time & updates pile. * * Otherwise, sets the time and adds to pile -- making timer active. + * + * It is an error to set a timer which has a NULL action. */ void -qtimer_set(qtimer qtr, qtime_t when) +qtimer_set(qtimer qtr, qtime_t when, qtimer_action* action) { qtimer_pile qtp ; @@ -283,17 +307,17 @@ qtimer_set(qtimer qtr, qtime_t when) qtr->time = when ; - if (qtr->active) - { - heap_update_item(&qtp->timers, qtr) ; /* update in heap */ - if (qtr == qtp->unset_pending) - qtp->unset_pending = NULL ; /* dealt with. */ - } + if (qtr_is_active(qtr)) + heap_update_item(&qtp->timers, qtr) ; /* update in heap */ else - { - heap_push_item(&qtp->timers, qtr) ; /* add to heap */ - qtr->active = 1 ; - } ; + heap_push_item(&qtp->timers, qtr) ; /* add to heap */ + + qtr->state = qtr_state_active ; /* overrides any unset pending */ + + if (action != NULL) + qtr->action = action ; + else + dassert(qtr->action != NULL) ; } ; /* Unset given timer @@ -303,15 +327,13 @@ qtimer_set(qtimer qtr, qtime_t when) void qtimer_unset(qtimer qtr) { - if (qtr->active) + if (qtr_is_active(qtr)) { qtimer_pile qtp = qtr->pile ; dassert(qtp != NULL) ; heap_delete_item(&qtp->timers, qtr) ; - if (qtr == qtp->unset_pending) - qtp->unset_pending = NULL ; - qtr->active = 0 ; + qtr->state = qtr_state_inactive ; /* overrides any unset pending */ } ; } ; diff --git a/lib/qtimers.h b/lib/qtimers.h index 65154a7a..37f55d89 100644 --- a/lib/qtimers.h +++ b/lib/qtimers.h @@ -46,12 +46,22 @@ typedef struct qtimer_pile* qtimer_pile ; typedef void (qtimer_action)(qtimer qtr, void* timer_info, qtime_t when) ; +enum qtimer_state { + qtr_state_inactive = 0, + qtr_state_active = 1, /* timer is active in its pile */ + qtr_state_unset_pending = 3 /* timer is active, but unset is pending */ +} ; + +#define qtr_is_active(qtr) ((qtr)->state != qtr_state_inactive) + +typedef enum qtimer_state qtimer_state_t ; + struct qtimer { qtimer_pile pile ; heap_backlink_t backlink ; - int active ; /* timer is active in the current pile. */ + qtimer_state_t state ; qtime_t time ; qtimer_action* action ; @@ -61,8 +71,6 @@ struct qtimer struct qtimer_pile { struct heap timers ; - - qtimer unset_pending ; } ; /*============================================================================== @@ -75,9 +83,17 @@ qtimer_pile_init_new(qtimer_pile qtp) ; int qtimer_pile_dispatch_next(qtimer_pile qtp, qtime_t upto) ; +qtime_t +qtimer_pile_top_time(qtimer_pile qtp, qtime_t max_time) ; + qtimer qtimer_pile_ream(qtimer_pile qtp, int free_structure) ; +/* Ream out qtimer pile and free the qtimer structure. */ +#define qtimer_pile_ream_free(qtp) qtimer_pile_ream(qtp, 1) +/* Ream out qtimer pile but keep the qtimer structure. */ +#define qtimer_pile_ream_keep(qtp) qtimer_pile_ream(qtp, 0) + Inline qtime_t qtimer_time_now() ; @@ -106,13 +122,13 @@ void qtimer_free(qtimer qtr) ; void -qtimer_set(qtimer qtr, qtime_t when) ; +qtimer_set(qtimer qtr, qtime_t when, qtimer_action* action) ; void qtimer_unset(qtimer qtr) ; Inline void -qtimer_add(qtimer qtr, qtime_t interval) ; +qtimer_add(qtimer qtr, qtime_t interval, qtimer_action* action) ; Inline qtime_t qtimer_get(qtimer qtr) ; @@ -156,9 +172,9 @@ qtimer_time_from_timeofday(qtime_t timeofday) /* Set given timer to given time later than *its* current time. */ Inline void -qtimer_add(qtimer qtr, qtime_t interval) +qtimer_add(qtimer qtr, qtime_t interval, qtimer_action* action) { - qtimer_set(qtr, qtimer_get(qtr) + interval); + qtimer_set(qtr, qtimer_get(qtr) + interval, action); } ; /* Get the given timer's time. |