summaryrefslogtreecommitdiff
path: root/src/lib/evas/canvas/evas_async_events.c
diff options
context:
space:
mode:
authorCedric Bail <cedric.bail@samsung.com>2013-05-30 15:42:56 +0900
committerCedric Bail <cedric.bail@samsung.com>2013-06-04 11:20:25 +0900
commit4d15a0f50f8680de22ea6ced009d666e9ae6be3f (patch)
treea497ff66fea181eb533357e7c46bda444681ba2b /src/lib/evas/canvas/evas_async_events.c
parentb52a380a5f3e198c25b27e540315268c75e6d6cf (diff)
evas: add infra to block the main loop from evas.
PS: later on, I think we should just move evas to use Ecore infra directly to create jobs and sync with the main loop.
Diffstat (limited to 'src/lib/evas/canvas/evas_async_events.c')
-rw-r--r--src/lib/evas/canvas/evas_async_events.c142
1 files changed, 141 insertions, 1 deletions
diff --git a/src/lib/evas/canvas/evas_async_events.c b/src/lib/evas/canvas/evas_async_events.c
index 2bab528..c6e9c0e 100644
--- a/src/lib/evas/canvas/evas_async_events.c
+++ b/src/lib/evas/canvas/evas_async_events.c
@@ -12,7 +12,6 @@
12#include "evas_private.h" 12#include "evas_private.h"
13 13
14typedef struct _Evas_Event_Async Evas_Event_Async; 14typedef struct _Evas_Event_Async Evas_Event_Async;
15
16struct _Evas_Event_Async 15struct _Evas_Event_Async
17{ 16{
18 const void *target; 17 const void *target;
@@ -21,6 +20,28 @@ struct _Evas_Event_Async
21 Evas_Callback_Type type; 20 Evas_Callback_Type type;
22}; 21};
23 22
23typedef struct _Evas_Safe_Call Evas_Safe_Call;
24struct _Evas_Safe_Call
25{
26 Eina_Condition c;
27 Eina_Lock m;
28
29 int current_id;
30};
31
32static Eina_Lock _thread_mutex;
33static Eina_Condition _thread_cond;
34
35static Eina_Lock _thread_feedback_mutex;
36static Eina_Condition _thread_feedback_cond;
37
38static int _thread_loop = 0;
39
40static Eina_Lock _thread_id_lock;
41static int _thread_id = -1;
42static int _thread_id_max = 0;
43static int _thread_id_update = 0;
44
24static int _fd_write = -1; 45static int _fd_write = -1;
25static int _fd_read = -1; 46static int _fd_read = -1;
26static pid_t _fd_pid = 0; 47static pid_t _fd_pid = 0;
@@ -81,6 +102,14 @@ evas_async_events_init(void)
81 eina_lock_new(&async_lock); 102 eina_lock_new(&async_lock);
82 eina_inarray_step_set(&async_queue, sizeof (Eina_Inarray), sizeof (Evas_Event_Async), 16); 103 eina_inarray_step_set(&async_queue, sizeof (Eina_Inarray), sizeof (Evas_Event_Async), 16);
83 104
105 eina_lock_new(&_thread_mutex);
106 eina_condition_new(&_thread_cond, &_thread_mutex);
107
108 eina_lock_new(&_thread_feedback_mutex);
109 eina_condition_new(&_thread_feedback_cond, &_thread_feedback_mutex);
110
111 eina_lock_new(&_thread_id_lock);
112
84 return _init_evas_event; 113 return _init_evas_event;
85} 114}
86 115
@@ -90,6 +119,12 @@ evas_async_events_shutdown(void)
90 _init_evas_event--; 119 _init_evas_event--;
91 if (_init_evas_event > 0) return _init_evas_event; 120 if (_init_evas_event > 0) return _init_evas_event;
92 121
122 eina_condition_free(&_thread_cond);
123 eina_lock_free(&_thread_mutex);
124 eina_condition_free(&_thread_feedback_cond);
125 eina_lock_free(&_thread_feedback_mutex);
126 eina_lock_free(&_thread_id_lock);
127
93 eina_lock_free(&async_lock); 128 eina_lock_free(&async_lock);
94 eina_inarray_flush(&async_queue); 129 eina_inarray_flush(&async_queue);
95 free(async_queue_cache); 130 free(async_queue_cache);
@@ -284,3 +319,108 @@ evas_async_events_put(const void *target, Evas_Callback_Type type, void *event_i
284 319
285 return ret; 320 return ret;
286} 321}
322
323static void
324_evas_thread_main_loop_lock(void *target EINA_UNUSED,
325 Evas_Callback_Type type EINA_UNUSED,
326 void *event_info)
327{
328 Evas_Safe_Call *call = event_info;
329
330 eina_lock_take(&_thread_mutex);
331
332 eina_lock_take(&call->m);
333 _thread_id = call->current_id;
334 eina_condition_broadcast(&call->c);
335 eina_lock_release(&call->m);
336
337 while (_thread_id_update != _thread_id)
338 eina_condition_wait(&_thread_cond);
339 eina_lock_release(&_thread_mutex);
340
341 eina_main_loop_define();
342
343 eina_lock_take(&_thread_feedback_mutex);
344
345 _thread_id = -1;
346
347 eina_condition_broadcast(&_thread_feedback_cond);
348 eina_lock_release(&_thread_feedback_mutex);
349
350 eina_condition_free(&call->c);
351 eina_lock_free(&call->m);
352 free(call);
353}
354
355EAPI int
356evas_thread_main_loop_begin(void)
357{
358 Evas_Safe_Call *order;
359
360 if (eina_main_loop_is())
361 {
362 return ++_thread_loop;
363 }
364
365 order = malloc(sizeof (Evas_Safe_Call));
366 if (!order) return -1;
367
368 eina_lock_take(&_thread_id_lock);
369 order->current_id = ++_thread_id_max;
370 if (order->current_id < 0)
371 {
372 _thread_id_max = 0;
373 order->current_id = ++_thread_id_max;
374 }
375 eina_lock_release(&_thread_id_lock);
376
377 eina_lock_new(&order->m);
378 eina_condition_new(&order->c, &order->m);
379
380 evas_async_events_put(NULL, 0, order, _evas_thread_main_loop_lock);
381
382 eina_lock_take(&order->m);
383 while (order->current_id != _thread_id)
384 eina_condition_wait(&order->c);
385 eina_lock_release(&order->m);
386
387 eina_main_loop_define();
388
389 _thread_loop = 1;
390
391 return _thread_loop;
392}
393
394EAPI int
395evas_thread_main_loop_end(void)
396{
397 int current_id;
398
399 if (_thread_loop == 0)
400 abort();
401
402 /* until we unlock the main loop, this thread has the main loop id */
403 if (!eina_main_loop_is())
404 {
405 ERR("Not in a locked thread !");
406 return -1;
407 }
408
409 _thread_loop--;
410 if (_thread_loop > 0)
411 return _thread_loop;
412
413 current_id = _thread_id;
414
415 eina_lock_take(&_thread_mutex);
416 _thread_id_update = _thread_id;
417 eina_condition_broadcast(&_thread_cond);
418 eina_lock_release(&_thread_mutex);
419
420 eina_lock_take(&_thread_feedback_mutex);
421 while (current_id == _thread_id && _thread_id != -1)
422 eina_condition_wait(&_thread_feedback_cond);
423 eina_lock_release(&_thread_feedback_mutex);
424
425 return 0;
426}