aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2017-08-26 19:59:39 -0300
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2017-08-27 11:47:55 -0300
commit4d7661b1746dcb2ba5d146700de887ecbe2e462e (patch)
tree5ebc792a722e2a7796a993878595f1a7b2c7e7f1
parentexport efl_future_then() for Eina_Future syntax sugar. (diff)
downloadefl-devs/barbieri/future.tar.gz
Efl_Loop: add job, timeout and idle based on Eina_Future.devs/barbieri/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.c3
-rw-r--r--src/lib/ecore/ecore_main.c104
-rw-r--r--src/lib/ecore/ecore_private.h3
-rw-r--r--src/lib/ecore/efl_loop.eo25
-rw-r--r--src/tests/ecore/ecore_test_promise2.c64
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 3494280aa7..8cf0c74915 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 f71fa07c0e..315e67d4ce 100644
--- a/src/tests/ecore/ecore_test_promise2.c
+++ b/src/tests/ecore/ecore_test_promise2.c
@@ -411,6 +411,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;
@@ -834,6 +895,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);