cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=ca1762be21f3913deedb094fe4186d1af8136632

commit ca1762be21f3913deedb094fe4186d1af8136632
Author: Cedric BAIL <ced...@osg.samsung.com>
Date:   Fri Dec 16 11:26:46 2016 -0800

    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 0ac83df..68df4af 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 59aa2ef..0197c8d 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 32ab6e0..9ced564 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)

-- 


Reply via email to