summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Hall (GMCH) <chris.hall@highwayman.com>2009-12-08 11:32:36 +0000
committerChris Hall (GMCH) <chris.hall@highwayman.com>2009-12-08 11:32:36 +0000
commite60547f53337d552e28088d2f3c1b3296efb43c7 (patch)
treed750ab0c28e847c8f1139361791319f667274774
parent2c282bd4752f5eae9d5e40d687fdc6af2f203c91 (diff)
downloadquagga-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.c113
-rw-r--r--lib/heap.h46
-rw-r--r--lib/qtimers.c100
-rw-r--r--lib/qtimers.h30
4 files changed, 177 insertions, 112 deletions
diff --git a/lib/heap.c b/lib/heap.c
index 9681525a..35a1b51d 100644
--- a/lib/heap.c
+++ b/lib/heap.c
@@ -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)) ;
diff --git a/lib/heap.h b/lib/heap.h
index 2d2289bd..bd984398 100644
--- a/lib/heap.h
+++ b/lib/heap.h
@@ -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.