-
Notifications
You must be signed in to change notification settings - Fork 26
/
timer.c
126 lines (103 loc) · 2.31 KB
/
timer.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
* Timers (one-short and periodic)
*
* Copyright (C) 2007 Olaf Kirch <[email protected]>
*/
#include <stdlib.h>
#include <time.h>
#include <libisns/isns.h>
#include <libisns/util.h>
typedef struct isns_timer isns_timer_t;
struct isns_timer {
isns_list_t it_list;
time_t it_when;
unsigned int it_period;
isns_timer_callback_t * it_func;
void * it_data;
};
static ISNS_LIST_DECLARE(timers);
static void
__isns_arm_timer(isns_timer_t *tm)
{
isns_list_t *pos, *next;
time_t when = tm->it_when;
isns_list_foreach(&timers, pos, next) {
isns_timer_t *cur = isns_list_item(isns_timer_t, it_list, pos);
if (when < cur->it_when)
break;
}
isns_item_insert_before(pos, &tm->it_list);
}
static isns_timer_t *
__isns_create_timer(time_t when,
unsigned int period,
isns_timer_callback_t *fn,
void *data)
{
isns_timer_t *tm;
tm = isns_calloc(1, sizeof(*tm));
tm->it_when = when;
tm->it_period = period;
tm->it_func = fn;
tm->it_data = data;
return tm;
}
void
isns_add_timer(unsigned int period,
isns_timer_callback_t *fn,
void *data)
{
isns_timer_t *tm;
isns_assert(period);
tm = __isns_create_timer(time(NULL) + period, period, fn, data);
__isns_arm_timer(tm);
}
void
isns_add_oneshot_timer(unsigned int expires,
isns_timer_callback_t *fn,
void *data)
{
isns_timer_t *tm;
tm = __isns_create_timer(time(NULL) + expires, 0, fn, data);
__isns_arm_timer(tm);
}
void
isns_cancel_timer(isns_timer_callback_t *fn, void *data)
{
isns_list_t *pos, *next;
isns_list_foreach(&timers, pos, next) {
isns_timer_t *tm = isns_list_item(isns_timer_t, it_list, pos);
if (tm->it_func == fn
&& (data == NULL || tm->it_data == data)) {
isns_list_del(pos);
isns_free(tm);
}
}
}
time_t
isns_run_timers(void)
{
while (!isns_list_empty(&timers)) {
isns_timer_t *tm = isns_list_item(isns_timer_t, it_list, timers.next);
isns_timer_callback_t *func;
time_t expire;
void *data;
expire = tm->it_when;
if (time(NULL) < expire)
return expire;
isns_list_del(&tm->it_list);
func = tm->it_func;
data = tm->it_data;
expire = 0;
/* If it's a periodic timer, rearm it now. This allows
* the timer callback to cancel the timer. */
if (tm->it_period) {
tm->it_when = time(NULL) + tm->it_period;
__isns_arm_timer(tm);
} else {
isns_free(tm);
}
func(data);
}
return 0;
}