From ca1762be21f3913deedb094fe4186d1af8136632 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Fri, 16 Dec 2016 11:26:46 -0800 Subject: [PATCH] ecore: delay promise fulfillment to next loop iteration. --- src/lib/ecore/ecore_main.c | 22 ++++++++++++++++++++- src/lib/ecore/ecore_private.h | 3 +++ src/lib/ecore/efl_promise.c | 36 +++++++++++++++++++++++++++++++---- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c index 0ac83dfb1a..68df4afbd5 100644 --- a/src/lib/ecore/ecore_main.c +++ b/src/lib/ecore/ecore_main.c @@ -276,6 +276,7 @@ static void _ecore_main_win32_handlers_cleanup(void); int in_main_loop = 0; static Eina_List *_pending_futures = NULL; +static Eina_List *_pending_promises = NULL; static unsigned char _ecore_exit_code = 0; static int do_quit = 0; static Ecore_Fd_Handler *fd_handlers = NULL; @@ -1598,6 +1599,7 @@ ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, void _ecore_main_shutdown(void) { + Efl_Promise *promise; Efl_Future *future; if (in_main_loop) @@ -1611,6 +1613,9 @@ _ecore_main_shutdown(void) EINA_LIST_FREE(_pending_futures, future) efl_del(future); + EINA_LIST_FREE(_pending_promises, promise) + ecore_loop_promise_fulfill(promise); + while (fd_handlers) { Ecore_Fd_Handler *fdh; @@ -2235,7 +2240,7 @@ static void _ecore_main_loop_iterate_internal(int once_only) { double next_time = -1.0; - Eo *f; + Eo *f, *p; in_main_loop++; @@ -2243,6 +2248,10 @@ _ecore_main_loop_iterate_internal(int once_only) EINA_LIST_FREE(_pending_futures, f) efl_del(f); + /* and propagate all promise value */ + EINA_LIST_FREE(_pending_promises, p) + ecore_loop_promise_fulfill(p); + /* expire any timers */ _efl_loop_timer_expired_timers_call(_ecore_time_loop_time); @@ -2933,6 +2942,17 @@ ecore_loop_future_unregister(Efl_Loop *l EINA_UNUSED, Efl_Future *f) _pending_futures = eina_list_remove(_pending_futures, f); } +void +ecore_loop_promise_register(Efl_Loop *l EINA_UNUSED, Efl_Promise *p) +{ + _pending_promises = eina_list_append(_pending_promises, p); +} + +void +ecore_loop_promise_unregister(Efl_Loop *l EINA_UNUSED, Efl_Promise *p) +{ + _pending_promises = eina_list_remove(_pending_promises, p); +} EFL_CALLBACKS_ARRAY_DEFINE(timeout, { EFL_LOOP_TIMER_EVENT_TICK, _efl_loop_timeout_cb }, diff --git a/src/lib/ecore/ecore_private.h b/src/lib/ecore/ecore_private.h index 59aa2efd10..0197c8df08 100644 --- a/src/lib/ecore/ecore_private.h +++ b/src/lib/ecore/ecore_private.h @@ -370,6 +370,9 @@ extern Efl_Version _app_efl_version; void ecore_loop_future_register(Efl_Loop *l, Efl_Future *f); void ecore_loop_future_unregister(Efl_Loop *l, Efl_Future *f); +void ecore_loop_promise_register(Efl_Loop *l, Efl_Promise *p); +void ecore_loop_promise_unregister(Efl_Loop *l, Efl_Promise *p); +void ecore_loop_promise_fulfill(Efl_Promise *p); // access to direct input cb #define ECORE_EVAS_INTERNAL diff --git a/src/lib/ecore/efl_promise.c b/src/lib/ecore/efl_promise.c index 32ab6e0092..9ced5643ea 100644 --- a/src/lib/ecore/efl_promise.c +++ b/src/lib/ecore/efl_promise.c @@ -35,6 +35,8 @@ struct _Efl_Promise_Data } set; Eina_Bool optional : 1; + Eina_Bool propagated : 1; + Eina_Bool nodelay : 1; }; static void @@ -525,8 +527,9 @@ _efl_promise_future_get(Eo *obj, Efl_Promise_Data *pd EINA_UNUSED) fd->promise = efl_data_xref(obj, EFL_PROMISE_CLASS, f); fd->promise->futures = eina_list_append(fd->promise->futures, fd); - // The promise has already been fullfilled, prepare the propagation - if (fd->promise->message) + // The promise has already been fulfilled, prepare the propagation + if (fd->promise->message && + fd->promise->propagated) { fd->message = fd->promise->message; EINA_REFCOUNT_REF(fd->message); @@ -557,6 +560,8 @@ _efl_promise_propagate(Eo *obj, Efl_Promise_Data *pd) Efl_Loop_Future_Data *f; Eina_List *l, *ln; + pd->propagated = EINA_TRUE; + // By triggering this message, we are likely going to kill all future // And a user of the promise may want to attach an event handler on the promise // and destroy it, so delay that to after the loop is done. @@ -578,6 +583,14 @@ _efl_promise_propagate(Eo *obj, Efl_Promise_Data *pd) efl_unref(obj); } +void +ecore_loop_promise_fulfill(Eo *obj) +{ + Efl_Promise_Data *pd = efl_data_scope_get(obj, EFL_PROMISE_CLASS); + + _efl_promise_propagate(obj, pd); +} + static void _efl_promise_value_set(Eo *obj, Efl_Promise_Data *pd, void *v, Eina_Free_Cb free_cb) { @@ -599,7 +612,10 @@ _efl_promise_value_set(Eo *obj, Efl_Promise_Data *pd, void *v, Eina_Free_Cb free EINA_REFCOUNT_INIT(message); pd->message = message; - _efl_promise_propagate(obj, pd); + if (pd->nodelay) + _efl_promise_propagate(obj, pd); + else + ecore_loop_promise_register(efl_provider_find(obj, EFL_LOOP_CLASS), obj); } static void @@ -621,7 +637,10 @@ _efl_promise_failed_set(Eo *obj, Efl_Promise_Data *pd, Eina_Error err) EINA_REFCOUNT_INIT(message); pd->message = message; - _efl_promise_propagate(obj, pd); + if (pd->nodelay) + _efl_promise_propagate(obj, pd); + else + ecore_loop_promise_register(efl_provider_find(obj, EFL_LOOP_CLASS), obj); } static void @@ -665,6 +684,8 @@ _efl_promise_efl_object_constructor(Eo *obj, Efl_Promise_Data *pd) static void _efl_promise_efl_object_destructor(Eo *obj, Efl_Promise_Data *pd) { + pd->nodelay = EINA_TRUE; + // Unref refcounted structure if (!pd->message && pd->futures) { @@ -672,6 +693,13 @@ _efl_promise_efl_object_destructor(Eo *obj, Efl_Promise_Data *pd) efl_promise_failed_set(obj, EINA_ERROR_FUTURE_CANCEL); } + if (pd->message && + !pd->propagated) + { + ecore_loop_promise_unregister(efl_provider_find(obj, EFL_LOOP_CLASS), obj); + _efl_promise_propagate(obj, pd); + } + if (pd->message) { EINA_REFCOUNT_UNREF(pd->message)