3
#include "LinkedList.h"
6
Copyright (c) 2013-2016 Gustav Hartvigsson
8
Permission is hereby granted, free of charge, to any person obtaining a copy
9
of this software and associated documentation files (the "Software"), to deal
10
in the Software without restriction, including without limitation the rights
11
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
copies of the Software, and to permit persons to whom the Software is
13
furnished to do so, subject to the following conditions:
15
The above copyright notice and this permission notice shall be included in
16
all copies or substantial portions of the Software.
18
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28
* The default mainloop, it is hidden.
31
_default_main_loop = NULL;
34
* The items that are held by the linked lists in SMainLoop.
36
typedef struct SMainLoopItem {
37
SMainLoopState state; /* in what list should this item be? */
38
sboolean is_alive; /* If this is TRUE then this can be removed. */
40
RunFunc callback; /* The callback that is run. */
41
spointer user_data; /* Pointer to the user data that was provided. */
44
typedef struct SMainLoopTeardownHandler {
45
Callback teardown_handler;
50
} SMainLoopTeardownHandler;
52
/* This is the freeing function for MainLoopTeardownHandler objcets it also
53
* calls the teardown handler.
55
* This reduces the iteration time for the teardown.
58
_s_main_loop_teardown_handerer_obj_free (SMainLoopTeardownHandler * self);
62
SMainLoopState ring_1_state;
63
SMainLoopState ring_2_state;
66
SMutex * mutex[S_MAIN_LOOP_RING_LAST][S_MAIN_LOOP_STATE_LAST];
68
SLinkedList * ring_1_event_handler_list;
69
SLinkedList * ring_1_io_push_list;
70
SLinkedList * ring_1_io_pull_list;
71
SLinkedList * ring_1_workers_list;
73
SLinkedList * ring_2_event_handler_list;
74
SLinkedList * ring_2_io_push_list;
75
SLinkedList * ring_2_io_pull_list;
76
SLinkedList * ring_2_workers_list;
78
SLinkedList * teardown_handler_list;
80
SMutex * teardown_handler_mutex;
84
s_main_loop_state_get_name (SMainLoopState state) {
85
return SMainLoopStateName[state];
89
s_main_loop_ring_get_name (SMainLoopRing ring) {
90
return SMainLoopStateName[ring];
93
/* ************************************************************************** */
96
_s_main_loop_do_list (SLinkedList * event_handler_list);
99
_s_main_loop_do_ring_two (SMainLoop * self);
101
/* -----------------------------------------------------------------------------
102
* imprementation of the real functions and stuffs.
103
* -----------------------------------------------------------------------------
108
SMainLoop * self = malloc (sizeof (SMainLoop));
110
for (sint i = 0; i < S_MAIN_LOOP_RING_LAST; i++){
111
for (sint j = 0; j < S_MAIN_LOOP_STATE_LAST; j++){
112
self->mutex[i][j] = s_mutex_new ();
116
self->teardown_handler_mutex = s_mutex_new ();
118
s_mutex_lock (self->mutex[S_MAIN_LOOP_RING_NONE][S_MAIN_LOOP_STATE_NONE]);
121
self->ring_1_state = S_MAIN_LOOP_STATE_EVENT;
122
self->ring_2_state = S_MAIN_LOOP_STATE_EVENT;
123
self->is_run = FALSE;
125
self->ring_1_event_handler_list = s_linked_list_new (FREEFUNC (free));
126
self->ring_1_io_push_list = s_linked_list_new (FREEFUNC (free));
127
self->ring_1_io_pull_list = s_linked_list_new (FREEFUNC (free));
128
self->ring_1_workers_list = s_linked_list_new (FREEFUNC (free));
130
self->ring_2_event_handler_list = s_linked_list_new (FREEFUNC (free));
131
self->ring_2_io_push_list = s_linked_list_new (FREEFUNC (free));
132
self->ring_2_io_pull_list = s_linked_list_new (FREEFUNC (free));
133
self->ring_2_workers_list = s_linked_list_new (FREEFUNC (free));
135
self->teardown_handler_list = s_linked_list_new (FREEFUNC (_s_main_loop_teardown_handerer_obj_free));
137
s_mutex_unlock (self->mutex[S_MAIN_LOOP_RING_NONE][S_MAIN_LOOP_STATE_NONE]);
143
s_main_loop_get_default () {
144
if (_default_main_loop == NULL) {
145
_default_main_loop = s_main_loop_new ();
147
return _default_main_loop;
151
s_main_loop_run (SMainLoop * self) {
152
assert (self != NULL);
154
while (self->is_run) {
155
switch (self->ring_1_state) {
156
case (S_MAIN_LOOP_STATE_EVENT):
157
_s_main_loop_do_list (self->ring_1_event_handler_list);
158
self->ring_1_state = S_MAIN_LOOP_STATE_IO_PUSH;
160
case (S_MAIN_LOOP_STATE_IO_PUSH):
161
_s_main_loop_do_list (self->ring_1_io_push_list);
162
self->ring_1_state = S_MAIN_LOOP_STATE_IO_PULL;
164
case (S_MAIN_LOOP_STATE_IO_PULL):
165
_s_main_loop_do_list (self->ring_1_io_pull_list);
166
self->ring_1_state = S_MAIN_LOOP_STATE_RING_TWO_NEXT;
168
case (S_MAIN_LOOP_STATE_RING_TWO_NEXT):
169
_s_main_loop_do_ring_two (self);
170
self->ring_1_state = S_MAIN_LOOP_STATE_DO_WORKERS;
172
case (S_MAIN_LOOP_STATE_DO_WORKERS):
173
_s_main_loop_do_list (self->ring_1_workers_list);
174
self->ring_1_state = S_MAIN_LOOP_STATE_SLEEP;
176
case (S_MAIN_LOOP_STATE_SLEEP):
178
self->ring_1_state = S_MAIN_LOOP_STATE_EVENT;
181
s_err_print ("Reaching a place that should not be reached.\n"
185
s_mutex_lock (self->mutex[S_MAIN_LOOP_RING_NONE][S_MAIN_LOOP_STATE_NONE]);
187
sint no_of_handlers = 0;
189
no_of_handlers += s_linked_list_len (self->ring_1_event_handler_list);
190
no_of_handlers += s_linked_list_len (self->ring_1_io_push_list);
191
no_of_handlers += s_linked_list_len (self->ring_1_io_pull_list);
192
no_of_handlers += s_linked_list_len (self->ring_1_workers_list);
194
no_of_handlers += s_linked_list_len (self->ring_2_event_handler_list);
195
no_of_handlers += s_linked_list_len (self->ring_2_io_push_list);
196
no_of_handlers += s_linked_list_len (self->ring_2_io_pull_list);
197
no_of_handlers += s_linked_list_len (self->ring_2_workers_list);
199
if (!self->is_run || no_of_handlers == 0) {
200
s_mutex_unlock (self->mutex[S_MAIN_LOOP_RING_NONE][S_MAIN_LOOP_STATE_NONE]);
203
s_mutex_unlock (self->mutex[S_MAIN_LOOP_RING_NONE][S_MAIN_LOOP_STATE_NONE]);
209
s_main_loop_quit (SMainLoop * self) {
210
s_mutex_lock (self->mutex[S_MAIN_LOOP_RING_NONE][S_MAIN_LOOP_STATE_NONE]);
211
self->is_run = FALSE;
213
s_linked_list_free (self->ring_1_event_handler_list, TRUE);
214
s_linked_list_free (self->ring_1_io_push_list, TRUE);
215
s_linked_list_free (self->ring_1_io_pull_list, TRUE);
216
s_linked_list_free (self->ring_1_workers_list, TRUE);
218
s_linked_list_free (self->ring_2_event_handler_list, TRUE);
219
s_linked_list_free (self->ring_2_io_push_list, TRUE);
220
s_linked_list_free (self->ring_2_io_pull_list, TRUE);
221
s_linked_list_free (self->ring_2_workers_list, TRUE);
223
s_linked_list_free (self->teardown_handler_list, TRUE);
225
for (sint i = 0; i < S_MAIN_LOOP_RING_LAST; i++) {
226
for (sint j = 0; j < S_MAIN_LOOP_STATE_LAST; j++) {
227
s_print ("[%d][%d]\n",i,j);
228
s_mutex_free (self->mutex[i][j]);
232
s_mutex_free (self->teardown_handler_mutex);
238
s_main_loop_ref (SMainLoop * self) {
243
s_main_loop_unref (SMainLoop * self) {
248
s_main_loop_add_event_handler (SMainLoop * self,
250
RunFunc event_handler,
251
spointer user_data) {
253
s_mutex_lock (self->mutex[ring][S_MAIN_LOOP_STATE_EVENT]);
254
if (user_data == NULL) {
255
s_err_print ("No user data provided to the event handeler."
256
" This is an error.");
261
SMainLoopItem * item = malloc (sizeof (SMainLoopItem));
262
item->state = S_MAIN_LOOP_STATE_EVENT;
263
item->callback = event_handler;
264
item->user_data = user_data;
265
item->is_alive = TRUE;
268
case (S_MAIN_LOOP_RING_ONE):
269
s_linked_list_append (self->ring_1_event_handler_list, item);
271
case (S_MAIN_LOOP_RING_TWO):
272
s_linked_list_append (self->ring_2_event_handler_list, item);
275
s_err_print ("Invalid value of the ring parameter for "
276
"s_main_loop_add_io_pull function.");
278
s_mutex_unlock (self->mutex[ring][S_MAIN_LOOP_STATE_EVENT]);
282
s_main_loop_add_io_push (SMainLoop * self,
284
RunFunc push_callback,
285
spointer user_data) {
287
s_mutex_lock (self->mutex[ring][S_MAIN_LOOP_STATE_IO_PUSH]);
288
if (user_data == NULL) {
289
s_err_print ("No user data provided to the IO push event."
290
" This is an error.");
295
SMainLoopItem * item = malloc (sizeof (SMainLoopItem));
296
item->state = S_MAIN_LOOP_STATE_IO_PUSH;
297
item->callback = push_callback;
298
item->user_data = user_data;
299
item->is_alive = TRUE;
302
case (S_MAIN_LOOP_RING_ONE):
303
s_linked_list_append (self->ring_1_io_push_list, item);
305
case (S_MAIN_LOOP_RING_TWO):
306
s_linked_list_append (self->ring_2_io_push_list, item);
309
s_err_print ("Invalid value of the ring parameter for "
310
"s_main_loop_add_io_push function.");
312
s_mutex_unlock (self->mutex[ring][S_MAIN_LOOP_STATE_IO_PUSH]);
316
s_main_loop_add_io_pull (SMainLoop * self,
318
RunFunc pull_callback,
319
spointer user_data) {
321
s_mutex_lock (self->mutex[ring][S_MAIN_LOOP_STATE_IO_PULL]);
322
if (user_data == NULL) {
323
s_err_print ("No user data provided to the IO pull event."
324
" This is an error.");
329
SMainLoopItem * item = malloc (sizeof (SMainLoopItem));
330
item->state = S_MAIN_LOOP_STATE_IO_PULL;
331
item->callback = pull_callback;
332
item->user_data = user_data;
333
item->is_alive = TRUE;
336
case (S_MAIN_LOOP_RING_ONE):
337
s_linked_list_append (self->ring_1_io_pull_list, item);
339
case (S_MAIN_LOOP_RING_TWO):
340
s_linked_list_append (self->ring_2_io_pull_list, item);
343
s_err_print ("Invalid value of the ring parameter for "
344
"s_main_loop_add_ function.");
346
s_mutex_unlock (self->mutex[ring][S_MAIN_LOOP_STATE_IO_PULL]);
350
s_main_loop_add_worker (SMainLoop * self,
352
RunFunc worker_callback,
353
spointer user_data) {
355
s_mutex_lock (self->mutex[ring][S_MAIN_LOOP_STATE_DO_WORKERS]);
356
s_dbg_print ("locked");
358
SMainLoopItem * item = malloc (sizeof (SMainLoopItem));
359
item->state = S_MAIN_LOOP_STATE_DO_WORKERS;
360
item->callback = worker_callback;
361
item->user_data = user_data;
362
item->is_alive = TRUE;
365
case (S_MAIN_LOOP_RING_ONE):
366
s_linked_list_append (self->ring_1_workers_list, item);
368
case (S_MAIN_LOOP_RING_TWO):
369
s_linked_list_append (self->ring_2_workers_list, item);
372
s_err_print ("Invalid value of the ring parameter for "
373
"s_main_loop_add_worker function.");
375
s_mutex_unlock (self->mutex[ring][S_MAIN_LOOP_STATE_DO_WORKERS]);
376
s_dbg_print ("Unlocked");
380
s_main_loop_add_teardown_handler (SMainLoop * self,
381
Callback teardown_handler,
383
spointer user_data) {
384
s_mutex_lock (self->teardown_handler_mutex);
386
s_err_print ("No self pointer provided for the teardown handler "
387
"This is an error.");
391
SMainLoopTeardownHandler * item = malloc (sizeof (SMainLoopTeardownHandler));
393
item->teardown_handler = teardown_handler;
394
item->obj_self = self_obj;
395
item->user_data = user_data;
397
s_linked_list_append (self->teardown_handler_list, item);
398
s_mutex_unlock (self->teardown_handler_mutex);
401
/* ************************************************************************** */
404
_s_main_loop_teardown_handerer_obj_free (SMainLoopTeardownHandler * self) {
405
Callback callback = self->teardown_handler;
406
callback (self->obj_self, self->user_data);
411
_s_main_loop_do_list (SLinkedList * event_handler_list) {
412
if (s_linked_list_len (event_handler_list) == 0) {
416
s_linked_list_head (event_handler_list);
418
SMainLoopItem * item = s_linked_list_get_current (event_handler_list);
419
RunFunc callback = item->callback;
420
spointer user_data = item->user_data;
422
item->is_alive = callback (user_data);
423
} while (s_linked_list_next (event_handler_list));
425
s_linked_list_head (event_handler_list);
427
SMainLoopItem * item = s_linked_list_get_current (event_handler_list);
428
if (!item->is_alive) {
429
s_linked_list_remove_current (event_handler_list, TRUE);
431
} while (s_linked_list_next (event_handler_list));
436
_s_main_loop_do_ring_two (SMainLoop * self) {
437
switch (self->ring_2_state) {
438
case (S_MAIN_LOOP_STATE_EVENT):
439
_s_main_loop_do_list (self->ring_2_event_handler_list);
440
self->ring_2_state = S_MAIN_LOOP_STATE_IO_PUSH;
442
case (S_MAIN_LOOP_STATE_IO_PUSH):
443
_s_main_loop_do_list (self->ring_2_io_push_list);
444
self->ring_2_state = S_MAIN_LOOP_STATE_IO_PULL;
446
case (S_MAIN_LOOP_STATE_IO_PULL):
447
_s_main_loop_do_list (self->ring_2_io_pull_list);
448
self->ring_2_state = S_MAIN_LOOP_STATE_DO_WORKERS;
450
case (S_MAIN_LOOP_STATE_DO_WORKERS):
451
_s_main_loop_do_list (self->ring_2_workers_list);
452
self->ring_2_state = S_MAIN_LOOP_STATE_EVENT;
455
s_err_print ("Reaching a place that should not be reached.\n"