forked from enlightenment/efl
ecore: add ecore_main_loop_thread_safe_call_sync and rename ecore_main_loop_thread_safe_call.
SVN revision: 62513
This commit is contained in:
parent
bf958ebbd7
commit
1ca5e18738
|
@ -271,10 +271,13 @@
|
|||
|
||||
2011-07-28 Cedric Bail
|
||||
|
||||
* Add ecore_main_loop_thread_safe_call.
|
||||
* Add ecore_main_loop_thread_safe_call_async.
|
||||
|
||||
2011-07-26 Carsten Haitzler (The Rasterman)
|
||||
|
||||
* Make ecore-evas give more errors on stderr when engines are
|
||||
not found.
|
||||
|
||||
2011-08-16 Cedric Bail
|
||||
|
||||
* Add ecore_main_loop_thread_safe_call_sync.
|
||||
|
|
|
@ -404,8 +404,15 @@ extern "C" {
|
|||
*/
|
||||
typedef void (*Ecore_Cb) (void *data);
|
||||
|
||||
/**
|
||||
* @typedef Ecore_Data_Cb Ecore_Data_Cb
|
||||
* A callback which is used to return data to the main function
|
||||
*/
|
||||
typedef void *(*Ecore_Data_Cb) (void *data);
|
||||
|
||||
/**
|
||||
* @brief Call callback in the main loop.
|
||||
* @brief Call callback asynchronously in the main loop.
|
||||
* @since 1.1.0
|
||||
*
|
||||
* @param callback The callback to call in the main loop
|
||||
* @param data The data to give to that call back
|
||||
|
@ -418,7 +425,24 @@ extern "C" {
|
|||
* 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);
|
||||
EAPI void ecore_main_loop_thread_safe_call_async(Ecore_Cb callback, void *data);
|
||||
|
||||
/**
|
||||
* @brief Call callback synchronously in the main loop.
|
||||
* @since 1.1.0
|
||||
*
|
||||
* @param callback The callback to call in the main loop
|
||||
* @param data The data to give to that call back
|
||||
* @return the value returned by the callback in the main loop
|
||||
*
|
||||
* 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 this function will block until the callback is executed in the
|
||||
* main loop. It can take time and you have no guaranty about the timeline.
|
||||
*/
|
||||
EAPI void *ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback, void *data);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -483,12 +507,6 @@ extern "C" {
|
|||
typedef struct _Ecore_Event_Signal_Power Ecore_Event_Signal_Power; /**< Power signal event */
|
||||
typedef struct _Ecore_Event_Signal_Realtime Ecore_Event_Signal_Realtime; /**< Realtime signal event */
|
||||
|
||||
/**
|
||||
* @typedef Ecore_Data_Cb Ecore_Data_Cb
|
||||
* A callback which is used to return data to the main function
|
||||
*/
|
||||
typedef void *(*Ecore_Data_Cb) (void *data);
|
||||
|
||||
/**
|
||||
* @typedef Ecore_Filter_Cb
|
||||
* A callback used for filtering events from the main loop.
|
||||
|
|
|
@ -56,10 +56,20 @@ int _ecore_fps_debug = 0;
|
|||
typedef struct _Ecore_Safe_Call Ecore_Safe_Call;
|
||||
struct _Ecore_Safe_Call
|
||||
{
|
||||
Ecore_Cb cb;
|
||||
union {
|
||||
Ecore_Cb async;
|
||||
Ecore_Data_Cb sync;
|
||||
} cb;
|
||||
void *data;
|
||||
|
||||
Eina_Lock m;
|
||||
Eina_Condition c;
|
||||
|
||||
Eina_Bool sync : 1;
|
||||
};
|
||||
|
||||
static void _ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order);
|
||||
static void _thread_safe_cleanup(void *data);
|
||||
static void _thread_callback(void *data, void *buffer, unsigned int nbyte);
|
||||
static Eina_List *_thread_cb = NULL;
|
||||
static Ecore_Pipe *_thread_call = NULL;
|
||||
|
@ -234,12 +244,14 @@ unlock:
|
|||
* @}
|
||||
*/
|
||||
|
||||
static int wakeup = 42;
|
||||
|
||||
EAPI void
|
||||
ecore_main_loop_thread_safe_call(Ecore_Cb callback, void *data)
|
||||
ecore_main_loop_thread_safe_call_async(Ecore_Cb callback, void *data)
|
||||
{
|
||||
Ecore_Safe_Call *order;
|
||||
int wakeup = 42;
|
||||
Eina_Bool count;
|
||||
|
||||
if (!callback) return ;
|
||||
|
||||
if (eina_main_loop_is())
|
||||
{
|
||||
|
@ -250,16 +262,50 @@ ecore_main_loop_thread_safe_call(Ecore_Cb callback, void *data)
|
|||
order = malloc(sizeof (Ecore_Safe_Call));
|
||||
if (!order) return ;
|
||||
|
||||
order->cb = callback;
|
||||
order->cb.async = callback;
|
||||
order->data = data;
|
||||
order->sync = EINA_FALSE;
|
||||
|
||||
eina_lock_take(&_thread_safety);
|
||||
_ecore_main_loop_thread_safe_call(order);
|
||||
}
|
||||
|
||||
count = _thread_cb ? 0 : 1;
|
||||
_thread_cb = eina_list_append(_thread_cb, order);
|
||||
if (count) ecore_pipe_write(_thread_call, &wakeup, sizeof (int));
|
||||
EAPI void *
|
||||
ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback, void *data)
|
||||
{
|
||||
Ecore_Safe_Call *order;
|
||||
void *ret;
|
||||
|
||||
eina_lock_release(&_thread_safety);
|
||||
if (!callback) return NULL;
|
||||
|
||||
if (eina_main_loop_is())
|
||||
{
|
||||
return callback(data);
|
||||
}
|
||||
|
||||
order = malloc(sizeof (Ecore_Safe_Call));
|
||||
if (!order) return NULL;
|
||||
|
||||
order->cb.sync = callback;
|
||||
order->data = data;
|
||||
eina_lock_new(&order->m);
|
||||
eina_condition_new(&order->c, &order->m);
|
||||
order->sync = EINA_TRUE;
|
||||
|
||||
_ecore_main_loop_thread_safe_call(order);
|
||||
|
||||
eina_lock_take(&order->m);
|
||||
eina_condition_wait(&order->c);
|
||||
eina_lock_release(&order->m);
|
||||
|
||||
ret = order->data;
|
||||
|
||||
order->sync = EINA_FALSE;
|
||||
order->cb.async = _thread_safe_cleanup;
|
||||
order->data = order;
|
||||
|
||||
_ecore_main_loop_thread_safe_call(order);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
|
@ -484,6 +530,29 @@ _ecore_memory_statistic(__UNUSED__ void *data)
|
|||
|
||||
#endif
|
||||
|
||||
static void
|
||||
_ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order)
|
||||
{
|
||||
Eina_Bool count;
|
||||
|
||||
eina_lock_take(&_thread_safety);
|
||||
|
||||
count = _thread_cb ? 0 : 1;
|
||||
_thread_cb = eina_list_append(_thread_cb, order);
|
||||
if (count) ecore_pipe_write(_thread_call, &wakeup, sizeof (int));
|
||||
|
||||
eina_lock_release(&_thread_safety);
|
||||
}
|
||||
|
||||
static void
|
||||
_thread_safe_cleanup(void *data)
|
||||
{
|
||||
Ecore_Safe_Call *call = data;
|
||||
|
||||
eina_condition_free(&call->c);
|
||||
eina_lock_free(&call->m);
|
||||
}
|
||||
|
||||
static void
|
||||
_thread_callback(void *data __UNUSED__,
|
||||
void *buffer __UNUSED__,
|
||||
|
@ -499,7 +568,15 @@ _thread_callback(void *data __UNUSED__,
|
|||
|
||||
EINA_LIST_FREE(callback, call)
|
||||
{
|
||||
call->cb(call->data);
|
||||
free(call);
|
||||
if (call->sync)
|
||||
{
|
||||
call->data = call->cb.sync(call->data);
|
||||
eina_condition_broadcast(&call->c);
|
||||
}
|
||||
else
|
||||
{
|
||||
call->cb.async(call->data);
|
||||
free(call);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue