cedric pushed a commit to branch master.

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

commit 36f8a70041a8a16249a07d5b7131d57a8a6ea95b
Author: Cedric Bail <ced...@osg.samsung.com>
Date:   Wed Apr 4 15:37:11 2018 -0700

    eo: to avoid mistake in timing, efl_invalidate should always be triggered 
before any destructor code.
    
    Differential Revision: https://phab.enlightenment.org/D6061
---
 src/lib/eo/eo_base_class.c | 76 ++++++++++++++++++++++++++--------------------
 src/lib/eo/eo_private.h    | 24 +++++++++++++++
 2 files changed, 67 insertions(+), 33 deletions(-)

diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c
index 9b7b1958f2..5d21a429bd 100644
--- a/src/lib/eo/eo_base_class.c
+++ b/src/lib/eo/eo_base_class.c
@@ -127,26 +127,31 @@ _efl_pending_futures_clear(Efl_Object_Data *pd)
      }
 }
 
-// Generate the invalidate event in all case and make sure it happens
-// before any user code can change the children invalidate state. This
-// make sure that the entire tree of object is valid at the time of
-// the invalidate event.
 static void
-_efl_invalidate(Eo *obj)
+_efl_object_invalidate(Eo *obj_id, Efl_Object_Data *pd)
 {
-   efl_event_callback_call(obj, EFL_EVENT_INVALIDATE, NULL);
+   Eina_Inlist *l;
+   _Eo_Object *child;
 
-   efl_invalidate(obj);
-}
-
-static void
-_efl_object_invalidate(Eo *obj, Efl_Object_Data *pd)
-{
    _efl_pending_futures_clear(pd);
 
-   if (pd->invalidate) return ;
-   efl_parent_set(obj, NULL);
-   pd->invalidate = EINA_TRUE;
+   EO_OBJ_POINTER(obj_id, obj);
+   if (obj->invalidate) goto end;
+
+   // Invalidate all children too
+   EINA_INLIST_FOREACH_SAFE(pd->children, l, child)
+     {
+        Eo *child_id = _eo_obj_id_get(child);
+        efl_parent_set(child_id, NULL);
+     }
+
+   // Finally invalidate itself
+   efl_parent_set(obj_id, NULL);
+
+   obj->invalidate = EINA_TRUE;
+
+ end:
+   EO_OBJ_DONE(obj_id);
 }
 
 static void
@@ -658,10 +663,11 @@ _efl_object_parent_sink_set(Eo *obj, Eina_Bool sink)
 }
 
 void
-_efl_object_reuse(Eo *obj)
+_efl_object_reuse(Eo *obj_id)
 {
-   Efl_Object_Data *pd = efl_data_scope_get(obj, EFL_OBJECT_CLASS);
-   pd->invalidate = EINA_FALSE;
+   EO_OBJ_POINTER(obj_id, obj);
+   obj->invalidate = EINA_FALSE;
+   EO_OBJ_DONE(obj_id);
 }
 
 EOLIAN static void
@@ -675,10 +681,10 @@ _efl_object_parent_set(Eo *obj, Efl_Object_Data *pd, Eo 
*parent_id)
    EO_OBJ_POINTER_GOTO(obj, eo_obj, err_impossible);
 
    // Invalidated object can not be bring back to life
-   if (pd->invalidate)
+   if (eo_obj->invalidate)
      {
         ERR("Call of efl_parent_set(%p, %p) when object is already 
invalidated.\n", obj, parent_id);
-       return ;
+        goto err_impossible;
      }
 
    if (pd->parent)
@@ -719,8 +725,8 @@ _efl_object_parent_set(Eo *obj, Efl_Object_Data *pd, Eo 
*parent_id)
      }
    else
      {
-        pd->invalidate = EINA_TRUE;
-        if (prev_parent) _efl_invalidate(obj);
+        eo_obj->invalidate = EINA_TRUE;
+        if (prev_parent) _efl_invalidate(eo_obj);
 
         pd->parent = NULL;
         if (prev_parent && !eo_obj->del_triggered) efl_unref(obj);
@@ -758,15 +764,22 @@ _efl_object_finalized_get(const Eo *obj_id, 
Efl_Object_Data *pd EINA_UNUSED)
 }
 
 EOLIAN static Eina_Bool
-_efl_object_invalidated_get(const Eo *obj_id EINA_UNUSED, Efl_Object_Data *pd)
+_efl_object_invalidated_get(const Eo *obj_id, Efl_Object_Data *pd EINA_UNUSED)
 {
-   return pd->invalidate;
+   Eina_Bool invalidate;
+   EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_TRUE);
+   invalidate = obj->invalidate;
+   EO_OBJ_DONE(obj_id);
+   return invalidate;
 }
 
 EOLIAN static Efl_Object *
 _efl_object_provider_find(const Eo *obj, Efl_Object_Data *pd, const Efl_Object 
*klass)
 {
-   if (pd->invalidate)
+   Eina_Bool invalidate;
+
+   invalidate = _efl_object_invalidated_get((Eo*) obj, NULL);
+   if (invalidate)
      {
         ERR("Calling efl_provider_find(%p) after the object was invalidated.", 
obj);
        return NULL;
@@ -2014,11 +2027,15 @@ efl_future_cb_from_desc(const Eo *o, const 
Efl_Future_Cb_Desc desc)
    Efl_Future_Pending *pending = NULL;
    Eina_Future **storage = NULL;
    Efl_Object_Data *pd;
+   Eina_Bool invalidate;
 
    EINA_SAFETY_ON_NULL_GOTO(o, end);
    pd = efl_data_scope_get(o, EFL_OBJECT_CLASS);
    EINA_SAFETY_ON_NULL_GOTO(pd, end);
-   EINA_SAFETY_ON_TRUE_GOTO(pd->invalidate, end);
+   EO_OBJ_POINTER_GOTO(o, eo_obj, end);
+   invalidate = eo_obj->invalidate;
+   EO_OBJ_DONE(o);
+   EINA_SAFETY_ON_TRUE_GOTO(invalidate, end);
    pending = _efl_pending_future_new();
    EINA_SAFETY_ON_NULL_GOTO(pending, end);
    memcpy(&pending->desc, &desc, sizeof(Efl_Future_Cb_Desc));
@@ -2086,13 +2103,6 @@ _efl_object_destructor(Eo *obj, Efl_Object_Data *pd)
 
    DBG("%p - %s.", obj, efl_class_name_get(obj));
 
-   // If the object has been invalidated yet, time to do it
-   // This can happen when the object has no parent and get
-   // deleted by efl_unref.
-   if (!pd->invalidate)
-     _efl_invalidate(obj);
-
-
    // special removal - remove from children list by hand after getting
    // child handle in case unparent method is overridden and does
    // extra things like removes other children too later on in the list
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h
index b3c8390e97..f3c0e582b9 100644
--- a/src/lib/eo/eo_private.h
+++ b/src/lib/eo/eo_private.h
@@ -115,6 +115,7 @@ struct _Eo_Object
      Eina_Bool condtor_done:1;
      Eina_Bool finalized:1;
      Eina_Bool super:1;
+     Eina_Bool invalidate:1;
 
      Eina_Bool del_triggered:1;
      Eina_Bool destructed:1;
@@ -247,6 +248,24 @@ _eo_condtor_reset(_Eo_Object *obj)
    obj->condtor_done = EINA_FALSE;
 }
 
+// Generate the invalidate event in all case and make sure it happens
+// before any user code can change the children invalidate state. This
+// make sure that the entire tree of object is valid at the time of
+// the invalidate event.
+static void
+_efl_invalidate(_Eo_Object *obj)
+{
+   Eo *id;
+
+   if (obj->invalidate) return;
+
+   id = _eo_obj_id_get(obj);
+
+   efl_event_callback_call(id, EFL_EVENT_INVALIDATE, NULL);
+
+   efl_invalidate(id);
+}
+
 static inline void
 _efl_del_internal(_Eo_Object *obj, const char *func_name, const char *file, 
int line)
 {
@@ -255,6 +274,11 @@ _efl_del_internal(_Eo_Object *obj, const char *func_name, 
const char *file, int
 
    const _Efl_Class *klass = obj->klass;
 
+   // If the object has been invalidated yet, time to do it
+   // before any destructor kick in. This can happen when
+   // the object has no parent and get deleted by efl_unref.
+   _efl_invalidate(obj);
+
    efl_event_callback_call(_eo_obj_id_get(obj), EFL_EVENT_DEL, NULL);
 
    _eo_condtor_reset(obj);

-- 


Reply via email to