summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ccan/timer/test/run-add.c1
-rw-r--r--ccan/timer/test/run-expiry.c1
-rw-r--r--ccan/timer/test/run-ff.c1
-rw-r--r--ccan/timer/test/run.c9
-rw-r--r--ccan/timer/timer.c16
-rw-r--r--ccan/timer/timer.h23
6 files changed, 44 insertions, 7 deletions
diff --git a/ccan/timer/test/run-add.c b/ccan/timer/test/run-add.c
index a7ea4f60..e97bf781 100644
--- a/ccan/timer/test/run-add.c
+++ b/ccan/timer/test/run-add.c
@@ -32,6 +32,7 @@ int main(void)
add_level(&timers, i);
i = 0;
+ timer_init(&t);
for (diff = 0; diff < (1ULL << MAX_ORD)+2; diff = next(diff)) {
i++;
for (timers.base = 0;
diff --git a/ccan/timer/test/run-expiry.c b/ccan/timer/test/run-expiry.c
index d2969d25..1c276c2c 100644
--- a/ccan/timer/test/run-expiry.c
+++ b/ccan/timer/test/run-expiry.c
@@ -13,6 +13,7 @@ int main(void)
timers_init(&timers, grains_to_time(1364984760903400ULL));
ok1(timers.base == 1364984760903400ULL);
+ timer_init(&t);
timer_add(&timers, &t, grains_to_time(1364984761003398ULL));
ok1(t.time == 1364984761003398ULL);
ok1(timers.first == 1364984761003398ULL);
diff --git a/ccan/timer/test/run-ff.c b/ccan/timer/test/run-ff.c
index 148b7f79..49c6e374 100644
--- a/ccan/timer/test/run-ff.c
+++ b/ccan/timer/test/run-ff.c
@@ -18,6 +18,7 @@ int main(void)
plan_tests(3);
timers_init(&timers, timeabs_from_usec(1364726722653919ULL));
+ timer_init(&t);
timer_add(&timers, &t, timeabs_from_usec(1364726722703919ULL));
ok1(!timers_expire(&timers, timeabs_from_usec(1364726722653920ULL)));
expired = timers_expire(&timers, timeabs_from_usec(1364726725454187ULL));
diff --git a/ccan/timer/test/run.c b/ccan/timer/test/run.c
index f7b711f2..51648fb1 100644
--- a/ccan/timer/test/run.c
+++ b/ccan/timer/test/run.c
@@ -24,6 +24,10 @@ int main(void)
ok1(timers_check(&timers, NULL));
ok1(!timer_earliest(&timers, &earliest));
+ timer_init(&t[0]);
+ /* timer_del can be called immediately after init. */
+ timer_del(&timers, &t[0]);
+
timer_add(&timers, &t[0], timeabs_from_nsec(1));
ok1(timers_check(&timers, NULL));
ok1(timer_earliest(&timers, &earliest));
@@ -32,10 +36,15 @@ int main(void)
ok1(timers_check(&timers, NULL));
ok1(!timer_earliest(&timers, &earliest));
+ /* timer_del can be called twice, no problems. */
+ timer_del(&timers, &t[0]);
+
/* Check timer ordering. */
for (i = 0; i < 32; i++) {
+ timer_init(&t[i*2]);
timer_add(&timers, &t[i*2], timeabs_from_nsec(1ULL << i));
ok1(timers_check(&timers, NULL));
+ timer_init(&t[i*2+1]);
timer_add(&timers, &t[i*2+1], timeabs_from_nsec((1ULL << i) + 1));
ok1(timers_check(&timers, NULL));
}
diff --git a/ccan/timer/timer.c b/ccan/timer/timer.c
index c1979fd3..0abf05cd 100644
--- a/ccan/timer/timer.c
+++ b/ccan/timer/timer.c
@@ -63,8 +63,20 @@ static void timer_add_raw(struct timers *timers, struct timer *t)
list_add_tail(l, &t->list);
}
+void timer_init(struct timer *t)
+{
+ list_node_init(&t->list);
+}
+
+static bool list_node_initted(const struct list_node *n)
+{
+ return n->prev == n;
+}
+
void timer_add(struct timers *timers, struct timer *t, struct timeabs when)
{
+ assert(list_node_initted(&t->list));
+
t->time = time_to_grains(when);
/* Added in the past? Treat it as imminent. */
@@ -79,7 +91,7 @@ void timer_add(struct timers *timers, struct timer *t, struct timeabs when)
/* FIXME: inline */
void timer_del(struct timers *timers, struct timer *t)
{
- list_del(&t->list);
+ list_del_init(&t->list);
}
static void timers_far_get(struct timers *timers,
@@ -285,6 +297,8 @@ struct timer *timers_expire(struct timers *timers, struct timeabs expire)
/* This *may* be NULL, if we deleted the first timer */
t = list_pop(&timers->level[0]->list[off], struct timer, list);
+ if (t)
+ list_node_init(&t->list);
} while (!t && update_first(timers));
return t;
diff --git a/ccan/timer/timer.h b/ccan/timer/timer.h
index aeb2aebc..7a9fb075 100644
--- a/ccan/timer/timer.h
+++ b/ccan/timer/timer.h
@@ -45,28 +45,39 @@ void timers_init(struct timers *timers, struct timeabs start);
void timers_cleanup(struct timers *timers);
/**
+ * timer_init - initialize a timer.
+ * @timer: the timer to initialize
+ *
+ * Example:
+ * struct timer t;
+ *
+ * timer_init(&t);
+ */
+void timer_init(struct timer *t);
+
+/**
* timer_add - insert a timer.
* @timers: the struct timers
- * @timer: the (uninitialized) timer to add
+ * @timer: the (initialized or timer_del'd) timer to add
* @when: when @timer expires.
*
* This efficiently adds @timer to @timers, to expire @when (rounded to
* TIMER_GRANULARITY nanoseconds).
*
* Example:
- * struct timer t;
- *
* // Timeout in 100ms.
* timer_add(&timeouts, &t, timeabs_add(time_now(), time_from_msec(100)));
*/
void timer_add(struct timers *timers, struct timer *timer, struct timeabs when);
/**
- * timer_del - remove an unexpired timer.
+ * timer_del - remove a timer.
* @timers: the struct timers
- * @timer: the timer previously added with timer_add()
+ * @timer: the timer
*
- * This efficiently removes @timer from @timers.
+ * This efficiently removes @timer from @timers, if timer_add() was
+ * called. It can be called multiple times without bad effect, and
+ * can be called any time after timer_init().
*
* Example:
* timer_del(&timeouts, &t);