Branch data Line data Source code
1 : :
2 : : #include "gwrl/event.h"
3 : :
4 : : #ifdef __cplusplus
5 : : extern "C" {
6 : : #endif
7 : :
8 : : #ifdef GWRL_COVERAGE_INTERNAL_ASSERT_VARS
9 : : int asserts_var1 = 0;
10 : : #endif
11 : :
12 : : gwrl *
13 : : gwrl_create() {
14 : 25 : gwrl * rl = _gwrl(gwrl_mem_calloc(1,sizeof(gwrl)));
15 : 25 : gwrl_options defaults = GWRL_DEFAULT_OPTIONS;
16 : :
17 : : #ifdef GWRL_COVERAGE_INTERNAL_ASSERT_VARS
18 : 25 : if(asserts_var1 == gwrl_create_fail) {
19 : 1 : free(rl);
20 : 1 : rl = NULL;
21 : 1 : }
22 : : #endif
23 : :
24 [ + + ]: 25 : if(!rl) {
25 : : #ifndef GWRL_COVERAGE_INTERNAL_ASSERT_VARS
26 : : gwerr("(6GlI8) calloc error");
27 : : #endif
28 : 1 : return NULL;
29 : : }
30 : :
31 : : //setup default options.
32 [ - + ]: 24 : memcpy(&rl->options,&defaults,sizeof(defaults));
33 : :
34 : : //initialize the backend.
35 : 24 : rl->backend = gwrl_bkd_init(rl);
36 [ + + ]: 24 : if(!rl->backend) {
37 : 1 : free(rl);
38 : 1 : return NULL;
39 : : }
40 : :
41 : : //setup the custom gather functions.
42 : 23 : rl->gatherfncs = NULL;
43 : : if(GWRL_GATHER_FUNCS_MAX > 0) {
44 : 23 : rl->gatherfncs = gwrl_mem_calloc(1,sizeof(gwrl_gather_fnc *) * GWRL_GATHER_FUNCS_MAX);
45 : : #ifdef GWRL_COVERAGE_INTERNAL_ASSERT_VARS
46 [ + + ]: 23 : if(asserts_var1 == gwrl_create_gatherfncs_fail) {
47 : 1 : free(rl->gatherfncs);
48 : 1 : rl->gatherfncs = NULL;
49 : 1 : }
50 : : #endif
51 [ + + ]: 23 : if(!rl->gatherfncs) {
52 : : #ifndef GWRL_COVERAGE_INTERNAL_ASSERT_VARS
53 : : gwerr("(7VB3R) calloc error");
54 : : #endif
55 : 1 : free(rl);
56 : 1 : return NULL;
57 : : }
58 : : }
59 : :
60 : : //initialize locks for thread safe functions.
61 : 22 : lockid_init(&rl->_qsrclk);
62 : 22 : lockid_init(&rl->_qevtlk);
63 : :
64 : : //initialize the backend waking mechanism.
65 : 22 : gwrl_wake_init(rl);
66 : 22 : return rl;
67 : 25 : }
68 : :
69 : : gwrlevt *
70 : 587 : gwrl_evt_create(gwrl * rl, gwrlsrc * src, gwrlevt_cb * callback,
71 : 587 : void * userdata, fileid_t fd, gwrlevt_flags_t flags) {
72 : 587 : gwrlevt * evt = NULL;
73 : 587 : if(rl->cevents) {
74 : 337 : evt = rl->cevents;
75 : 337 : rl->cevents = evt->next;
76 : 337 : rl->ncevents--;
77 : 337 : evt->next = NULL;
78 : 337 : } else {
79 : 250 : evt = _gwrlevt(gwrl_mem_calloc(1,sizeof(*evt)));
80 : : #ifdef GWRL_COVERAGE_INTERNAL_ASSERT_VARS
81 [ + + ]: 250 : if(asserts_var1 == gwrl_evt_create_fail) {
82 : 1 : free(evt);
83 : 1 : evt = NULL;
84 : 1 : }
85 : : #endif
86 [ + + ]: 250 : if(!evt) {
87 : : #ifndef GWRL_COVERAGE_INTERNAL_ASSERT_VARS
88 : : gwerr("(8FxlC) calloc error");
89 : : #endif
90 : 250 : return NULL;
91 : : }
92 : : }
93 : 586 : evt->callback = callback;
94 : 586 : evt->userdata = userdata;
95 : 586 : evt->src = src;
96 : 586 : evt->fd = fd;
97 : 586 : evt->flags = flags;
98 : 586 : return evt;
99 : 587 : }
100 : :
101 : : gwrlsrc *
102 : 21 : gwrl_src_time_create(int64_t ms, bool repeat, int whence,
103 : 21 : bool persist, gwrlevt_cb * callback, void * userdata) {
104 : 21 : gwrlsrc_time * tsrc = _gwrlsrct(gwrl_mem_calloc(1,sizeof(gwrlsrc_time)));
105 : 21 : gwrlsrc * src = _gwrlsrc(tsrc);
106 : 21 : if(!tsrc) {
107 : 0 : gwerr("(5Gn3K) caloc error");
108 : 0 : return NULL;
109 : : }
110 : 21 : src->type = GWRL_SRC_TYPE_TIME;
111 : 21 : src->userdata = userdata;
112 : 21 : src->callback = callback;
113 : 21 : tsrc->ms = ms;
114 [ + + ][ + - ]: 21 : if(repeat && whence != GWRL_ABS) flset(src->flags,GWRL_REPEAT);
115 [ + + ]: 21 : if(whence == GWRL_NOW) {
116 : 20 : tsrc->when.tv_sec = sec_min;
117 : 20 : tsrc->when.tv_nsec = nsec_min;
118 : 20 : }
119 [ + - ]: 1 : else if(whence == GWRL_ABS) {
120 : 1 : flset(src->flags,GWRL_WHENCE_ABS);
121 : 1 : gwtm_ms_to_timespec(ms,&tsrc->when);
122 : 1 : }
123 : 21 : flset(src->flags,GWRL_ENABLED);
124 [ + + ]: 21 : if(persist) flset(src->flags,GWRL_PERSIST);
125 : 21 : return src;
126 : 21 : }
127 : :
128 : : gwrlsrc *
129 : 35 : gwrl_src_file_create(fileid_t fd, gwrlsrc_flags_t flags,
130 : 35 : gwrlevt_cb * callback, void * userdata) {
131 : 35 : gwrlsrc_file * fsrc = _gwrlsrcf(gwrl_mem_calloc(1,sizeof(gwrlsrc_file)));
132 : 35 : gwrlsrc * src = _gwrlsrc(fsrc);
133 : 35 : if(!src) {
134 : 0 : gwerr("(25FnG) calloc error");
135 : 0 : return NULL;
136 : : }
137 : 35 : src->flags = flags;
138 : 35 : src->type = GWRL_SRC_TYPE_FILE;
139 : 35 : src->userdata = userdata;
140 : 35 : src->callback = callback;
141 : 35 : flset(src->flags,GWRL_ENABLED);
142 : 35 : fsrc->fd = fd;
143 : 35 : return src;
144 : 35 : }
145 : :
146 : : gwrlsrc *
147 : 2 : gwrl_set_fd(gwrl * rl, fileid_t fd, gwrlsrc_flags_t flags,
148 : 2 : gwrlevt_cb * callback, void * userdata) {
149 : 2 : gwrlsrc * fsrc = gwrl_src_file_create(fd,flags,callback,userdata);
150 [ - + ]: 2 : while(!fsrc) fsrc = gwrl_src_file_create(fd,flags,callback,userdata);
151 : 2 : gwrl_src_add(rl,fsrc);
152 : 2 : return fsrc;
153 : : }
154 : :
155 : : gwrlsrc *
156 : 17 : gwrl_set_timeout(gwrl * rl, int64_t ms, bool persist,
157 : 17 : gwrlevt_cb * callback, void * userdata) {
158 : 17 : gwrlsrc * tsrc = gwrl_src_time_create(ms,false,GWRL_NOW,persist,callback,userdata);
159 [ - + ]: 17 : while(!tsrc) tsrc = gwrl_src_time_create(ms,false,GWRL_NOW,persist,callback,userdata);
160 : 17 : gwrl_src_add(rl,tsrc);
161 : 17 : return tsrc;
162 : : }
163 : :
164 : : gwrlsrc *
165 : 3 : gwrl_set_interval(gwrl * rl, int64_t ms, gwrlevt_cb * callback,
166 : 3 : void * userdata) {
167 : 3 : gwrlsrc * tsrc = gwrl_src_time_create(ms,true,GWRL_NOW,false,callback,userdata);
168 [ - + ]: 3 : while(!tsrc) tsrc = gwrl_src_time_create(ms,true,GWRL_NOW,false,callback,userdata);
169 : 3 : gwrl_src_add(rl,tsrc);
170 : 3 : return tsrc;
171 : : }
172 : :
173 : : gwrlsrc *
174 : 1 : gwrl_set_date_timeout(gwrl * rl, int64_t ms, gwrlevt_cb * callback,
175 : 1 : void * userdata) {
176 : 1 : gwrlsrc * tsrc = gwrl_src_time_create(ms,false,GWRL_ABS,false,callback,userdata);
177 [ - + ]: 1 : while(!tsrc) tsrc = gwrl_src_time_create(ms,false,GWRL_ABS,false,callback,userdata);
178 : 1 : gwrl_src_add(rl,tsrc);
179 : 1 : return tsrc;
180 : : }
181 : :
182 : : void
183 : 7 : gwrl_post_function(gwrl * rl, gwrlevt_cb * cb, void * userdata) {
184 : 7 : gwrlevt * evt = gwrl_evt_create(rl,NULL,cb,userdata,0,0);
185 [ - + ]: 7 : while(!evt) evt = gwrl_evt_create(rl,NULL,cb,userdata,0,0);
186 : 7 : gwrl_post_evt(rl,evt);
187 : 7 : }
188 : :
189 : : void
190 : 2 : gwrl_post_function_safely(gwrl * rl, gwrlevt_cb * cb, void * userdata) {
191 : 2 : gwrlevt * evt = gwrl_evt_create(rl,NULL,cb,userdata,0,0);
192 [ - + ]: 2 : while(!evt) evt = gwrl_evt_create(rl,NULL,cb,userdata,0,0);
193 : 2 : gwrl_post_evt_safely(rl,evt);
194 : 2 : }
195 : :
196 : : void
197 : 2 : gwrl_set_options(gwrl * rl, gwrl_options * opts) {
198 : 2 : if(opts->gwrl_gather_funcs_max > rl->options.gwrl_gather_funcs_max) {
199 : 2 : int orig = rl->options.gwrl_gather_funcs_max;
200 : 2 : int diff = opts->gwrl_gather_funcs_max - orig;
201 : 2 : void * tmp = NULL;
202 [ - + ]: 2 : if(rl->options.gwrl_gather_funcs_max < 1) {
203 : 0 : tmp = gwrl_mem_calloc(1,sizeof(gwrl_gather_fnc *) * opts->gwrl_gather_funcs_max);
204 [ # # ]: 0 : while(!tmp) tmp = gwrl_mem_calloc(1,sizeof(gwrl_gather_fnc *) * opts->gwrl_gather_funcs_max);
205 : 0 : } else {
206 : 2 : tmp = gwrl_mem_realloc(rl->gatherfncs,sizeof(gwrl_gather_fnc *) * opts->gwrl_gather_funcs_max);
207 [ - + ]: 2 : while(!tmp) tmp = gwrl_mem_realloc(rl->gatherfncs,sizeof(gwrl_gather_fnc *) * opts->gwrl_gather_funcs_max);
208 : : }
209 [ + - ][ + - ]: 2 : if(diff > 0 && orig > 0) {
210 : 2 : char * buf = (char *)tmp;
211 : 2 : buf += (sizeof(gwrl_gather_fnc *) * orig);
212 : 2 : bzero(buf,sizeof(gwrl_gather_fnc *) * diff);
213 : 2 : }
214 : 2 : rl->gatherfncs = (gwrl_gather_fnc **)tmp;
215 : 2 : }
216 [ - + ]: 2 : memcpy(&rl->options,opts,sizeof(rl->options));
217 : 2 : gwrl_bkd_set_options(rl,opts);
218 : 2 : }
219 : :
220 : : void
221 : 3 : gwrl_add_gather_fnc(gwrl * rl, gwrl_gather_fnc * fnc) {
222 : 3 : int i = 0;
223 : 3 : bool added = false;
224 [ + - ]: 4 : for(; i < rl->options.gwrl_gather_funcs_max; i++) {
225 [ + + ]: 4 : if(!rl->gatherfncs[i]) {
226 : 3 : rl->gatherfncs[i] = fnc;
227 : 3 : added = true;
228 : 3 : break;
229 : : }
230 : 1 : }
231 [ - + ]: 3 : if(!added) {
232 : 0 : gwerr("(3F85R) no open gather slots.");
233 : 0 : return;
234 : : }
235 : 3 : }
236 : :
237 : : void
238 : 0 : gwrl_reset_gather_fncs(gwrl * rl, gwrl_gather_fnc * fnc) {
239 : 0 : if(rl->options.gwrl_gather_funcs_max > 0) {
240 : 0 : bzero(rl->gatherfncs,sizeof(gwrl_gather_fnc*)*
241 : : rl->options.gwrl_gather_funcs_max);
242 : 0 : }
243 : 0 : }
244 : :
245 : : void
246 : 6 : gwrl_free(gwrl * rl, gwrlsrc ** sources) {
247 : 6 : int i = 0;
248 : 6 : gwrlevt * del = NULL;
249 : 6 : gwrlevt * evt = NULL;
250 : 6 : gwrlsrc * head = NULL;
251 : 6 : gwrlsrc * last = NULL;
252 : 6 : gwrlsrc * delsrc = NULL;
253 : 6 : gwrlsrc * src = NULL;
254 : :
255 : : //make sure there is no proactor associated with the reactor.
256 [ - + ]: 4 : if(rl && rl->pr) {
257 : 0 : gwerr("(RF4L3) gwrl_free error, you can't free a reactor before freeing the proactor.");
258 : 0 : return;
259 : : }
260 : :
261 : : //if rl is NULL, just free all sources passed in
262 [ + + ][ + - ]: 6 : if(!rl && sources) {
263 : 2 : head = *sources;
264 [ + + ]: 4 : while(head) {
265 : 2 : delsrc = head;
266 : 2 : head = head->next;
267 : 2 : free(delsrc);
268 : 2 : }
269 : 2 : return;
270 : : }
271 : :
272 : : //dispatch one last time, if events exist after
273 : : //this they're ignored and freed.
274 : 4 : gwrl_dispatch(rl);
275 : 4 : evt = rl->events;
276 : :
277 : : //no events, set to cached events
278 [ + - ]: 4 : if(!evt) {
279 : 4 : evt = rl->cevents;
280 : 4 : rl->cevents = NULL;
281 : 4 : }
282 : :
283 : : //go through all events and free them
284 [ + + ]: 8 : while(evt) {
285 : 4 : del = evt;
286 : 4 : evt = evt->next;
287 : 4 : free(del);
288 [ + - ]: 4 : if(!evt) {
289 : 4 : evt = rl->cevents;
290 : 4 : rl->cevents = NULL;
291 : 4 : }
292 : 4 : }
293 : :
294 : : //loop over all input sources for each type. either
295 : : //assembling the sources list for the user, or freeing them.
296 [ + + ]: 16 : for(; i<GWRL_SRC_TYPES_COUNT; i++) {
297 : 12 : src = rl->sources[i];
298 : 12 : rl->sources[i] = NULL;
299 [ + + ]: 19 : while(src) {
300 : 7 : delsrc = src;
301 : 7 : src = src->next;
302 [ + + ]: 7 : if(!sources) {
303 : 3 : free(delsrc);
304 : 3 : } else {
305 : 4 : delsrc->next = NULL;
306 [ + + ]: 4 : if(!head) {
307 : 2 : head = delsrc;
308 : 2 : }
309 [ + + ]: 4 : if(!last) {
310 : 2 : last = delsrc;
311 : 2 : } else {
312 : 2 : last->next = delsrc;
313 : 4 : last = delsrc;
314 : : }
315 : : }
316 : 7 : }
317 : 12 : }
318 : :
319 : : //get and free queued input sources
320 [ - + ]: 4 : if(rl->_qsrc) {
321 : 0 : lockid_lock(&rl->_qsrclk);
322 : 0 : src = rl->_qsrc;
323 : 0 : rl->_qsrc = NULL;
324 : 0 : lockid_unlock(&rl->_qsrclk);
325 [ # # ]: 0 : while(src) {
326 : 0 : delsrc = src;
327 : 0 : src = src->next;
328 [ # # ]: 0 : if(!sources) {
329 : 0 : free(delsrc);
330 : 0 : } else {
331 : 0 : delsrc->next = NULL;
332 [ # # ]: 0 : if(!head) {
333 : 0 : head = delsrc;
334 : 0 : }
335 [ # # ]: 0 : if(!last) {
336 : 0 : last = delsrc;
337 : 0 : } else {
338 : 0 : last->next = delsrc;
339 : 0 : last = delsrc;
340 : : }
341 : : }
342 : 0 : }
343 : 0 : }
344 : :
345 : : //get and free all queued events
346 [ - + ]: 4 : if(rl->_qevt) {
347 : 0 : lockid_lock(&rl->_qevtlk);
348 : 0 : evt = rl->_qevt;
349 : 0 : rl->_qevt = NULL;
350 : 0 : lockid_unlock(&rl->_qevtlk);
351 [ # # ]: 0 : while(evt) {
352 : 0 : del = evt;
353 : 0 : evt = evt->next;
354 : 0 : free(del);
355 : 0 : }
356 : 0 : }
357 : :
358 [ + + ]: 4 : if(sources) {
359 : 2 : *sources = head;
360 : 2 : }
361 : 4 : lockid_free(&rl->_qevtlk);
362 : 4 : lockid_free(&rl->_qsrclk);
363 : 4 : gwrl_bkd_free(rl);
364 : 4 : gwrl_wake_free(rl);
365 : 4 : free(rl);
366 : 6 : }
367 : :
368 : : void
369 : 586 : gwrl_evt_free(gwrl * rl, gwrlevt * evt) {
370 : 586 : if(rl->ncevents >= (rl->options.gwrl_event_cache_max)) {
371 : 100 : free(evt);
372 : 100 : } else {
373 : 486 : gwrlevt * head = NULL;
374 : 486 : bzero(evt,sizeof(*evt));
375 : 486 : head = rl->cevents;
376 [ + + ]: 486 : if(head) {
377 : 346 : evt->next = head;
378 : 346 : }
379 : 486 : rl->cevents = evt;
380 : 486 : rl->ncevents++;
381 : : }
382 : 586 : }
383 : :
384 : : void
385 : 252 : gwrl_evt_free_list(gwrl * rl, gwrlevt * evt) {
386 : 252 : gwrlevt * nev = NULL;
387 [ + + ]: 836 : while(evt) {
388 : 584 : nev = evt->next;
389 : 584 : gwrl_evt_free(rl,evt);
390 : 584 : evt = nev;
391 : 584 : }
392 : 252 : }
393 : :
394 : : void
395 : 2 : gwrl_allow_poll_sleep(gwrl * rl, int onoff) {
396 : 0 : if(onoff) flclr(rl->flags,GWRL_NOSLEEP);
397 : 2 : else flset(rl->flags,GWRL_NOSLEEP);
398 : 2 : }
399 : :
400 : : void
401 : 59 : gwrl_src_add(gwrl * rl, gwrlsrc * src) {
402 : 59 : gwrlsrc * head = rl->sources[src->type];
403 : 22 : if(head) src->next = head;
404 : 59 : rl->sources[src->type] = src;
405 [ + + ]: 59 : if(src->type == GWRL_SRC_TYPE_FILE) gwrl_bkd_src_add(rl,src);
406 : 59 : gwrl_wake(rl);
407 : 59 : }
408 : :
409 : : void
410 : 0 : gwrl_src_add_safely(gwrl * rl, gwrlsrc * src) {
411 : 0 : gwrlsrc * head = rl->_qsrc;
412 : 0 : lockid_lock(&rl->_qsrclk);
413 : 0 : if(head) src->next = head;
414 : 0 : else src->next = NULL;
415 : 0 : rl->_qsrc = src;
416 : 0 : lockid_unlock(&rl->_qsrclk);
417 [ # # ]: 0 : if(rl->flags & GWRL_SLEEPING) gwrl_wake(rl);
418 : 0 : }
419 : :
420 : : void
421 : 2 : gwrl_post_evt_safely(gwrl * rl, gwrlevt * evt) {
422 : 2 : gwrlevt * head = rl->_qevt;
423 : 2 : lockid_lock(&rl->_qevtlk);
424 : 0 : if(head) evt->next = head;
425 : 2 : else evt->next = NULL;
426 : 2 : rl->_qevt = evt;
427 : 2 : lockid_unlock(&rl->_qevtlk);
428 [ + - ]: 2 : if(rl->flags & GWRL_SLEEPING) gwrl_wake(rl);
429 : 2 : }
430 : :
431 : : void
432 : 14 : gwrl_src_del(gwrl * rl, gwrlsrc * src, gwrlsrc * prev, bool freesrc) {
433 : 14 : gwrlsrc * head = rl->sources[src->type];
434 : 14 : gwrlsrc * search = head;
435 : 14 : gwrlsrc * _prev = prev;
436 : :
437 : 14 : if(!prev) {
438 [ + + ][ + + ]: 11 : if(src == head && head->next) {
439 : 3 : rl->sources[src->type] = head->next;
440 : 3 : src->next = NULL;
441 [ + + ]: 11 : } else if(src == head) {
442 : 5 : rl->sources[src->type] = NULL;
443 : 5 : src->next = NULL;
444 : 5 : } else {
445 [ + - ]: 6 : while(search) {
446 [ + + ]: 6 : if(search == src) break;
447 : 3 : _prev = search;
448 : 3 : search = search->next;
449 : 11 : }
450 : : }
451 : 11 : }
452 : :
453 [ + + ]: 14 : if(_prev) {
454 : 6 : _prev->next = src->next;
455 : 6 : src->next = NULL;
456 : 6 : }
457 : :
458 [ + + ]: 14 : if(src->type == GWRL_SRC_TYPE_FILE) gwrl_bkd_del_src(rl,src);
459 [ + + ]: 14 : if(freesrc) free(src);
460 : 14 : gwrl_wake(rl);
461 : 14 : }
462 : :
463 : : void
464 : 4 : gwrl_src_remove(gwrl * rl, gwrlsrc * src) {
465 : 4 : gwrl_src_del(rl,src,NULL,false);
466 : 4 : }
467 : :
468 : : void
469 : 3 : gwrl_del_persistent_timeouts(gwrl * rl) {
470 : 3 : gwrlsrc * src = rl->sources[GWRL_SRC_TYPE_TIME];
471 : 3 : gwrlsrc * shead = src;
472 : 3 : gwrlsrc * phead = NULL;
473 : 3 : gwrlsrc * psrc = NULL;
474 : 3 : gwrlsrc * del = NULL;
475 : 3 : gwrlsrc * deltmp = NULL;
476 : 3 : rl->sources[GWRL_SRC_TYPE_TIME] = NULL;
477 : :
478 : : //first gather all the ones to free, and
479 : : //take them out of the source list
480 [ + + ]: 8 : while(src) {
481 [ + - ]: 5 : if(src->flags & GWRL_PERSIST) {
482 : 5 : del = src;
483 [ + - ]: 5 : if(src == shead) shead = shead->next;
484 [ + + ]: 5 : if(psrc) psrc->next = src->next;
485 [ + + ]: 5 : if(!phead) phead = del;
486 : 2 : else phead->next = del, phead = del;
487 : 5 : }
488 : 5 : psrc = src;
489 : 5 : src = src->next;
490 : 5 : }
491 : :
492 : : //delete the persistent ones
493 [ + + ]: 6 : while(phead) {
494 : 3 : deltmp = phead->next;
495 : 3 : free(phead);
496 : 3 : phead = deltmp;
497 : 3 : }
498 : :
499 : : //replace time input sources with updated list
500 : 3 : rl->sources[GWRL_SRC_TYPE_TIME] = shead;
501 : 3 : }
502 : :
503 : : void
504 : 359 : gwrl_post_evt(gwrl * rl, gwrlevt * evt) {
505 : 359 : gwrlevt * head = rl->events;
506 : 106 : if(head) evt->next = head;
507 : 359 : rl->events = evt;
508 : 359 : gwrl_wake(rl);
509 : 359 : }
510 : :
511 : : void
512 : 9 : gwrl_src_enable(gwrl * rl, gwrlsrc * src) {
513 : 9 : flset(src->flags,GWRL_ENABLED);
514 : 9 : if(src->type == GWRL_SRC_TYPE_TIME) {
515 : 9 : gwrlsrc_time * tsrc = (gwrlsrc_time *)src;
516 [ + - ]: 9 : if(!flisset(src->flags,GWRL_WHENCE_ABS)) {
517 : 9 : gwtm_gettimeofday_timespec(&tsrc->when);
518 : 9 : gwtm_add_ms_to_timespec(tsrc->ms,&tsrc->when);
519 : 9 : }
520 [ # # ]: 9 : } else if(src->type == GWRL_SRC_TYPE_FILE) {
521 : 0 : gwrl_bkd_enable_src(rl,src);
522 : 0 : }
523 : 9 : gwrl_wake(rl);
524 : 9 : }
525 : :
526 : : void
527 : 18 : gwrl_src_disable(gwrl * rl, gwrlsrc * src) {
528 : 18 : flclr(src->flags,GWRL_ENABLED);
529 : 2 : if(src->type == GWRL_SRC_TYPE_FILE) gwrl_bkd_disable_src(rl,src);
530 : 18 : gwrl_wake(rl);
531 : 18 : }
532 : :
533 : : void
534 : 15 : gwrl_stop(gwrl * rl) {
535 : 15 : flset(rl->flags,GWRL_STOP);
536 : 15 : }
537 : :
538 : : void
539 : 185 : gwrl_time_gather(gwrl * rl) {
540 : 185 : bool update_tsrc = true;
541 : 185 : bool posted_event = false;
542 : 185 : struct timespec current;
543 : 185 : struct timespec timediff;
544 : 185 : gwrlsrc * src = NULL;
545 : 185 : gwrlsrc * del = NULL;
546 : 185 : gwrlsrc_time * tsrc_prev = NULL;
547 : 185 : gwrlsrc_time * tsrc = _gwrlsrct(rl->sources[GWRL_SRC_TYPE_TIME]);
548 [ + + ]: 561 : while(tsrc) {
549 : 376 : src = _gwrlsrc(tsrc);
550 : 376 : update_tsrc = true;
551 [ + + ]: 376 : if(!flisset(src->flags,GWRL_ENABLED)) goto update_tsrc_l;
552 : :
553 : 346 : gwtm_gettimeofday_timespec(¤t);
554 : :
555 [ + + ][ + + ]: 346 : if(!flisset(src->flags,GWRL_WHENCE_ABS) &&
[ + - ]
556 : : tsrc->when.tv_sec == sec_min && tsrc->when.tv_nsec == nsec_min) {
557 : 20 : gwtm_gettimeofday_timespec(&tsrc->when);
558 : 20 : gwtm_add_ms_to_timespec(tsrc->ms,&tsrc->when);
559 : 20 : }
560 : :
561 : 346 : gwtm_timespec_sub_into(&tsrc->when,¤t,&timediff);
562 : :
563 [ + + ]: 346 : if(gwtm_timespec_is_expired(&timediff)) {
564 : 143 : gwrlevt * evt = gwrl_evt_create(rl,src,src->callback,src->userdata,0,0);
565 [ - + ]: 143 : while(!evt) evt = gwrl_evt_create(rl,src,src->callback,src->userdata,0,0);
566 : 143 : gwrl_post_evt(rl,evt);
567 : 143 : posted_event = true;
568 : :
569 [ + + ]: 143 : if(flisset(src->flags,GWRL_REPEAT)) {
570 : :
571 : 118 : gwtm_add_ms_to_timespec(tsrc->ms,&tsrc->when);
572 : 118 : gwtm_timespec_sub_into(&tsrc->when,¤t,&timediff);
573 : :
574 [ + + ][ + - ]: 118 : if(rl->backend->timeout.tv_sec == sec_min && rl->backend->timeout.tv_nsec == nsec_min) {
575 [ - + ]: 10 : memcpy(&rl->backend->timeout,&timediff,sizeof(timediff));
576 : 10 : } else {
577 : 108 : gwtm_timespec_copy_if_smaller(&timediff,&rl->backend->timeout);
578 : : }
579 : :
580 : 118 : } else {
581 : :
582 [ + + ]: 25 : if(flisset(src->flags,GWRL_PERSIST)) {
583 : 16 : gwrl_src_disable(rl,src);
584 : 16 : tsrc->when.tv_sec = sec_min;
585 : 16 : tsrc->when.tv_nsec = nsec_min;
586 : 16 : } else {
587 : 9 : del = src;
588 : 9 : tsrc = (gwrlsrc_time *)src->next;
589 : 9 : gwrl_src_del(rl,del,_gwrlsrc(tsrc_prev),true);
590 : 9 : tsrc_prev = NULL;
591 : 25 : update_tsrc = false;
592 : : }
593 : : }
594 : 143 : } else {
595 [ + + ][ + - ]: 203 : if(rl->backend->timeout.tv_sec == sec_min && rl->backend->timeout.tv_nsec == nsec_min) {
596 [ - + ]: 156 : memcpy(&rl->backend->timeout,&timediff,sizeof(timediff));
597 : 156 : } else {
598 : 346 : gwtm_timespec_copy_if_smaller(&timediff,&rl->backend->timeout);
599 : : }
600 : : }
601 : :
602 : : update_tsrc_l:
603 [ + + ]: 376 : if(update_tsrc) {
604 : 367 : tsrc_prev = tsrc;
605 : 367 : tsrc = _gwrlsrct((_gwrlsrc(tsrc))->next);
606 : 367 : }
607 : 376 : }
608 : :
609 [ + + ]: 185 : if(posted_event) {
610 : 143 : rl->backend->timeout.tv_sec = 0;
611 : 143 : rl->backend->timeout.tv_nsec = 0;
612 : 143 : }
613 : 185 : }
614 : :
615 : : void
616 : 0 : gwrl_install_queued_sources(gwrl * rl) {
617 : 0 : gwrlsrc * src = rl->_qsrc;
618 : 0 : gwrlsrc * isrc = NULL;
619 : 0 : lockid_lock(&rl->_qsrclk);
620 : 0 : rl->_qsrc = NULL;
621 : 0 : lockid_unlock(&rl->_qsrclk);
622 [ # # ]: 0 : while(src) {
623 : 0 : isrc = src;
624 : 0 : src = src->next;
625 : 0 : gwrl_src_add(rl,isrc);
626 : 0 : }
627 : 0 : }
628 : :
629 : : void
630 : 2 : gwrl_install_queued_events(gwrl * rl) {
631 : 2 : gwrlevt * evt = rl->_qevt;
632 : 2 : gwrlevt * pevt = NULL;
633 : 2 : lockid_lock(&rl->_qevtlk);
634 : 2 : rl->_qevt = NULL;
635 : 2 : lockid_unlock(&rl->_qevtlk);
636 [ + + ]: 4 : while(evt) {
637 : 2 : pevt = evt;
638 : 2 : evt = evt->next;
639 : 2 : gwrl_post_evt(rl,pevt);
640 : 2 : }
641 : 2 : }
642 : :
643 : : void
644 : 216 : gwrl_dispatch(gwrl * rl) {
645 : 216 : uint8_t repost_count = 0;
646 : 216 : gwrlevt * evt = rl->events;
647 : 216 : gwrlevt * del = evt;
648 : 216 : rl->events = NULL;
649 [ + + ]: 572 : while(evt) {
650 [ + - ]: 356 : if(evt->callback) evt->callback(rl,evt);
651 : 356 : evt = evt->next;
652 [ + + ][ + + ]: 356 : if(!evt && rl->events && repost_count < GWRL_REDISPATCH_MAX) {
[ + - ]
653 : 101 : gwrl_evt_free_list(rl,del);
654 : 101 : repost_count++;
655 : 101 : evt = rl->events;
656 : 101 : del = evt;
657 : 101 : rl->events = NULL;
658 : 101 : }
659 : 356 : }
660 [ + + ]: 216 : if(del) gwrl_evt_free_list(rl,del);
661 : 216 : }
662 : :
663 : : void
664 : 1 : gwrl_run_once(gwrl * rl) {
665 : 1 : int i = 0;
666 : 0 : if(rl->_qsrc) gwrl_install_queued_sources(rl);
667 [ - + ]: 1 : if(rl->_qevt) gwrl_install_queued_events(rl);
668 : 1 : gwrl_dispatch(rl);
669 : 1 : rl->backend->timeout.tv_sec = sec_min;
670 : 1 : rl->backend->timeout.tv_nsec = nsec_min;
671 [ - + ]: 1 : if(rl->sources[GWRL_SRC_TYPE_TIME]) gwrl_time_gather(rl);
672 : 1 : gwrl_bkd_gather(rl);
673 [ + - ]: 3 : for(; i<rl->options.gwrl_gather_funcs_max; i++) {
674 [ + + ]: 3 : if(!rl->gatherfncs[i]) break;
675 : 2 : ((gwrl_gather_fnc *)rl->gatherfncs[i])(rl);
676 : 2 : }
677 : 1 : }
678 : :
679 : : void
680 : 14 : gwrl_run(gwrl * rl) {
681 : 14 : int i = 0;
682 : 14 : flclr(rl->flags,GWRL_STOP);
683 : 14 : for(;;) {
684 [ - + ]: 211 : if(rl->_qsrc) gwrl_install_queued_sources(rl);
685 [ + + ]: 211 : if(rl->_qevt) gwrl_install_queued_events(rl);
686 : 211 : gwrl_dispatch(rl);
687 [ + + ]: 211 : if(flisset(rl->flags,GWRL_STOP)) {
688 : 14 : flclr(rl->flags,GWRL_STOP);
689 : 14 : break;
690 : : }
691 : 197 : rl->backend->timeout.tv_sec = sec_min;
692 : 197 : rl->backend->timeout.tv_nsec = nsec_min;
693 [ + + ]: 197 : if(rl->sources[GWRL_SRC_TYPE_TIME]) gwrl_time_gather(rl);
694 : 197 : gwrl_bkd_gather(rl);
695 [ + - ]: 207 : for(i=0; i<rl->options.gwrl_gather_funcs_max; i++) {
696 [ + + ]: 207 : if(!rl->gatherfncs[i]) break;
697 : 10 : ((gwrl_gather_fnc *)rl->gatherfncs[i])(rl);
698 : 10 : }
699 : 197 : }
700 : 14 : }
701 : :
702 : : #ifdef __cplusplus
703 : : }
704 : : #endif
|