]>
Commit | Line | Data |
---|---|---|
9af9ec33 EW |
1 | /* praxis: services for TSora IRC networks. |
2 | * src/event.c: The event loop routines. | |
3 | * | |
4 | * Copyright (c) 2004 Eric Will <rakaur@malkier.net> | |
5 | * Copyright (c) 2003-2004 shrike development team. | |
6 | * | |
7 | * $Id$ | |
8 | */ | |
9 | ||
10 | #include "praxis.h" | |
11 | #include "dlink.h" | |
12 | #include "balloc.h" | |
13 | #include "ilog.h" | |
14 | #include "events.h" | |
15 | #include "event.h" | |
16 | ||
17 | static Heap *eventq_heap; | |
18 | ||
19 | /* eventInit() | |
20 | * Initialises the event system. | |
21 | * | |
22 | * inputs - none | |
23 | * outputs - none | |
24 | */ | |
25 | void | |
26 | eventInit(void) | |
27 | { | |
28 | eventq_heap = ballocHeapCreate(sizeof(EventQ), EVENTQ_HEAP_SIZE); | |
29 | ||
30 | memset(&event_table, '\0', (sizeof(Event) * E_LAST)); | |
31 | memset(&event_queue, '\0', sizeof(event_queue)); | |
32 | ||
33 | if (eventq_heap == NULL) | |
34 | { | |
35 | ilog(L_INFO, "eventInit(): ballocHeapCreate() failed!"); | |
36 | exit(EXIT_FAILURE); | |
37 | } | |
38 | } | |
39 | ||
40 | /* eventAdd() | |
41 | * Adds a function to be called when an event happens. | |
42 | * | |
43 | * inputs - E_event, pointer to function | |
44 | * outputs - none | |
45 | */ | |
46 | void | |
47 | eventAdd(uint event, uchar (*func) ()) | |
48 | { | |
49 | iassert(event >= 0); | |
50 | iassert(event < E_LAST); | |
51 | iassert(func != NULL); | |
52 | ||
53 | ilog(L_DEBUG2, "eventAdd(): Registering function for event: %d", event); | |
54 | ||
512f83e1 | 55 | dlinkAddTailAlloc((void *)func, &event_table[event].func_list); |
9af9ec33 EW |
56 | } |
57 | ||
58 | /* eventAddSpecial() | |
59 | * Adds a function to be called first or last when an event happens. | |
60 | * | |
61 | * inputs - E_event, 1 for first 2 for last, pointer to function | |
62 | * outputs - 1 on success or 0 on failure | |
63 | */ | |
64 | uchar | |
65 | eventAddSpecial(uint event, uchar type, uchar (*func) ()) | |
66 | { | |
67 | iassert(event >= 0); | |
68 | iassert(event < E_LAST); | |
69 | iassert(type == 1 || type == 2); | |
70 | iassert(func != NULL); | |
71 | ||
72 | if (type == 1) | |
73 | { | |
74 | if (event_table[event].first_func != NULL) | |
75 | return 0; | |
76 | ||
77 | ilog(L_DEBUG2, "eventAddSpecial(): Registering first function for " | |
78 | "event: %d", event); | |
79 | ||
80 | event_table[event].first_func = func; | |
81 | } | |
82 | else if (type == 2) | |
83 | { | |
84 | if (event_table[event].last_func != NULL) | |
85 | return 0; | |
86 | ||
87 | ilog(L_DEBUG2, "eventAddSpecial(): Registering last function for " | |
88 | "event: %d", event); | |
89 | ||
90 | event_table[event].last_func = func; | |
91 | } | |
92 | else | |
93 | return 0; | |
94 | ||
95 | return 1; | |
96 | } | |
97 | ||
98 | /* eventDelete() | |
99 | * Removes a function to be called when an event happens. | |
100 | * | |
101 | * inputs - E_event, pointer to function | |
102 | * outputs - 1 on success or 0 on failure | |
103 | */ | |
104 | uchar | |
105 | eventDelete(uint event, uchar (*func) ()) | |
106 | { | |
107 | uchar ret; | |
108 | ||
109 | iassert(event >= 0); | |
110 | iassert(event < E_LAST); | |
111 | iassert(func != NULL); | |
112 | ||
113 | ilog(L_DEBUG2, "eventDelete(): Unregistering function for event: %d", | |
114 | event); | |
115 | ||
512f83e1 | 116 | ret = dlinkFindDestroy((void *)func, &event_table[event].func_list); |
9af9ec33 EW |
117 | |
118 | if (ret == 0) | |
119 | { | |
120 | ilog(L_ERROR, "eventDelete(): dlinkFindDestroy() failed."); | |
121 | return 0; | |
122 | } | |
123 | ||
124 | return 1; | |
125 | } | |
126 | ||
127 | /* eventDeleteSpecial() | |
128 | * Removes a function to be called first or last when an event happens. | |
129 | * | |
130 | * inputs - E_event, 1 for first 2 for last, pointer to function | |
131 | * outputs - 1 on success or 0 on failure | |
132 | */ | |
133 | uchar | |
134 | eventDeleteSpecial(uint event, uchar type, uchar (*func) ()) | |
135 | { | |
136 | iassert(event >= 0); | |
137 | iassert(event < E_LAST); | |
138 | iassert(type == 1 || type == 2); | |
139 | iassert(func != NULL); | |
140 | ||
141 | if (type == 1) | |
142 | { | |
143 | if (event_table[event].first_func != func) | |
144 | return 0; | |
145 | ||
146 | ilog(L_DEBUG2, "eventDeleteSpecial(): Unregistering first function for " | |
147 | "event: %d", event); | |
148 | ||
149 | event_table[event].first_func = NULL; | |
150 | } | |
151 | else if (type == 2) | |
152 | { | |
153 | if (event_table[event].last_func != func) | |
154 | return 0; | |
155 | ||
156 | ilog(L_DEBUG2, "eventDeleteSpecial(): Unregistering last function for " | |
157 | "event: %d", event); | |
158 | ||
159 | event_table[event].last_func = NULL; | |
160 | } | |
161 | else | |
162 | return 0; | |
163 | ||
164 | return 1; | |
165 | } | |
166 | ||
167 | /* eventPost() | |
168 | * Post an event to the event_queue that has happened. | |
169 | * | |
170 | * inputs - E_event, argument | |
171 | * outputs - none | |
172 | */ | |
173 | void | |
174 | eventPost(uint event, void *arg) | |
175 | { | |
176 | EventQ *eventq_p; | |
177 | ||
178 | iassert(event >= 0); | |
179 | iassert(event < E_LAST); | |
180 | ||
181 | /* Check to see if this Event is being handled. */ | |
182 | if ((event_table[event].first_func == NULL) && | |
183 | (dlinkLength(&event_table[event].func_list) == 0) && | |
184 | (event_table[event].last_func == NULL)) | |
185 | return; | |
186 | ||
187 | eventq_p = ballocHeapAlloc(eventq_heap); | |
188 | ||
189 | eventq_p->event = event; | |
190 | eventq_p->arg = arg; | |
191 | ||
192 | dlinkAddTailAlloc(eventq_p, &event_queue); | |
193 | } | |
194 | ||
195 | /* eventShouldRun() | |
196 | * Returns if we need to clear the queue or not. | |
197 | * | |
198 | * inputs - none | |
199 | * outputs - 1 for yes, or 0 for no | |
200 | */ | |
201 | uchar | |
202 | eventShouldRun(void) | |
203 | { | |
204 | if (dlinkLength(&event_queue) != 0) | |
205 | return 1; | |
206 | ||
207 | return 0; | |
208 | } | |
209 | ||
210 | /* eventRun() | |
211 | * Runs all pending events. | |
212 | * | |
213 | * inputs - none | |
214 | * outputs - none | |
215 | */ | |
216 | void | |
217 | eventRun(void) | |
218 | { | |
219 | EventQ *eventq_p; | |
220 | DLinkNode *node_p, *tnode_p, *node2_p; | |
221 | uchar (*func) (); | |
222 | uchar ret, terminated = 0; | |
223 | ||
224 | /* Should we even bother? */ | |
225 | if (dlinkLength(&event_queue) == 0) | |
226 | return; | |
227 | ||
228 | DLINK_FOREACH_SAFE(node_p, tnode_p, event_queue.head) | |
229 | { | |
230 | eventq_p = node_p->data; | |
231 | ||
232 | /* If there's a first function, call it. */ | |
233 | if (event_table[eventq_p->event].first_func != NULL) | |
234 | { | |
235 | ret = event_table[eventq_p->event].first_func(eventq_p->arg); | |
236 | ||
237 | if (ret == 0) | |
238 | { | |
239 | ilog(L_ERROR, "eventRun(): first_func failure for event: %d.", | |
240 | eventq_p->event); | |
241 | ||
242 | terminated = 1; | |
243 | } | |
244 | } | |
245 | ||
246 | /* If there are function list entries, call them. */ | |
247 | DLINK_FOREACH(node2_p, event_table[eventq_p->event].func_list.head) | |
248 | { | |
512f83e1 | 249 | func = (uchar (*) ())node2_p->data; |
9af9ec33 EW |
250 | |
251 | if (terminated == 1) | |
252 | break; | |
253 | ||
254 | ret = func(eventq_p->arg); | |
255 | ||
256 | if (ret == 0) | |
257 | { | |
258 | ilog(L_ERROR, "eventRun(): func_list failure for event: %d.", | |
259 | eventq_p->event); | |
260 | ||
261 | terminated = 1; | |
262 | } | |
263 | } | |
264 | ||
265 | /* If there's a last function, call it. */ | |
266 | if (event_table[eventq_p->event].last_func != NULL) | |
267 | { | |
268 | ret = event_table[eventq_p->event].last_func(eventq_p->arg); | |
269 | ||
270 | if (ret == 0) | |
271 | { | |
272 | ilog(L_ERROR, "eventRun(): last_func failure for event: %d.", | |
273 | eventq_p->event); | |
274 | } | |
275 | } | |
276 | ||
277 | /* Now destroy the event_queue entry. */ | |
278 | dlinkDestroy(node_p, &event_queue); | |
279 | ballocHeapFree(eventq_heap, eventq_p); | |
280 | } | |
281 | } |