From 8d50990a2709b1745d40ee368ffa48cba7f15faa Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Wed, 4 May 2016 14:44:56 -0700 Subject: [PATCH] ecore: add a timeout promise. --- src/lib/ecore/ecore_main.c | 107 ++++++++++++++++++++++++++++++------- src/lib/ecore/efl_loop.eo | 12 ++++- 2 files changed, 97 insertions(+), 22 deletions(-) diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c index 71ce95b2ea..93f1d1cf60 100644 --- a/src/lib/ecore/ecore_main.c +++ b/src/lib/ecore/ecore_main.c @@ -2800,54 +2800,121 @@ _efl_loop_eo_base_constructor(Eo *obj, Efl_Loop_Data *pd) return obj; } -typedef struct _Efl_Internal_Job Efl_Internal_Job; -struct _Efl_Internal_Job +typedef struct _Efl_Internal_Promise Efl_Internal_Promise; +struct _Efl_Internal_Promise { - Ecore_Job *job; + union { + Ecore_Job *job; + Efl_Timer *timer; + } u; Eina_Promise_Owner *promise; const void *data; + + Eina_Bool job_is : 1; }; static void _efl_loop_job_cb(void *data) { - Efl_Internal_Job *j = data; + Efl_Internal_Promise *j = data; eina_promise_owner_value_set(j->promise, &j->data, NULL); free(j); } +static Eina_Bool +_efl_loop_timeout_cb(void *data, const Eo_Event *event EINA_UNUSED) +{ + Efl_Internal_Promise *t = data; + + eina_promise_owner_value_set(t->promise, &t->data, NULL); + + eo_del(t->u.timer); + + return EO_CALLBACK_CONTINUE; +} + +static void +_efl_loop_internal_cancel(Efl_Internal_Promise *p) +{ + eina_promise_owner_error_set(p->promise, _promise_canceled); + free(p); +} + static void _efl_loop_job_cancel(void* data, Eina_Promise_Owner* promise EINA_UNUSED) { - Efl_Internal_Job *j = data; + Efl_Internal_Promise *j = data; - eina_promise_owner_error_set(j->promise, _promise_canceled); - ecore_job_del(j->job); - free(j); + if (j->job_is) + ecore_job_del(j->u.job); + else + eo_del(j->u.timer); + _efl_loop_internal_cancel(j); +} + +static Efl_Internal_Promise * +_efl_internal_promise_new(Eina_Promise_Owner* promise, const void *data) +{ + Efl_Internal_Promise *p; + + p = calloc(1, sizeof (Efl_Internal_Promise)); + if (!p) return NULL; + + eina_promise_owner_default_cancel_cb_add(promise, &_efl_loop_job_cancel, p, NULL); + p->promise = promise; + p->data = data; + + return p; } static void _efl_loop_job(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED, Eina_Promise_Owner *promise, const void *data) { - Efl_Internal_Job *j; + Efl_Internal_Promise *j; - j = calloc(1, sizeof (Efl_Internal_Job)); - if (!j) goto on_error; + j = _efl_internal_promise_new(promise, data); + if (!j) return ; - eina_promise_owner_default_cancel_cb_add(promise, &_efl_loop_job_cancel, j, NULL); - j->promise = promise; - j->data = data; - j->job = ecore_job_add(_efl_loop_job_cb, j); - if (!j->job) goto on_error; + j->job_is = EINA_TRUE; + j->u.job = ecore_job_add(_efl_loop_job_cb, j); - return ; + if (j->u.job) return ; - on_error: - eina_promise_owner_error_set(promise, _promise_canceled); - free(j); + _efl_loop_internal_cancel(j); +} + +/* This event will be triggered when the main loop is destroyed and destroy its timers along */ +static Eina_Bool +_efl_loop_timeout_force_cancel_cb(void *data, const Eo_Event *event EINA_UNUSED) +{ + _efl_loop_internal_cancel(data); + + return EO_CALLBACK_CONTINUE; +} + +EO_CALLBACKS_ARRAY_DEFINE(timeout, + { EFL_TIMER_EVENT_TICK, _efl_loop_timeout_cb }, + { EO_BASE_EVENT_DEL, _efl_loop_timeout_force_cancel_cb }); + +static void +_efl_loop_timeout(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, Eina_Promise_Owner *promise, double time, const void *data) +{ + Efl_Internal_Promise *t; + + t = _efl_internal_promise_new(promise, data); + if (!t) return ; + + t->job_is = EINA_FALSE; + t->u.timer = eo_add(EFL_TIMER_CLASS, obj, + efl_timer_interval_set(eo_self, time), + eo_event_callback_array_add(eo_self, timeout(), t)); + + if (t->u.timer) return ; + + _efl_loop_internal_cancel(t); } #include "efl_loop.eo.c" diff --git a/src/lib/ecore/efl_loop.eo b/src/lib/ecore/efl_loop.eo index 2896b4008d..283d583e00 100644 --- a/src/lib/ecore/efl_loop.eo +++ b/src/lib/ecore/efl_loop.eo @@ -34,8 +34,16 @@ class Efl.Loop (Eo.Base) job { [[Will execute that promise in the near future.]] params { - @inout promise: promise*; - @in data: const(void)* @optional; + @inout promise: promise*; [[The promise that will be triggered.]] + @in data: const(void)* @optional; [[The data to be given when the promise is done.]] + } + } + timeout { + [[Will trigger this promise when the specified timeout occur.]] + params { + @inout promise: promise*; [[The promise that will be triggered.]] + @in time: double; [[The time from now in second that the main loop will wait before triggering it.]] + @in data: const(void)* @optional; [[The data to be given when the promise is done.]] } } }