summaryrefslogtreecommitdiff
path: root/toxav/event.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxav/event.c')
-rw-r--r--toxav/event.c382
1 files changed, 0 insertions, 382 deletions
diff --git a/toxav/event.c b/toxav/event.c
deleted file mode 100644
index 870abf2a..00000000
--- a/toxav/event.c
+++ /dev/null
@@ -1,382 +0,0 @@
1/** event.c
2 *
3 * Copyright (C) 2013 Tox project All Rights Reserved.
4 *
5 * This file is part of Tox.
6 *
7 * Tox is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Tox is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 *
20 *
21 * Report bugs/suggestions at #tox-dev @ freenode.net:6667
22 */
23
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif /* HAVE_CONFIG_H */
28
29#include <stdlib.h>
30#include "../toxcore/network.h" /* current_time_monotonic() */
31#include "event.h"
32
33#define _GNU_SOURCE
34
35#include <assert.h>
36#include <unistd.h>
37#include <stddef.h>
38#include <inttypes.h>
39#include <pthread.h>
40#include <stdio.h>
41
42#define RUN_IN_THREAD(func, args) { pthread_t _tid; \
43pthread_create(&_tid, NULL, func, args); assert( pthread_detach(_tid) == 0 ); }
44
45#define LOCK(event_handler) pthread_mutex_lock (&event_handler->mutex)
46#define UNLOCK(event_handler) pthread_mutex_unlock(&event_handler->mutex)
47
48#define FREQUENCY 10000
49
50#define inline__ inline __attribute__((always_inline))
51
52
53typedef struct _EventContainer {
54 void *(*func)(void *);
55 void *func_args;
56 unsigned timeout;
57 long long id;
58
59} EventContainer;
60
61typedef struct _EventHandler {
62 EventContainer *timed_events;
63 size_t timed_events_count;
64
65 int running;
66
67 pthread_mutex_t mutex;
68
69} EventHandler;
70
71int throw_event( void *(func)(void *), void *arg );
72int reset_timer_event ( int id, uint32_t timeout );
73int throw_timer_event ( void *(func)(void *), void *arg, unsigned timeout);
74int cancel_timer_event ( int id );
75int execute_timer_event ( int id );
76
77struct _Event event = {
78 throw_event,
79 /* reset_timer_event */ NULL,
80 throw_timer_event,
81 cancel_timer_event,
82 /*execute_timer_event*/ NULL
83};
84
85/*
86 * Random functions used by this file
87 */
88void clear_events (EventContainer **event_container, size_t *counter)
89{
90 free(*event_container );
91
92 *event_container = NULL;
93 *counter = 0;
94}
95
96int pop_id ( EventContainer **event_container, size_t *counter, int id )
97{
98 if ( !*event_container || !*counter || !id )
99 return -1;
100
101 EventContainer *_it = *event_container;
102 int i;
103
104 for ( i = *counter; i; -- i ) {
105 if ( _it->id == id ) { /* Hit! */
106 break;
107 }
108
109 ++_it;
110 }
111
112 if ( i ) {
113 for ( ; i; -- i ) {
114 *_it = *(_it + 1);
115 ++_it;
116 }
117
118 -- (*counter );
119
120 if ( !(*counter)) { /* Free and set to NULL */
121 free(*event_container);
122 *event_container = NULL;
123 } else {
124 void *_result = realloc(*event_container, sizeof(EventContainer) * (*counter )); /* resize */
125
126
127 if ( _result != NULL ) {
128 *event_container = _result;
129 return 0;
130 } else {
131 /* Not sure what would happen next so abort execution.
132 */
133 fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
134 abort();
135 return -1;
136 }
137 }
138 }
139
140 /* not found here */
141
142 return -1;
143}
144
145void push_event ( EventContainer **container, size_t *counter, void *(func)(void *), void *arg )
146{
147 EventContainer *_new = realloc((*container ), sizeof(EventContainer) * ((*counter ) + 1));
148
149 if ( _new == NULL ) {
150 /* Not sure what would happen next so abort execution.
151 * TODO: This could notice the calling function
152 * about realloc failing.
153 */
154 fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
155 abort();
156 }
157
158 _new[*counter].func = func;
159 _new[*counter].func_args = arg;
160 _new[*counter].timeout = 0;
161 _new[*counter].id = 0;
162
163 (*container) = _new;
164
165 (*counter )++;
166}
167
168void reorder_events ( size_t counter, EventContainer *container, unsigned timeout )
169{
170 if ( counter > 1 ) {
171
172 int i = counter - 1;
173
174 /* start from behind excluding last added member */
175 EventContainer *_it = &container[i - 1];
176
177 EventContainer _last_added = container[i];
178
179 for ( ; i; --i ) {
180 if ( _it->timeout > timeout ) {
181 *(_it + 1) = *_it;
182 *_it = _last_added;
183 -- _it;
184 }
185 }
186
187 }
188}
189
190/* ============================================= */
191
192/* main poll for event execution */
193void *event_poll( void *arg )
194{
195 EventHandler *_event_handler = arg;
196
197 while ( _event_handler->running ) {
198
199 LOCK( _event_handler );
200
201 if ( _event_handler->timed_events ) {
202
203 uint32_t _time = ((uint32_t)current_time_monotonic());
204
205 if ( _event_handler->timed_events[0].timeout < _time ) {
206
207 RUN_IN_THREAD ( _event_handler->timed_events[0].func,
208 _event_handler->timed_events[0].func_args );
209
210 pop_id(&_event_handler->timed_events,
211 &_event_handler->timed_events_count,
212 _event_handler->timed_events[0].id);
213
214 }
215
216 }
217
218 UNLOCK( _event_handler );
219
220 usleep(FREQUENCY);
221 }
222
223 LOCK( _event_handler );
224
225 clear_events(&_event_handler->timed_events, &_event_handler->timed_events_count);
226
227 UNLOCK( _event_handler );
228
229 _event_handler->running = -1;
230 pthread_exit(NULL);
231}
232
233int throw_event( void *(func)(void *), void *arg )
234{
235 pthread_t _tid;
236 int _rc =
237 pthread_create(&_tid, NULL, func, arg );
238
239 return (0 != _rc ) ? _rc : pthread_detach(_tid);
240}
241
242EventHandler event_handler;
243
244/* Place and order array of timers */
245int throw_timer_event ( void *(func)(void *), void *arg, unsigned timeout)
246{
247 static int _unique_id = 1;
248
249 push_event(&event_handler.timed_events, &(event_handler.timed_events_count), func, arg );
250
251 size_t _counter = event_handler.timed_events_count;
252
253 event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)current_time_monotonic());
254 event_handler.timed_events[_counter - 1].id = _unique_id;
255 ++_unique_id;
256
257
258 /* reorder */
259
260 reorder_events(_counter, event_handler.timed_events, timeout );
261
262 return _unique_id - 1;
263}
264
265int execute_timer_event ( int id )
266{
267 int _status;
268
269 LOCK((&event_handler));
270 EventContainer *_it = event_handler.timed_events;
271
272 int _i = event_handler.timed_events_count;
273
274 /* Find it and execute */
275 for ( ; _i; _i-- ) {
276 if ( _it->id == id ) {
277 RUN_IN_THREAD ( _it->func, _it->func_args );
278 break;
279 }
280
281 ++_it;
282 }
283
284 /* Now remove it from the queue */
285
286 if ( _i ) {
287 for ( ; _i; -- _i ) {
288 *_it = *(_it + 1);
289 ++_it;
290 }
291
292 -- event_handler.timed_events_count;
293
294 if ( !event_handler.timed_events_count ) { /* Free and set to null */
295 free(event_handler.timed_events);
296 event_handler.timed_events = NULL;
297 } else {
298 void *_result = realloc(event_handler.timed_events,
299 sizeof(EventContainer) * event_handler.timed_events_count); /* resize */
300
301 if ( _result != NULL ) {
302 event_handler.timed_events = _result;
303 } else {
304 /* Not sure what would happen next so abort execution.
305 */
306 fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
307 abort();
308 return -1;
309 }
310 }
311
312 _status = 0;
313
314 } else _status = -1;
315
316 UNLOCK((&event_handler));
317
318 return _status;
319}
320
321int reset_timer_event ( int id, uint32_t timeout )
322{
323 int _status;
324
325 LOCK((&event_handler));
326
327 EventContainer *_it = event_handler.timed_events;
328
329 int _i = event_handler.timed_events_count;
330
331 /* Find it and change */
332 for ( ; _i; _i-- ) {
333 if ( _it->id == id ) {
334 _it->timeout = timeout + ((uint32_t)current_time_monotonic());
335 break;
336 }
337
338 ++_it;
339 }
340
341 _status = _i ? -1 : 0;
342
343 UNLOCK((&event_handler));
344
345 return _status;
346}
347
348/* Remove timer from array */
349inline__ int cancel_timer_event ( int id )
350{
351 return pop_id (&event_handler.timed_events, &event_handler.timed_events_count, id );
352}
353
354
355/* Initialization and termination of event polls
356 * This will be run at the beginning and the end of the program execution.
357 * I think that's the best way to do it.
358 */
359
360void __attribute__((constructor)) init_event_poll ()
361{
362 event_handler.timed_events = NULL;
363 event_handler.timed_events_count = 0;
364
365 event_handler.running = 1;
366
367 pthread_mutex_init(&event_handler.mutex, NULL);
368
369 RUN_IN_THREAD(event_poll, &event_handler);
370}
371
372/* NOTE: Do we need this? */
373void __attribute__((destructor)) terminate_event_poll()
374{
375 /* Exit thread */
376 event_handler.running = 0;
377
378 /* Give it enought time to exit */
379 usleep(FREQUENCY * 2);
380
381 pthread_mutex_destroy( &event_handler.mutex );
382} \ No newline at end of file