From 4d15a0f50f8680de22ea6ced009d666e9ae6be3f Mon Sep 17 00:00:00 2001 From: Cedric Bail Date: Thu, 30 May 2013 15:42:56 +0900 Subject: [PATCH] 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. --- src/lib/evas/canvas/evas_async_events.c | 142 +++++++++++++++++++++++++++++++- src/lib/evas/include/evas_private.h | 3 + 2 files changed, 144 insertions(+), 1 deletion(-) 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 @@ #include "evas_private.h" typedef struct _Evas_Event_Async Evas_Event_Async; - struct _Evas_Event_Async { const void *target; @@ -21,6 +20,28 @@ struct _Evas_Event_Async Evas_Callback_Type type; }; +typedef struct _Evas_Safe_Call Evas_Safe_Call; +struct _Evas_Safe_Call +{ + Eina_Condition c; + Eina_Lock m; + + int current_id; +}; + +static Eina_Lock _thread_mutex; +static Eina_Condition _thread_cond; + +static Eina_Lock _thread_feedback_mutex; +static Eina_Condition _thread_feedback_cond; + +static int _thread_loop = 0; + +static Eina_Lock _thread_id_lock; +static int _thread_id = -1; +static int _thread_id_max = 0; +static int _thread_id_update = 0; + static int _fd_write = -1; static int _fd_read = -1; static pid_t _fd_pid = 0; @@ -81,6 +102,14 @@ evas_async_events_init(void) eina_lock_new(&async_lock); eina_inarray_step_set(&async_queue, sizeof (Eina_Inarray), sizeof (Evas_Event_Async), 16); + eina_lock_new(&_thread_mutex); + eina_condition_new(&_thread_cond, &_thread_mutex); + + eina_lock_new(&_thread_feedback_mutex); + eina_condition_new(&_thread_feedback_cond, &_thread_feedback_mutex); + + eina_lock_new(&_thread_id_lock); + return _init_evas_event; } @@ -90,6 +119,12 @@ evas_async_events_shutdown(void) _init_evas_event--; if (_init_evas_event > 0) return _init_evas_event; + eina_condition_free(&_thread_cond); + eina_lock_free(&_thread_mutex); + eina_condition_free(&_thread_feedback_cond); + eina_lock_free(&_thread_feedback_mutex); + eina_lock_free(&_thread_id_lock); + eina_lock_free(&async_lock); eina_inarray_flush(&async_queue); free(async_queue_cache); @@ -284,3 +319,108 @@ evas_async_events_put(const void *target, Evas_Callback_Type type, void *event_i return ret; } + +static void +_evas_thread_main_loop_lock(void *target EINA_UNUSED, + Evas_Callback_Type type EINA_UNUSED, + void *event_info) +{ + Evas_Safe_Call *call = event_info; + + eina_lock_take(&_thread_mutex); + + eina_lock_take(&call->m); + _thread_id = call->current_id; + eina_condition_broadcast(&call->c); + eina_lock_release(&call->m); + + while (_thread_id_update != _thread_id) + eina_condition_wait(&_thread_cond); + eina_lock_release(&_thread_mutex); + + eina_main_loop_define(); + + eina_lock_take(&_thread_feedback_mutex); + + _thread_id = -1; + + eina_condition_broadcast(&_thread_feedback_cond); + eina_lock_release(&_thread_feedback_mutex); + + eina_condition_free(&call->c); + eina_lock_free(&call->m); + free(call); +} + +EAPI int +evas_thread_main_loop_begin(void) +{ + Evas_Safe_Call *order; + + if (eina_main_loop_is()) + { + return ++_thread_loop; + } + + order = malloc(sizeof (Evas_Safe_Call)); + if (!order) return -1; + + eina_lock_take(&_thread_id_lock); + order->current_id = ++_thread_id_max; + if (order->current_id < 0) + { + _thread_id_max = 0; + order->current_id = ++_thread_id_max; + } + eina_lock_release(&_thread_id_lock); + + eina_lock_new(&order->m); + eina_condition_new(&order->c, &order->m); + + evas_async_events_put(NULL, 0, order, _evas_thread_main_loop_lock); + + eina_lock_take(&order->m); + while (order->current_id != _thread_id) + eina_condition_wait(&order->c); + eina_lock_release(&order->m); + + eina_main_loop_define(); + + _thread_loop = 1; + + return _thread_loop; +} + +EAPI int +evas_thread_main_loop_end(void) +{ + int current_id; + + if (_thread_loop == 0) + abort(); + + /* until we unlock the main loop, this thread has the main loop id */ + if (!eina_main_loop_is()) + { + ERR("Not in a locked thread !"); + return -1; + } + + _thread_loop--; + if (_thread_loop > 0) + return _thread_loop; + + current_id = _thread_id; + + eina_lock_take(&_thread_mutex); + _thread_id_update = _thread_id; + eina_condition_broadcast(&_thread_cond); + eina_lock_release(&_thread_mutex); + + eina_lock_take(&_thread_feedback_mutex); + while (current_id == _thread_id && _thread_id != -1) + eina_condition_wait(&_thread_feedback_cond); + eina_lock_release(&_thread_feedback_mutex); + + return 0; +} diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 9b0dc12..d05d19b 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1205,6 +1205,9 @@ int evas_async_events_init(void); int evas_async_events_shutdown(void); int evas_async_target_del(const void *target); +EAPI int evas_thread_main_loop_begin(void); +EAPI int evas_thread_main_loop_end(void); + void _evas_preload_thread_init(void); void _evas_preload_thread_shutdown(void); Evas_Preload_Pthread *evas_preload_thread_run(void (*func_heavy)(void *data), -- 2.7.4