* {
* struct timers timers;
* struct list_head strings;
- * struct list_head expired;
+ * struct timer *t;
* struct timed_string *s;
*
* timers_init(&timers, time_now());
* struct timeabs now = time_now();
* list_for_each(&strings, s, node)
* printf("%s", s->string);
- * timers_expire(&timers, now, &expired);
- * while ((s = list_pop(&expired, struct timed_string,
- * timer.list)) != NULL) {
+ * while ((t = timers_expire(&timers, now)) != NULL) {
+ * s = container_of(t, struct timed_string, timer);
* list_del_from(&strings, &s->node);
* free(s);
* }
curr = time_add(curr, time_from_msec(1));
if (check)
timers_check(&timers, NULL);
- timers_expire(&timers, curr, &expired);
+ if (timers_expire(&timers, curr))
+ abort();
if (check)
timers_check(&timers, NULL);
- assert(list_empty(&expired));
if (i >= PER_CONN_TIME) {
timer_del(&timers, &t[i%PER_CONN_TIME]);
{
struct timers timers;
struct timer t;
- struct list_head list;
/* This is how many tests you plan to run */
plan_tests(7);
timer_add(&timers, &t, grains_to_time(1364984761003398ULL));
ok1(t.time == 1364984761003398ULL);
ok1(timers.first == 1364984761003398ULL);
- timers_expire(&timers, grains_to_time(1364984760903444ULL), &list);
+ ok1(!timers_expire(&timers, grains_to_time(1364984760903444ULL)));
ok1(timers_check(&timers, NULL));
- ok1(list_pop(&list, struct timer, list) == NULL);
- timers_expire(&timers, grains_to_time(1364984761002667ULL), &list);
+ ok1(!timers_expire(&timers, grains_to_time(1364984761002667ULL)));
ok1(timers_check(&timers, NULL));
- ok1(list_pop(&list, struct timer, list) == NULL);
timers_cleanup(&timers);
int main(void)
{
struct timers timers;
- struct timer t;
- struct list_head expired;
+ struct timer t, *expired;
/* This is how many tests you plan to run */
plan_tests(3);
timers_init(&timers, timeabs_from_usec(1364726722653919ULL));
timer_add(&timers, &t, timeabs_from_usec(1364726722703919ULL));
- timers_expire(&timers, timeabs_from_usec(1364726722653920ULL), &expired);
- ok1(list_empty(&expired));
- timers_expire(&timers, timeabs_from_usec(1364726725454187ULL), &expired);
- ok1(!list_empty(&expired));
- ok1(list_top(&expired, struct timer, list) == &t);
-
+ ok1(!timers_expire(&timers, timeabs_from_usec(1364726722653920ULL)));
+ expired = timers_expire(&timers, timeabs_from_usec(1364726725454187ULL));
+ ok1(expired == &t);
+ ok1(!timers_expire(&timers, timeabs_from_usec(1364726725454187ULL)));
timers_cleanup(&timers);
/* This exits depending on whether all tests passed */
{
struct timers timers;
struct timer t[64];
- struct list_head expired;
struct timeabs earliest;
uint64_t i;
struct timeabs epoch = { { 0, 0 } };
struct timer *t1, *t2;
ok1(timer_earliest(&timers, &earliest));
- timers_expire(&timers, earliest, &expired);
-
- t1 = list_pop(&expired, struct timer, list);
+ t1 = timers_expire(&timers, earliest);
ok1(t1);
- t2 = list_pop(&expired, struct timer, list);
+ t2 = timers_expire(&timers, earliest);
ok1(t2);
- ok1(list_empty(&expired));
+ ok1(!timers_expire(&timers, earliest));
ok1(t1 == &t[i*2] || t1 == &t[i*2+1]);
ok1(t2 != t1 && (t2 == &t[i*2] || t2 == &t[i*2+1]));
timer_add_raw(timers, i);
}
-/* Fills list of expired timers. */
-void timers_expire(struct timers *timers,
- struct timeabs expire,
- struct list_head *list)
+/* Returns an expired timer. */
+struct timer *timers_expire(struct timers *timers, struct timeabs expire)
{
uint64_t now = time_to_grains(expire);
unsigned int off;
+ struct timer *t;
assert(now >= timers->base);
- list_head_init(list);
-
if (!timers->level[0]) {
if (list_empty(&timers->far))
- return;
+ return NULL;
add_level(timers, 0);
}
do {
if (timers->first > now) {
timer_fast_forward(timers, now);
- break;
+ return NULL;
}
timer_fast_forward(timers, timers->first);
off = timers->base % PER_LEVEL;
- list_append_list(list, &timers->level[0]->list[off]);
- if (timers->base == now)
- break;
- } while (update_first(timers));
+ /* This *may* be NULL, if we deleted the first timer */
+ t = list_pop(&timers->level[0]->list[off], struct timer, list);
+ } while (!t && update_first(timers));
+
+ return t;
}
static bool timer_list_check(const struct list_head *l,
bool timer_earliest(struct timers *timers, struct timeabs *first);
/**
- * timers_expire - update timers structure and remove expired timers.
+ * timers_expire - update timers structure and remove one expire timer.
* @timers: the struct timers
* @expire: the current time
- * @list: the list for expired timers.
*
- * @list will be initialized to the empty list, then all timers added
- * with a @when arg less than or equal to @expire will be added to it in
- * expiry order (within TIMER_GRANULARITY nanosecond precision).
+ * A timers added with a @when arg less than or equal to @expire will be
+ * returned (within TIMER_GRANULARITY nanosecond precision). If
+ * there are no timers due to expire, NULL is returned.
*
- * After this, @expire is considered the current time, and adding any
- * timers with @when before this value will be silently changed to
- * adding them with immediate expiration.
+ * After this returns NULL, @expire is considered the current time,
+ * and adding any timers with @when before this value will be silently
+ * changed to adding them with immediate expiration.
*
* You should not move @expire backwards, though it need not move
* forwards.
*
* Example:
- * struct list_head expired;
+ * struct timer *expired;
*
- * timers_expire(&timeouts, time_now(), &expired);
- * if (!list_empty(&expired))
+ * while ((expired = timers_expire(&timeouts, time_now())) != NULL)
* printf("Timer expired!\n");
+ *
*/
-void timers_expire(struct timers *timers,
- struct timeabs expire,
- struct list_head *list);
+struct timer *timers_expire(struct timers *timers, struct timeabs expire);
/**
* timers_check - check timer structure for consistency