Efl_Loop: add job, timeout and idle based on Eina_Future.

Since some clash with old version, then add Eina_FutureXXX to their
name, later we'll sed.
This commit is contained in:
Gustavo Sverzut Barbieri 2017-08-26 19:59:39 -03:00 committed by Guilherme Iscaro
parent 8e80d3d2dc
commit 22cee38239
5 changed files with 199 additions and 0 deletions

View File

@ -44,6 +44,7 @@ GENERIC_ALLOC_FREE(Ecore_Event, ecore_event);
//GENERIC_ALLOC_FREE(Ecore_Poller, ecore_poller);
GENERIC_ALLOC_FREE(Ecore_Pipe, ecore_pipe);
GENERIC_ALLOC_FREE(Ecore_Fd_Handler, ecore_fd_handler);
GENERIC_ALLOC_FREE(Efl_Loop_Promise_Simple_Data, efl_loop_promise_simple_data);
#ifdef _WIN32
GENERIC_ALLOC_FREE(Ecore_Win32_Handler, ecore_win32_handler);
#endif
@ -61,6 +62,7 @@ static Ecore_Mempool *mempool_array[] = {
// &ecore_poller_mp,
&ecore_pipe_mp,
&ecore_fd_handler_mp,
&efl_loop_promise_simple_data_mp,
#ifdef _WIN32
&ecore_win32_handler_mp
#endif
@ -87,6 +89,7 @@ ecore_mempool_init(void)
// MP_SIZE_INIT(Ecore_Poller, ecore_poller);
MP_SIZE_INIT(Ecore_Pipe, ecore_pipe);
MP_SIZE_INIT(Ecore_Fd_Handler, ecore_fd_handler);
MP_SIZE_INIT(Efl_Loop_Promise_Simple_Data, efl_loop_promise_simple_data);
#ifdef _WIN32
MP_SIZE_INIT(Ecore_Win32_Handler, ecore_win32_handler);
#endif

View File

@ -233,6 +233,15 @@ struct _Ecore_Fd_Handler
};
GENERIC_ALLOC_SIZE_DECLARE(Ecore_Fd_Handler);
typedef struct _Efl_Loop_Promise_Simple_Data {
union {
Ecore_Timer *timer;
Ecore_Idler *idler;
};
Eina_Promise *promise;
} Efl_Loop_Promise_Simple_Data;
GENERIC_ALLOC_SIZE_DECLARE(Efl_Loop_Promise_Simple_Data);
#ifdef _WIN32
struct _Ecore_Win32_Handler
{
@ -3112,6 +3121,101 @@ EFL_CALLBACKS_ARRAY_DEFINE(timeout,
{ EFL_LOOP_TIMER_EVENT_TICK, _efl_loop_timeout_cb },
{ EFL_EVENT_DEL, _efl_loop_timeout_force_cancel_cb });
static Eina_Future *
_efl_loop_Eina_FutureXXX_job(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
{
// NOTE: Eolian should do efl_future_then() to bind future to object.
return efl_future_Eina_FutureXXX_then(obj,
eina_future_resolved(efl_loop_future_scheduler_get(obj),
EINA_VALUE_EMPTY));
}
static void
_efl_loop_Eina_FutureXXX_idle_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED)
{
Efl_Loop_Promise_Simple_Data *d = data;
ecore_idler_del(d->idler);
efl_loop_promise_simple_data_mp_free(d);
}
static Eina_Bool
_efl_loop_Eina_FutureXXX_idle_done(void *data)
{
Efl_Loop_Promise_Simple_Data *d = data;
eina_promise_resolve(d->promise, EINA_VALUE_EMPTY);
efl_loop_promise_simple_data_mp_free(d);
return EINA_FALSE;
}
static Eina_Future *
_efl_loop_Eina_FutureXXX_idle(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
{
Efl_Loop_Promise_Simple_Data *d;
Eina_Promise *p;
d = efl_loop_promise_simple_data_calloc(1);
EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
d->idler = ecore_idler_add(_efl_loop_Eina_FutureXXX_idle_done, d);
EINA_SAFETY_ON_NULL_GOTO(d->idler, idler_error);
p = eina_promise_new(efl_loop_future_scheduler_get(obj),
_efl_loop_Eina_FutureXXX_idle_cancel, d);
// d is dead if p is NULL
EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL);
d->promise = p;
// NOTE: Eolian should do efl_future_then() to bind future to object.
return efl_future_Eina_FutureXXX_then(obj, eina_future_new(p));
idler_error:
efl_loop_promise_simple_data_mp_free(d);
return NULL;
}
static void
_efl_loop_Eina_FutureXXX_timeout_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED)
{
Efl_Loop_Promise_Simple_Data *d = data;
ecore_timer_del(d->timer);
efl_loop_promise_simple_data_mp_free(d);
}
static Eina_Bool
_efl_loop_Eina_FutureXXX_timeout_done(void *data)
{
Efl_Loop_Promise_Simple_Data *d = data;
eina_promise_resolve(d->promise, EINA_VALUE_EMPTY);
efl_loop_promise_simple_data_mp_free(d);
return EINA_FALSE;
}
static Eina_Future *
_efl_loop_Eina_FutureXXX_timeout(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, double time)
{
Efl_Loop_Promise_Simple_Data *d;
Eina_Promise *p;
d = efl_loop_promise_simple_data_calloc(1);
EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
d->timer = ecore_timer_add(time, _efl_loop_Eina_FutureXXX_timeout_done, d);
EINA_SAFETY_ON_NULL_GOTO(d->timer, timer_error);
p = eina_promise_new(efl_loop_future_scheduler_get(obj),
_efl_loop_Eina_FutureXXX_timeout_cancel, d);
// d is dead if p is NULL
EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL);
d->promise = p;
// NOTE: Eolian should do efl_future_then() to bind future to object.
return efl_future_Eina_FutureXXX_then(obj, eina_future_new(p));
timer_error:
efl_loop_promise_simple_data_mp_free(d);
return NULL;
}
/* This event will be triggered when the main loop is destroyed and destroy its timers along */
static void _efl_loop_internal_cancel(Efl_Internal_Promise *p);

View File

@ -81,6 +81,8 @@ extern int _ecore_log_dom;
typedef struct _Ecore_Factorized_Idle Ecore_Factorized_Idle;
typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data;
typedef struct _Efl_Loop_Data Efl_Loop_Data;
struct _Efl_Loop_Data
{
@ -371,6 +373,7 @@ GENERIC_ALLOC_FREE_HEADER(Ecore_Event, ecore_event);
//GENERIC_ALLOC_FREE_HEADER(Ecore_Poller, ecore_poller);
GENERIC_ALLOC_FREE_HEADER(Ecore_Pipe, ecore_pipe);
GENERIC_ALLOC_FREE_HEADER(Ecore_Fd_Handler, ecore_fd_handler);
GENERIC_ALLOC_FREE_HEADER(Efl_Loop_Promise_Simple_Data, efl_loop_promise_simple_data);
#ifdef _WIN32
GENERIC_ALLOC_FREE_HEADER(Ecore_Win32_Handler, ecore_win32_handler);
#endif

View File

@ -82,6 +82,31 @@ class Efl.Loop (Efl.Object)
scheduler: ptr(Eina.Future.Scheduler); [[The scheduler.]]
}
}
Eina_FutureXXX_job {
[[A future promise that will be resolved from a clean main
loop context as soon as possible.
This has higher priority, for low priority use
@.Eina_FutureXXX_idle
]]
return: own(ptr(Eina.Future)) /* TODO: future<void> */; [[The future handle.]]
}
Eina_FutureXXX_idle {
[[A future promise that will be resolved from a clean main
loop context as soon as the main loop is idle.
This is a low priority version of @.Eina_FutureXXX_job
]]
return: own(ptr(Eina.Future)) /* TODO: future<void> */; [[The future handle.]]
}
Eina_FutureXXX_timeout {
[[A future promise that will be resolved from a clean main
loop context after $time seconds.]]
params {
@in time: double; [[The time from now in second that the main loop will wait before triggering it.]]
}
return: own(ptr(Eina.Future)) /* future<void> */; [[The future handle.]]
}
job {
[[Will execute that promise in the near future.]]
params {

View File

@ -472,6 +472,67 @@ _race_end_cb(void *data, const Eina_Value v, const Eina_Future *dead EINA_UNUSED
return v;
}
static Eina_Value
_promise_empty_done(void *data, const Eina_Value value, const Eina_Future *dead_future EINA_UNUSED)
{
Eina_Bool *pdone = data;
if (!value.type) *pdone = EINA_TRUE;
ecore_main_loop_quit();
return value;
}
START_TEST(efl_test_timeout)
{
Eina_Future *f;
Eina_Bool done = EINA_FALSE;
fail_if(!ecore_init());
f = eina_future_then(efl_loop_Eina_FutureXXX_timeout(ecore_main_loop_get(), 0.0001),
_promise_empty_done, &done);
fail_if(!f);
ecore_main_loop_begin();
ecore_shutdown();
fail_unless(done);
}
END_TEST
START_TEST(efl_test_job)
{
Eina_Future *f;
Eina_Bool done = EINA_FALSE;
fail_if(!ecore_init());
f = eina_future_then(efl_loop_Eina_FutureXXX_job(ecore_main_loop_get()),
_promise_empty_done, &done);
fail_if(!f);
ecore_main_loop_begin();
ecore_shutdown();
fail_unless(done);
}
END_TEST
START_TEST(efl_test_idle)
{
Eina_Future *f;
Eina_Bool done = EINA_FALSE;
fail_if(!ecore_init());
f = eina_future_then(efl_loop_Eina_FutureXXX_idle(ecore_main_loop_get()),
_promise_empty_done, &done);
fail_if(!f);
ecore_main_loop_begin();
ecore_shutdown();
fail_unless(done);
}
END_TEST
START_TEST(efl_test_promise_future_success)
{
Eina_Future *f;
@ -1258,6 +1319,9 @@ END_TEST
void ecore_test_ecore_promise2(TCase *tc)
{
tcase_add_test(tc, efl_test_timeout);
tcase_add_test(tc, efl_test_job);
tcase_add_test(tc, efl_test_idle);
tcase_add_test(tc, efl_test_promise_future_success);
tcase_add_test(tc, efl_test_promise_future_failure);
tcase_add_test(tc, efl_test_promise_future_chain_no_error);