summaryrefslogtreecommitdiff
path: root/toxcore/event.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/event.c')
-rwxr-xr-xtoxcore/event.c230
1 files changed, 135 insertions, 95 deletions
diff --git a/toxcore/event.c b/toxcore/event.c
index 17e68c87..81f8172f 100755
--- a/toxcore/event.c
+++ b/toxcore/event.c
@@ -39,11 +39,12 @@
39#include <stddef.h> 39#include <stddef.h>
40#include <inttypes.h> 40#include <inttypes.h>
41#include <pthread.h> 41#include <pthread.h>
42#include <stdio.h>
42 43
43#define RUN_IN_THREAD(func, args) { pthread_t _tid; \ 44#define RUN_IN_THREAD(func, args) { pthread_t _tid; \
44 pthread_create(&_tid, NULL, func, args); assert( pthread_detach(_tid) == 0 ); } 45pthread_create(&_tid, NULL, func, args); assert( pthread_detach(_tid) == 0 ); }
45 46
46#define LOCK(event_handler) pthread_mutex_lock (&event_handler->mutex) 47#define LOCK(event_handler) pthread_mutex_lock (&event_handler->mutex)
47#define UNLOCK(event_handler) pthread_mutex_unlock(&event_handler->mutex) 48#define UNLOCK(event_handler) pthread_mutex_unlock(&event_handler->mutex)
48 49
49#define FREQUENCY 10000 50#define FREQUENCY 10000
@@ -52,21 +53,21 @@
52 53
53 54
54typedef struct _EventContainer { 55typedef struct _EventContainer {
55 void* (*func)(void*); 56 void* (*func)(void*);
56 void* func_args; 57 void* func_args;
57 unsigned timeout; 58 unsigned timeout;
58 long long id; 59 long long id;
59 60
60} EventContainer; 61} EventContainer;
61 62
62typedef struct _EventHandler { 63typedef struct _EventHandler {
63 EventContainer* timed_events; 64 EventContainer* timed_events;
64 size_t timed_events_count; 65 size_t timed_events_count;
65 66
66 int running; 67 int running;
67 68
68 pthread_mutex_t mutex; 69 pthread_mutex_t mutex;
69 70
70} EventHandler; 71} EventHandler;
71 72
72int throw_event( void* (func)(void*), void* arg ); 73int throw_event( void* (func)(void*), void* arg );
@@ -90,7 +91,7 @@ struct _Event event =
90void clear_events (EventContainer** event_container, size_t* counter) 91void clear_events (EventContainer** event_container, size_t* counter)
91{ 92{
92 free(*event_container ); 93 free(*event_container );
93 94
94 *event_container = NULL; 95 *event_container = NULL;
95 *counter = 0; 96 *counter = 0;
96} 97}
@@ -99,62 +100,86 @@ int pop_id ( EventContainer** event_container, size_t* counter, int id )
99{ 100{
100 if ( !*event_container || !*counter || !id ) 101 if ( !*event_container || !*counter || !id )
101 return -1; 102 return -1;
102 103
103 EventContainer* _it = *event_container; 104 EventContainer* _it = *event_container;
104 int i; 105 int i;
105 106
106 for ( i = *counter; i; -- i ){ 107 for ( i = *counter; i; -- i ){
107 if ( _it->id == id ) { /* Hit! */ 108 if ( _it->id == id ) { /* Hit! */
108 break; 109 break;
109 } 110 }
110 ++_it; 111 ++_it;
111 } 112 }
112 113
113 if ( i ) { 114 if ( i ) {
114 for ( ; i; -- i ){ *_it = *(_it + 1); ++_it; } 115 for ( ; i; -- i ){ *_it = *(_it + 1); ++_it; }
115 -- (*counter ); 116 -- (*counter );
116 *event_container = realloc(*event_container, sizeof(EventContainer) * (*counter )); /* resize */ 117
117 118 if ( !(*counter)) { /* Free and set to NULL */
118 return 0; 119 free(*event_container);
119 120 *event_container = NULL;
121 }
122 else {
123 void* _result = realloc(*event_container, sizeof(EventContainer) * (*counter )); /* resize */
124
125
126 if ( _result != NULL ) { *event_container = _result; return 0; }
127 else {
128 /* Not sure what would happen next so abort execution.
129 */
130 fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
131 abort();
132 return -1;
133 }
134 }
120 } 135 }
121 136
122 /* not found here */ 137 /* not found here */
123 138
124 return -1; 139 return -1;
125} 140}
126 141
127void push_event ( EventContainer** container, size_t* counter, void* (func)(void*), void* arg ) 142void push_event ( EventContainer** container, size_t* counter, void* (func)(void*), void* arg )
128{ 143{
129 (*container ) = realloc((*container ), sizeof(EventContainer) * ((*counter ) + 1)); 144 EventContainer* _new = realloc((*container ), sizeof(EventContainer) * ((*counter ) + 1));
130 assert((*container ) != NULL); 145
131 146 if ( _new == NULL ) {
132 (*container )[*counter].func = func; 147 /* Not sure what would happen next so abort execution.
133 (*container )[*counter].func_args = arg; 148 * TODO: This could notice the calling function
134 (*container )[*counter].timeout = 0; 149 * about realloc failing.
135 (*container )[*counter].id = 0; 150 */
136 151 fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
152 abort();
153 }
154
155 _new[*counter].func = func;
156 _new[*counter].func_args = arg;
157 _new[*counter].timeout = 0;
158 _new[*counter].id = 0;
159
160 (*container) = _new;
161
137 (*counter )++; 162 (*counter )++;
138} 163}
139 164
140void reorder_events ( size_t counter, EventContainer* container, unsigned timeout ) 165void reorder_events ( size_t counter, EventContainer* container, unsigned timeout )
141{ 166{
142 if ( counter > 1 ) { 167 if ( counter > 1 ) {
143 168
144 int i = counter - 1; 169 int i = counter - 1;
145 170
146 /* start from behind excluding last added member */ 171 /* start from behind excluding last added member */
147 EventContainer* _it = &container[i - 1]; 172 EventContainer* _it = &container[i - 1];
148 173
149 EventContainer _last_added = container[i]; 174 EventContainer _last_added = container[i];
150 175
151 for ( ; i; --i ) { 176 for ( ; i; --i ) {
152 if ( _it->timeout > timeout ){ 177 if ( _it->timeout > timeout ){
153 *(_it + 1) = *_it; 178 *(_it + 1) = *_it;
154 *_it = _last_added; -- _it; 179 *_it = _last_added; -- _it;
155 } 180 }
156 } 181 }
157 182
158 } 183 }
159} 184}
160 185
@@ -164,40 +189,40 @@ void reorder_events ( size_t counter, EventContainer* container, unsigned timeou
164void* event_poll( void* arg ) 189void* event_poll( void* arg )
165{ 190{
166 EventHandler* _event_handler = arg; 191 EventHandler* _event_handler = arg;
167 192
168 while ( _event_handler->running ) 193 while ( _event_handler->running )
169 { 194 {
170 195
171 LOCK( _event_handler ); 196 LOCK( _event_handler );
172 197
173 if ( _event_handler->timed_events ){ 198 if ( _event_handler->timed_events ){
174 199
175 uint32_t _time = ((uint32_t)(current_time() / 1000)); 200 uint32_t _time = ((uint32_t)(current_time() / 1000));
176 201
177 if ( _event_handler->timed_events[0].timeout < _time ) { 202 if ( _event_handler->timed_events[0].timeout < _time ) {
178 203
179 RUN_IN_THREAD ( _event_handler->timed_events[0].func, 204 RUN_IN_THREAD ( _event_handler->timed_events[0].func,
180 _event_handler->timed_events[0].func_args ); 205 _event_handler->timed_events[0].func_args );
181 206
182 pop_id(&_event_handler->timed_events, 207 pop_id(&_event_handler->timed_events,
183 &_event_handler->timed_events_count, 208 &_event_handler->timed_events_count,
184 _event_handler->timed_events[0].id); 209 _event_handler->timed_events[0].id);
185 210
186 } 211 }
187 212
188 } 213 }
189 214
190 UNLOCK( _event_handler ); 215 UNLOCK( _event_handler );
191 216
192 usleep(FREQUENCY); 217 usleep(FREQUENCY);
193 } 218 }
194 219
195LOCK( _event_handler ); 220 LOCK( _event_handler );
196 221
197 clear_events(&_event_handler->timed_events, &_event_handler->timed_events_count); 222 clear_events(&_event_handler->timed_events, &_event_handler->timed_events_count);
198 223
199UNLOCK( _event_handler ); 224 UNLOCK( _event_handler );
200 225
201 _event_handler->running = -1; 226 _event_handler->running = -1;
202 pthread_exit(NULL); 227 pthread_exit(NULL);
203} 228}
@@ -207,7 +232,7 @@ int throw_event( void* (func)(void*), void* arg )
207 pthread_t _tid; 232 pthread_t _tid;
208 int _rc = 233 int _rc =
209 pthread_create(&_tid, NULL, func, arg ); 234 pthread_create(&_tid, NULL, func, arg );
210 235
211 return (0 != _rc ) ? _rc : pthread_detach(_tid); 236 return (0 != _rc ) ? _rc : pthread_detach(_tid);
212} 237}
213 238
@@ -217,31 +242,31 @@ EventHandler event_handler;
217int throw_timer_event ( void* (func)(void*), void* arg, unsigned timeout) 242int throw_timer_event ( void* (func)(void*), void* arg, unsigned timeout)
218{ 243{
219 static int _unique_id = 1; 244 static int _unique_id = 1;
220 245
221 push_event(&event_handler.timed_events, &(event_handler.timed_events_count), func, arg ); 246 push_event(&event_handler.timed_events, &(event_handler.timed_events_count), func, arg );
222 247
223 size_t _counter = event_handler.timed_events_count; 248 size_t _counter = event_handler.timed_events_count;
224 249
225 event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)(current_time() / 1000)); 250 event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)(current_time() / 1000));
226 event_handler.timed_events[_counter - 1].id = _unique_id; ++_unique_id; 251 event_handler.timed_events[_counter - 1].id = _unique_id; ++_unique_id;
227 252
228 253
229 /* reorder */ 254 /* reorder */
230 255
231 reorder_events(_counter, event_handler.timed_events, timeout ); 256 reorder_events(_counter, event_handler.timed_events, timeout );
232 257
233 return _unique_id - 1; 258 return _unique_id - 1;
234} 259}
235 260
236int execute_timer_event ( int id ) 261int execute_timer_event ( int id )
237{ 262{
238 int _status; 263 int _status;
239 264
240LOCK((&event_handler)); 265 LOCK((&event_handler));
241 EventContainer* _it = event_handler.timed_events; 266 EventContainer* _it = event_handler.timed_events;
242 267
243 int _i = event_handler.timed_events_count; 268 int _i = event_handler.timed_events_count;
244 269
245 /* Find it and execute */ 270 /* Find it and execute */
246 for ( ; _i; _i-- ) { 271 for ( ; _i; _i-- ) {
247 if ( _it->id == id ) { 272 if ( _it->id == id ) {
@@ -250,36 +275,51 @@ LOCK((&event_handler));
250 } 275 }
251 ++_it; 276 ++_it;
252 } 277 }
253 278
254 /* Now remove it from the queue */ 279 /* Now remove it from the queue */
255 280
256 if ( _i ) { 281 if ( _i ) {
257 for ( ; _i; -- _i ){ *_it = *(_it + 1); ++_it; } 282 for ( ; _i; -- _i ){ *_it = *(_it + 1); ++_it; }
283
258 -- event_handler.timed_events_count; 284 -- event_handler.timed_events_count;
259 285
260 event_handler.timed_events = realloc 286 if ( !event_handler.timed_events_count ) { /* Free and set to null */
261 (event_handler.timed_events, sizeof(EventContainer) * event_handler.timed_events_count); /* resize */ 287 free(event_handler.timed_events);
262 288 event_handler.timed_events = NULL;
289 }
290 else {
291 void* _result = realloc(event_handler.timed_events, sizeof(EventContainer) * event_handler.timed_events_count); /* resize */
292
293 if ( _result != NULL ) { event_handler.timed_events = _result; }
294 else {
295 /* Not sure what would happen next so abort execution.
296 */
297 fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
298 abort();
299 return -1;
300 }
301 }
302
263 _status = 0; 303 _status = 0;
264 304
265 } 305 }
266 else _status = -1; 306 else _status = -1;
267 307
268UNLOCK((&event_handler)); 308 UNLOCK((&event_handler));
269 309
270 return _status; 310 return _status;
271} 311}
272 312
273int reset_timer_event ( int id, uint32_t timeout ) 313int reset_timer_event ( int id, uint32_t timeout )
274{ 314{
275 int _status; 315 int _status;
276 316
277LOCK((&event_handler)); 317 LOCK((&event_handler));
278 318
279 EventContainer* _it = event_handler.timed_events; 319 EventContainer* _it = event_handler.timed_events;
280 320
281 int _i = event_handler.timed_events_count; 321 int _i = event_handler.timed_events_count;
282 322
283 /* Find it and change */ 323 /* Find it and change */
284 for ( ; _i; _i-- ) { 324 for ( ; _i; _i-- ) {
285 if ( _it->id == id ) { 325 if ( _it->id == id ) {
@@ -288,11 +328,11 @@ LOCK((&event_handler));
288 } 328 }
289 ++_it; 329 ++_it;
290 } 330 }
291 331
292 _status = _i ? -1 : 0; 332 _status = _i ? -1 : 0;
293 333
294UNLOCK((&event_handler)); 334 UNLOCK((&event_handler));
295 335
296 return _status; 336 return _status;
297} 337}
298 338
@@ -312,11 +352,11 @@ void __attribute__((constructor)) init_event_poll ()
312{ 352{
313 event_handler.timed_events = NULL; 353 event_handler.timed_events = NULL;
314 event_handler.timed_events_count = 0; 354 event_handler.timed_events_count = 0;
315 355
316 event_handler.running = 1; 356 event_handler.running = 1;
317 357
318 pthread_mutex_init(&event_handler.mutex, NULL); 358 pthread_mutex_init(&event_handler.mutex, NULL);
319 359
320 RUN_IN_THREAD(event_poll, &event_handler); 360 RUN_IN_THREAD(event_poll, &event_handler);
321} 361}
322 362
@@ -326,10 +366,10 @@ void __attribute__((destructor)) terminate_event_poll()
326 event_handler.running = 0; 366 event_handler.running = 0;
327 367
328 /* Keep the global until thread exits */ 368 /* Keep the global until thread exits */
329 while (event_handler.running > -1) { 369 while (event_handler.running > -1) {
330 event_handler.running; 370 (void)event_handler.running;
331 usleep(FREQUENCY*2); 371 usleep(FREQUENCY*2);
332 } 372 }
333 373
334 pthread_mutex_destroy( &event_handler.mutex ); 374 pthread_mutex_destroy( &event_handler.mutex );
335} 375} \ No newline at end of file