Merge with git+ssh://pasky.or.cz/srv/git/elinks.git
[elinks.git] / src / main / timer.c
blob1a362cd2d9a4e193b3972b99792065a88812025c
1 /* Timers. */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include "elinks.h"
9 #include "main/select.h"
10 #include "main/timer.h"
11 #include "util/error.h"
12 #include "util/lists.h"
13 #include "util/memory.h"
14 #include "util/time.h"
17 struct timer {
18 LIST_HEAD(struct timer);
20 timeval_T interval;
21 void (*func)(void *);
22 void *data;
25 /* @timers.next points to the timer with the smallest interval,
26 * @timers.next->next to the second smallest, and so on. */
27 static INIT_LIST_HEAD(timers);
29 int
30 get_timers_count(void)
32 return list_size(&timers);
36 void
37 check_timers(timeval_T *last_time)
39 timeval_T now;
40 timeval_T interval;
41 struct timer *timer;
43 timeval_now(&now);
44 timeval_sub(&interval, last_time, &now);
46 foreach (timer, timers) {
47 timeval_sub_interval(&timer->interval, &interval);
50 while (!list_empty(timers)) {
51 timer = timers.next;
53 if (timeval_is_positive(&timer->interval))
54 break;
56 del_from_list(timer);
57 /* At this point, *@timer is to be considered invalid
58 * outside timers.c; if anything e.g. passes it to
59 * @kill_timer, that's a bug. However, @timer->func
60 * and @check_bottom_halves can still call @kill_timer
61 * on other timers, so this loop must be careful not to
62 * keep pointers to them. (bug 868) */
63 timer->func(timer->data);
64 mem_free(timer);
65 check_bottom_halves();
68 timeval_copy(last_time, &now);
71 /* Install a timer that calls @func(@data) after @delay milliseconds.
72 * Store to *@id either the ID of the new timer, or TIMER_ID_UNDEF if
73 * the timer cannot be installed. (This function ignores the previous
74 * value of *@id in any case.)
76 * When @func is called, the timer ID has become invalid. @func
77 * should erase the expired timer ID from all variables, so that
78 * there's no chance it will be given to @kill_timer later. */
79 void
80 install_timer(timer_id_T *id, milliseconds_T delay, void (*func)(void *), void *data)
82 struct timer *new_timer, *timer;
84 assert(id && delay > 0);
86 new_timer = mem_alloc(sizeof(*new_timer));
87 *id = (timer_id_T) new_timer; /* TIMER_ID_UNDEF is NULL */
88 if (!new_timer) return;
90 timeval_from_milliseconds(&new_timer->interval, delay);
91 new_timer->func = func;
92 new_timer->data = data;
94 foreach (timer, timers) {
95 if (timeval_cmp(&timer->interval, &new_timer->interval) >= 0)
96 break;
99 add_at_pos(timer->prev, new_timer);
102 void
103 kill_timer(timer_id_T *id)
105 struct timer *timer;
107 assert(id != NULL);
108 if (*id == TIMER_ID_UNDEF) return;
110 timer = *id;
111 del_from_list(timer);
112 mem_free(timer);
114 *id = TIMER_ID_UNDEF;
118 get_next_timer_time(timeval_T *t)
120 if (!list_empty(timers)) {
121 timeval_copy(t, &((struct timer *) &timers)->next->interval);
122 return 1;
125 return 0;