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;
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);
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));
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));
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));
}
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. */
/* 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,
/* 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;
*/
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);