diff options
author | Gustavo Sverzut Barbieri <barbieri@profusion.mobi> | 2017-08-26 19:59:39 -0300 |
---|---|---|
committer | Guilherme Iscaro <iscaro@profusion.mobi> | 2017-09-04 10:24:00 -0300 |
commit | 22cee38239912d87467844ded59589c9fed319d4 (patch) | |
tree | 178e559e7030a261dfaac3a2409af93be09c5219 | |
parent | 8e80d3d2dc162312070d043e622747b17d4e1763 (diff) | |
download | efl-22cee38239912d87467844ded59589c9fed319d4.tar.gz |
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.
-rw-r--r-- | src/lib/ecore/ecore_alloc.c | 3 | ||||
-rw-r--r-- | src/lib/ecore/ecore_main.c | 104 | ||||
-rw-r--r-- | src/lib/ecore/ecore_private.h | 3 | ||||
-rw-r--r-- | src/lib/ecore/efl_loop.eo | 25 | ||||
-rw-r--r-- | src/tests/ecore/ecore_test_promise2.c | 64 |
5 files changed, 199 insertions, 0 deletions
diff --git a/src/lib/ecore/ecore_alloc.c b/src/lib/ecore/ecore_alloc.c index bec66ef0d5..3196b82a2d 100644 --- a/src/lib/ecore/ecore_alloc.c +++ b/src/lib/ecore/ecore_alloc.c @@ -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 diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c index 0bb15e0c02..6819a05d7e 100644 --- a/src/lib/ecore/ecore_main.c +++ b/src/lib/ecore/ecore_main.c @@ -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); diff --git a/src/lib/ecore/ecore_private.h b/src/lib/ecore/ecore_private.h index 6437b41fb2..366c169943 100644 --- a/src/lib/ecore/ecore_private.h +++ b/src/lib/ecore/ecore_private.h @@ -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 diff --git a/src/lib/ecore/efl_loop.eo b/src/lib/ecore/efl_loop.eo index e34deb586f..a5610c20e2 100644 --- a/src/lib/ecore/efl_loop.eo +++ b/src/lib/ecore/efl_loop.eo @@ -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 { diff --git a/src/tests/ecore/ecore_test_promise2.c b/src/tests/ecore/ecore_test_promise2.c index ea8d0d272e..c23c5d1c74 100644 --- a/src/tests/ecore/ecore_test_promise2.c +++ b/src/tests/ecore/ecore_test_promise2.c @@ -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); |