forked from enlightenment/efl
ecore: add ecore_thread_wait and necessary infrastructure.
This enable the possibility to block the main loop until a specific thread is done. It may trigger still process ending of other thread during that function call, but not any other type of event (timer, animator, idler, ... are all ignored).
This commit is contained in:
parent
2cae004592
commit
e5ddfb4b2b
|
@ -385,6 +385,19 @@ EAPI void ecore_main_loop_thread_safe_call_async(Ecore_Cb callback, void *data);
|
|||
*/
|
||||
EAPI void *ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback, void *data);
|
||||
|
||||
/**
|
||||
* @brief Wait for the next thread call in the main loop.
|
||||
* @since 1.13.0
|
||||
*
|
||||
* @param wait How long to wait for this callback to be called
|
||||
*
|
||||
* Note: This function should only be called in the main loop
|
||||
* and will actually block the main loop until either a call
|
||||
* is triggered from a thread or the time specified by wait has
|
||||
* passed.
|
||||
*/
|
||||
EAPI void ecore_main_loop_thread_safe_call_wait(double wait);
|
||||
|
||||
/**
|
||||
* @brief This function suspend the main loop in a know state
|
||||
* @since 1.1.0
|
||||
|
@ -1818,6 +1831,15 @@ EAPI Ecore_Thread *ecore_thread_feedback_run(Ecore_Thread_Cb func_heavy, Ecore_T
|
|||
*/
|
||||
EAPI Eina_Bool ecore_thread_cancel(Ecore_Thread *thread);
|
||||
|
||||
/**
|
||||
* @brief Block the main loop until the thread execution is over.
|
||||
*
|
||||
* @param thread The thread to wait on.
|
||||
* @param wait Maximum time to wait before exiting anyway.
|
||||
* @return EINA_TRUE if the thread execution is over.
|
||||
*/
|
||||
EAPI Eina_Bool ecore_thread_wait(Ecore_Thread *thread, double wait);
|
||||
|
||||
/**
|
||||
* Checks if a thread is pending cancellation
|
||||
*
|
||||
|
|
|
@ -583,6 +583,12 @@ ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback,
|
|||
return ret;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_main_loop_thread_safe_call_wait(double wait)
|
||||
{
|
||||
ecore_pipe_wait(_thread_call, 1, wait);
|
||||
}
|
||||
|
||||
EAPI int
|
||||
ecore_thread_main_loop_begin(void)
|
||||
{
|
||||
|
|
|
@ -733,6 +733,79 @@ ecore_thread_cancel(Ecore_Thread *thread)
|
|||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
typedef struct _Ecore_Thread_Waiter Ecore_Thread_Waiter;
|
||||
struct _Ecore_Thread_Waiter
|
||||
{
|
||||
Ecore_Thread_Cb func_cancel;
|
||||
Ecore_Thread_Cb func_end;
|
||||
const void *data;
|
||||
};
|
||||
|
||||
static void
|
||||
_ecore_thread_wait_reset(Ecore_Thread_Waiter *waiter,
|
||||
Ecore_Pthread_Worker *worker)
|
||||
{
|
||||
worker->data = waiter->data;
|
||||
worker->func_cancel = waiter->func_cancel;
|
||||
worker->func_end = waiter->func_end;
|
||||
// The waiter will be checked by _wait, NULL meaning it is done
|
||||
waiter->func_end = NULL;
|
||||
waiter->func_cancel = NULL;
|
||||
waiter->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_thread_wait_cancel(void *data, Ecore_Thread *thread)
|
||||
{
|
||||
Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker*) thread;
|
||||
Ecore_Thread_Waiter *waiter = data;
|
||||
|
||||
waiter->func_cancel((void*) waiter->data, thread);
|
||||
_ecore_thread_wait_reset(waiter, worker);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_thread_wait_end(void *data, Ecore_Thread *thread)
|
||||
{
|
||||
Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker*) thread;
|
||||
Ecore_Thread_Waiter *waiter = data;
|
||||
|
||||
waiter->func_end((void*) waiter->data, thread);
|
||||
_ecore_thread_wait_reset(waiter, worker);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_thread_wait(Ecore_Thread *thread, double wait)
|
||||
{
|
||||
Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker*) thread;
|
||||
Ecore_Thread_Waiter waiter;
|
||||
|
||||
if (!thread) return ;
|
||||
|
||||
waiter.data = worker->data;
|
||||
waiter.func_end = worker->func_end;
|
||||
waiter.func_cancel = worker->func_cancel;
|
||||
// Now trick the thread to call the wrapper function
|
||||
worker->data = &waiter;
|
||||
worker->func_cancel = _ecore_thread_wait_cancel;
|
||||
worker->func_end = _ecore_thread_wait_end;
|
||||
|
||||
while (waiter.data)
|
||||
{
|
||||
double start, end;
|
||||
|
||||
start = ecore_time_get();
|
||||
ecore_main_loop_thread_safe_call_wait(wait);
|
||||
end = ecore_time_get();
|
||||
|
||||
wait -= end - start;
|
||||
|
||||
if (wait <= 0) break;
|
||||
}
|
||||
|
||||
return (waiter.data == NULL) ? EINA_TRUE : EINA_FALSE;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_thread_check(Ecore_Thread *thread)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue