]>
Commit | Line | Data |
---|---|---|
3b15402f MM |
1 | /* |
2 | * BIRD Library -- Event Processing | |
3 | * | |
4 | * (c) 1999 Martin Mares <mj@ucw.cz> | |
5 | * | |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
525fa2c1 MM |
9 | /** |
10 | * DOC: Events | |
11 | * | |
12 | * Events are there to keep track of deferred execution. | |
13 | * Since BIRD is single-threaded, it requires long lasting tasks to be split to smaller | |
14 | * parts, so that no module can monopolize the CPU. To split such a task, just create | |
15 | * an &event resource, point it to the function you want to have called and call ev_schedule() | |
58f7d004 | 16 | * to ask the core to run the event when nothing more important requires attention. |
525fa2c1 MM |
17 | * |
18 | * You can also define your own event lists (the &event_list structure), enqueue your | |
19 | * events in them and explicitly ask to run them. | |
525fa2c1 MM |
20 | */ |
21 | ||
3b15402f MM |
22 | #include "nest/bird.h" |
23 | #include "lib/event.h" | |
24 | ||
25 | event_list global_event_list; | |
26 | ||
27 | inline void | |
28 | ev_postpone(event *e) | |
29 | { | |
30 | if (e->n.next) | |
31 | { | |
32 | rem_node(&e->n); | |
33 | e->n.next = NULL; | |
34 | } | |
35 | } | |
36 | ||
37 | static void | |
38 | ev_dump(resource *r) | |
39 | { | |
40 | event *e = (event *) r; | |
41 | ||
42 | debug("(code %p, data %p, %s)\n", | |
43 | e->hook, | |
44 | e->data, | |
45 | e->n.next ? "scheduled" : "inactive"); | |
46 | } | |
47 | ||
48 | static struct resclass ev_class = { | |
49 | "Event", | |
67bd949a | 50 | sizeof(event), |
3b15402f | 51 | (void (*)(resource *)) ev_postpone, |
e81b440f | 52 | ev_dump, |
acb60628 | 53 | NULL, |
e81b440f | 54 | NULL |
3b15402f MM |
55 | }; |
56 | ||
525fa2c1 MM |
57 | /** |
58 | * ev_new - create a new event | |
59 | * @p: resource pool | |
60 | * | |
61 | * This function creates a new event resource. To use it, | |
62 | * you need to fill the structure fields and call ev_schedule(). | |
63 | */ | |
3b15402f MM |
64 | event * |
65 | ev_new(pool *p) | |
66 | { | |
67 | event *e = ralloc(p, &ev_class); | |
3b15402f MM |
68 | return e; |
69 | } | |
70 | ||
525fa2c1 MM |
71 | /** |
72 | * ev_run - run an event | |
73 | * @e: an event | |
74 | * | |
75 | * This function explicitly runs the event @e (calls its hook | |
76 | * function) and removes it from an event list if it's linked to any. | |
77 | * | |
78 | * From the hook function, you can call ev_enqueue() or ev_schedule() | |
79 | * to re-add the event. | |
80 | */ | |
8f6accb5 | 81 | inline void |
3b15402f MM |
82 | ev_run(event *e) |
83 | { | |
8f6accb5 MM |
84 | ev_postpone(e); |
85 | e->hook(e->data); | |
3b15402f MM |
86 | } |
87 | ||
525fa2c1 MM |
88 | /** |
89 | * ev_enqueue - enqueue an event | |
90 | * @l: an event list | |
91 | * @e: an event | |
92 | * | |
93 | * ev_enqueue() stores the event @e to the specified event | |
94 | * list @l which can be run by calling ev_run_list(). | |
95 | */ | |
3b15402f MM |
96 | inline void |
97 | ev_enqueue(event_list *l, event *e) | |
98 | { | |
8f6accb5 | 99 | ev_postpone(e); |
3b15402f MM |
100 | add_tail(l, &e->n); |
101 | } | |
102 | ||
525fa2c1 MM |
103 | /** |
104 | * ev_schedule - schedule an event | |
105 | * @e: an event | |
106 | * | |
107 | * This function schedules an event by enqueueing it to a system-wide | |
108 | * event list which is run by the platform dependent code whenever | |
109 | * appropriate. | |
110 | */ | |
3b15402f MM |
111 | void |
112 | ev_schedule(event *e) | |
113 | { | |
114 | ev_enqueue(&global_event_list, e); | |
115 | } | |
116 | ||
525fa2c1 MM |
117 | /** |
118 | * ev_run_list - run an event list | |
119 | * @l: an event list | |
120 | * | |
121 | * This function calls ev_run() for all events enqueued in the list @l. | |
122 | */ | |
84a7d7f7 | 123 | int |
3b15402f MM |
124 | ev_run_list(event_list *l) |
125 | { | |
b933281e | 126 | node *n; |
8f6accb5 | 127 | list tmp_list; |
0d70292d | 128 | |
8f6accb5 MM |
129 | init_list(&tmp_list); |
130 | add_tail_list(&tmp_list, l); | |
131 | init_list(l); | |
b933281e | 132 | WALK_LIST_FIRST(n, tmp_list) |
3b15402f | 133 | { |
0d70292d | 134 | event *e = SKIP_BACK(event, n, n); |
ebc793a5 | 135 | ev_run(e); |
3b15402f | 136 | } |
ebc793a5 | 137 | return !EMPTY_LIST(*l); |
3b15402f | 138 | } |