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
|
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)
|
2011-07-26 Carsten Haitzler (The Rasterman)
|
||||||
|
|
||||||
* Make ecore-evas give more errors on stderr when engines are
|
* Make ecore-evas give more errors on stderr when engines are
|
||||||
not found.
|
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 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 callback The callback to call in the main loop
|
||||||
* @param data The data to give to that call back
|
* @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
|
* in the thread, it is owned by the main loop and you callback should take
|
||||||
* care of freeing it if necessary.
|
* 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_Power Ecore_Event_Signal_Power; /**< Power signal event */
|
||||||
typedef struct _Ecore_Event_Signal_Realtime Ecore_Event_Signal_Realtime; /**< Realtime 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
|
* @typedef Ecore_Filter_Cb
|
||||||
* A callback used for filtering events from the main loop.
|
* 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;
|
typedef struct _Ecore_Safe_Call Ecore_Safe_Call;
|
||||||
struct _Ecore_Safe_Call
|
struct _Ecore_Safe_Call
|
||||||
{
|
{
|
||||||
Ecore_Cb cb;
|
union {
|
||||||
|
Ecore_Cb async;
|
||||||
|
Ecore_Data_Cb sync;
|
||||||
|
} cb;
|
||||||
void *data;
|
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 void _thread_callback(void *data, void *buffer, unsigned int nbyte);
|
||||||
static Eina_List *_thread_cb = NULL;
|
static Eina_List *_thread_cb = NULL;
|
||||||
static Ecore_Pipe *_thread_call = NULL;
|
static Ecore_Pipe *_thread_call = NULL;
|
||||||
|
@ -234,12 +244,14 @@ unlock:
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static int wakeup = 42;
|
||||||
|
|
||||||
EAPI void
|
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;
|
Ecore_Safe_Call *order;
|
||||||
int wakeup = 42;
|
|
||||||
Eina_Bool count;
|
if (!callback) return ;
|
||||||
|
|
||||||
if (eina_main_loop_is())
|
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));
|
order = malloc(sizeof (Ecore_Safe_Call));
|
||||||
if (!order) return ;
|
if (!order) return ;
|
||||||
|
|
||||||
order->cb = callback;
|
order->cb.async = callback;
|
||||||
order->data = data;
|
order->data = data;
|
||||||
|
order->sync = EINA_FALSE;
|
||||||
|
|
||||||
eina_lock_take(&_thread_safety);
|
_ecore_main_loop_thread_safe_call(order);
|
||||||
|
}
|
||||||
|
|
||||||
count = _thread_cb ? 0 : 1;
|
EAPI void *
|
||||||
_thread_cb = eina_list_append(_thread_cb, order);
|
ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback, void *data)
|
||||||
if (count) ecore_pipe_write(_thread_call, &wakeup, sizeof (int));
|
{
|
||||||
|
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
|
EAPI void
|
||||||
|
@ -484,6 +530,29 @@ _ecore_memory_statistic(__UNUSED__ void *data)
|
||||||
|
|
||||||
#endif
|
#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
|
static void
|
||||||
_thread_callback(void *data __UNUSED__,
|
_thread_callback(void *data __UNUSED__,
|
||||||
void *buffer __UNUSED__,
|
void *buffer __UNUSED__,
|
||||||
|
@ -499,7 +568,15 @@ _thread_callback(void *data __UNUSED__,
|
||||||
|
|
||||||
EINA_LIST_FREE(callback, call)
|
EINA_LIST_FREE(callback, call)
|
||||||
{
|
{
|
||||||
call->cb(call->data);
|
if (call->sync)
|
||||||
free(call);
|
{
|
||||||
|
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