From de7c8a6338e7545de75352677a166c3099e70d30 Mon Sep 17 00:00:00 2001 From: cedric Date: Thu, 28 Jul 2011 13:33:14 +0000 Subject: [PATCH] ecore: add ecore_main_loop_thread_safe_call. NOTE: that's for you mike. git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@61857 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- ChangeLog | 6 +++++- src/lib/ecore/Ecore.h | 16 ++++++++++++++++ src/lib/ecore/ecore.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 466e0de..2b69001 100644 --- a/ChangeLog +++ b/ChangeLog @@ -263,9 +263,13 @@ 2011-07-22 Mike Blumenkrantz * Added ecore_con_url_url_get - + 2011-07-26 Carsten Haitzler (The Rasterman) * Fix timer precision handling for grouping timer ticks so they actually do tick off together +2011-07-28 Cedric Bail + + * Add ecore_main_loop_thread_safe_call. + diff --git a/src/lib/ecore/Ecore.h b/src/lib/ecore/Ecore.h index 159aac6..e57bc17 100644 --- a/src/lib/ecore/Ecore.h +++ b/src/lib/ecore/Ecore.h @@ -737,6 +737,22 @@ extern "C" { EAPI void *ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler); /** + * @brief Call callback in the main loop. + * + * @param callback The callback to call in the main loop + * @param data The data to give to that call back + * + * For all call that need to happen in the main loop (most EFL functions do), + * this helper function provide the infrastructure needed to do it safely + * by avoind dead lock, race condition and properly wake up the main loop. + * + * Remember after that function call, you should never touch again the @p data + * in the thread, it is owned by the main loop and you callback should take + * care of freeing it if necessary. + */ + EAPI void ecore_main_loop_thread_safe_call(Ecore_Cb callback, void *data); + + /** * @} */ diff --git a/src/lib/ecore/ecore.c b/src/lib/ecore/ecore.c index c92c241..b7e0fbd 100644 --- a/src/lib/ecore/ecore.c +++ b/src/lib/ecore/ecore.c @@ -53,6 +53,17 @@ static int _ecore_init_count = 0; int _ecore_log_dom = -1; int _ecore_fps_debug = 0; +typedef struct _Ecore_Safe_Call Ecore_Safe_Call; +struct _Ecore_Safe_Call +{ + Ecore_Cb cb; + void *data; +}; + +static void _thread_callback(void *data, void *buffer, unsigned int nbyte); +static Ecore_Pipe *_thread_call = NULL; +static Eina_Lock _thread_safety; + /** OpenBSD does not define CODESET * FIXME ?? */ @@ -126,6 +137,9 @@ ecore_init(void) _ecore_job_init(); _ecore_time_init(); + eina_lock_new(&_thread_safety); + _thread_call = ecore_pipe_add(_thread_callback, NULL); + #if HAVE_MALLINFO if (getenv("ECORE_MEM_STAT")) { @@ -165,6 +179,9 @@ ecore_shutdown(void) if (--_ecore_init_count != 0) return _ecore_init_count; + ecore_pipe_del(_thread_call); + eina_lock_free(&_thread_safety); + if (_ecore_fps_debug) _ecore_fps_debug_shutdown(); _ecore_poller_shutdown(); _ecore_animator_shutdown(); @@ -203,6 +220,22 @@ ecore_shutdown(void) return _ecore_init_count; } +EAPI void +ecore_main_loop_thread_safe_call(Ecore_Cb callback, void *data) +{ + Ecore_Safe_Call *order; + + order = malloc(sizeof (Ecore_Safe_Call)); + if (!order) return ; + + order->cb = callback; + order->data = data; + + eina_lock_take(&_thread_safety); + ecore_pipe_write(_thread_call, &order, sizeof (Ecore_Safe_Call*)); + eina_lock_release(&_thread_safety); +} + /** * @} */ @@ -428,3 +461,18 @@ _ecore_memory_statistic(__UNUSED__ void *data) } #endif + +static void +_thread_callback(void *data __UNUSED__, void *buffer, unsigned int nbyte) +{ + Ecore_Safe_Call *call = buffer; + + while (nbyte >= sizeof (Ecore_Safe_Call*)) + { + call->cb(call->data); + free(call); + + call++; + nbyte -= sizeof (Ecore_Safe_Call*); + } +} -- 2.7.4