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