forked from enlightenment/efl
ecore: add clean thread safety mecanism.
SVN revision: 62531
This commit is contained in:
parent
1ec7bacc52
commit
7b047a49d7
|
@ -444,6 +444,34 @@ extern "C" {
|
|||
*/
|
||||
EAPI void *ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback, void *data);
|
||||
|
||||
/**
|
||||
* @brief This function suspend the main loop in a know state
|
||||
* @since 1.1.0
|
||||
*
|
||||
* @result EINA_TRUE if the main loop was suspended correcly.
|
||||
*
|
||||
* This function suspend the main loop in a know state, this let you
|
||||
* use any EFL call you want after it return. Be carefull, the main loop
|
||||
* is blocked until you call ecore_thread_main_loop_end(). This is
|
||||
* the only sane way to achieve pseudo thread safety.
|
||||
*
|
||||
* Notice that until the main loop is blocked, the thread is blocked
|
||||
* and their is noway around that.
|
||||
*
|
||||
* We still advise you, when possible, to use ecore_main_loop_thread_safe_call_async()
|
||||
* as it will not block the thread nor the main loop.
|
||||
*/
|
||||
EAPI Eina_Bool ecore_thread_main_loop_begin(void);
|
||||
|
||||
/**
|
||||
* @brief Unlock the main loop.
|
||||
* @since 1.1.0
|
||||
*
|
||||
* After a call to ecore_thread_main_loop_begin(), you need to absolutly
|
||||
* call ecore_thread_main_loop_end(), or you application will stay frozen.
|
||||
*/
|
||||
EAPI void ecore_thread_main_loop_end(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -66,6 +66,7 @@ struct _Ecore_Safe_Call
|
|||
Eina_Condition c;
|
||||
|
||||
Eina_Bool sync : 1;
|
||||
Eina_Bool suspend : 1;
|
||||
};
|
||||
|
||||
static void _ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order);
|
||||
|
@ -74,6 +75,11 @@ static void _thread_callback(void *data, void *buffer, unsigned int nbyte);
|
|||
static Eina_List *_thread_cb = NULL;
|
||||
static Ecore_Pipe *_thread_call = NULL;
|
||||
static Eina_Lock _thread_safety;
|
||||
|
||||
static Eina_Bool _thread_loop = EINA_FALSE;
|
||||
static Eina_Lock _thread_mutex;
|
||||
static Eina_Condition _thread_cond;
|
||||
|
||||
Eina_Lock _ecore_main_loop_lock;
|
||||
int _ecore_main_lock_count;
|
||||
|
||||
|
@ -151,9 +157,12 @@ ecore_init(void)
|
|||
_ecore_time_init();
|
||||
|
||||
eina_lock_new(&_thread_safety);
|
||||
eina_lock_new(&_ecore_main_loop_lock);
|
||||
eina_lock_new(&_thread_mutex);
|
||||
eina_condition_new(&_thread_cond, &_thread_mutex);
|
||||
_thread_call = ecore_pipe_add(_thread_callback, NULL);
|
||||
|
||||
eina_lock_new(&_ecore_main_loop_lock);
|
||||
|
||||
#if HAVE_MALLINFO
|
||||
if (getenv("ECORE_MEM_STAT"))
|
||||
{
|
||||
|
@ -265,6 +274,7 @@ ecore_main_loop_thread_safe_call_async(Ecore_Cb callback, void *data)
|
|||
order->cb.async = callback;
|
||||
order->data = data;
|
||||
order->sync = EINA_FALSE;
|
||||
order->suspend = EINA_FALSE;
|
||||
|
||||
_ecore_main_loop_thread_safe_call(order);
|
||||
}
|
||||
|
@ -290,6 +300,7 @@ ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback, void *data)
|
|||
eina_lock_new(&order->m);
|
||||
eina_condition_new(&order->c, &order->m);
|
||||
order->sync = EINA_TRUE;
|
||||
order->suspend = EINA_FALSE;
|
||||
|
||||
_ecore_main_loop_thread_safe_call(order);
|
||||
|
||||
|
@ -308,6 +319,44 @@ ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback, void *data)
|
|||
return ret;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_thread_main_loop_begin(void)
|
||||
{
|
||||
Ecore_Safe_Call *order;
|
||||
|
||||
if (eina_main_loop_is())
|
||||
return EINA_FALSE;
|
||||
|
||||
order = malloc(sizeof (Ecore_Safe_Call));
|
||||
if (!order) return EINA_FALSE;
|
||||
|
||||
eina_lock_new(&order->m);
|
||||
eina_condition_new(&order->c, &order->m);
|
||||
order->suspend = EINA_TRUE;
|
||||
|
||||
_ecore_main_loop_thread_safe_call(order);
|
||||
|
||||
eina_lock_take(&order->m);
|
||||
eina_condition_wait(&order->c);
|
||||
eina_lock_release(&order->m);
|
||||
|
||||
eina_main_loop_define();
|
||||
|
||||
_thread_loop = EINA_TRUE;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_thread_main_loop_end(void)
|
||||
{
|
||||
if (!_thread_loop) return ;
|
||||
/* until we unlock the main loop, this thread has the main loop id */
|
||||
if (!eina_main_loop_is()) return ;
|
||||
|
||||
eina_condition_broadcast(&_thread_cond);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_print_warning(const char *function, const char *sparam)
|
||||
{
|
||||
|
@ -568,7 +617,20 @@ _thread_callback(void *data __UNUSED__,
|
|||
|
||||
EINA_LIST_FREE(callback, call)
|
||||
{
|
||||
if (call->sync)
|
||||
if (call->suspend)
|
||||
{
|
||||
eina_condition_broadcast(&call->c);
|
||||
|
||||
eina_lock_take(&_thread_mutex);
|
||||
eina_condition_wait(&_thread_cond);
|
||||
eina_lock_release(&_thread_mutex);
|
||||
|
||||
eina_main_loop_define();
|
||||
|
||||
_thread_safe_cleanup(call);
|
||||
free(call);
|
||||
}
|
||||
else if (call->sync)
|
||||
{
|
||||
call->data = call->cb.sync(call->data);
|
||||
eina_condition_broadcast(&call->c);
|
||||
|
|
Loading…
Reference in New Issue