eo: actually enforcing the efl_parent_set code path is necessary to enforce the predictability of the code path.

This commit is contained in:
Cedric Bail 2018-05-12 22:14:53 -07:00 committed by Cedric BAIL
parent 23e2c0bdb8
commit e1d41eef3a
2 changed files with 27 additions and 10 deletions

View File

@ -43,7 +43,7 @@ typedef struct
Eo ***wrefs;
} Efl_Object_Extension;
typedef struct
struct _Efl_Object_Data
{
Eina_Inlist *children;
Eo *parent;
@ -68,7 +68,7 @@ typedef struct
Eina_Bool parent_sunk : 1; // If parent ref has already been settled (parent has been set, or we are in add_ref mode
Eina_Bool allow_parent_unref : 1; // Allows unref to zero even with a parent
Eina_Bool has_destroyed_event_cb : 1; // No proper count: minor optimization triggered at destruction only
} Efl_Object_Data;
};
typedef enum
{
@ -135,7 +135,6 @@ _efl_object_invalidate(Eo *obj_id, Efl_Object_Data *pd)
_efl_pending_futures_clear(pd);
EO_OBJ_POINTER(obj_id, obj);
if (obj->invalidate) goto end;
// Finally invalidate itself if it wasn't done already
// I am not sure this is a good idea, but it force the
@ -144,9 +143,6 @@ _efl_object_invalidate(Eo *obj_id, Efl_Object_Data *pd)
if (!obj->is_invalidating)
efl_parent_set(obj_id, NULL);
obj->invalidate = EINA_TRUE;
end:
EO_OBJ_DONE(obj_id);
}
@ -189,6 +185,8 @@ _efl_invalidate(_Eo_Object *obj)
}
eina_array_flush(&stash);
obj->invalidate = EINA_TRUE;
}
static void
@ -711,7 +709,7 @@ _efl_object_reuse(_Eo_Object *obj)
obj->invalidate = EINA_FALSE;
}
EOLIAN static void
EOLIAN void
_efl_object_parent_set(Eo *obj, Efl_Object_Data *pd, Eo *parent_id)
{
Eo *prev_parent = pd->parent;

View File

@ -251,7 +251,9 @@ _eo_condtor_reset(_Eo_Object *obj)
obj->condtor_done = EINA_FALSE;
}
void _efl_invalidate(_Eo_Object *obj);
typedef struct _Efl_Object_Data Efl_Object_Data;
EOLIAN void _efl_object_parent_set(Eo *obj, Efl_Object_Data *pd, Eo *parent_id);
static inline void
_efl_del_internal(_Eo_Object *obj, const char *func_name, const char *file, int line)
@ -261,10 +263,27 @@ _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
// If the object hasn't 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);
if (obj->parent)
{
Eo *parent = efl_parent_get(_eo_obj_id_get(obj));
ERR("Destructor path being taken while object [%s] still has a parent [%s] in state %i:%i.",
efl_debug_name_get(_eo_obj_id_get(obj)),
efl_debug_name_get(parent),
obj->is_invalidating, obj->invalidate);
efl_parent_set(_eo_obj_id_get(obj), NULL);
if (obj->parent)
{
CRI("Something is preventing [%s] from disconnecting from its parent, bypassing.",
efl_debug_name_get(_eo_obj_id_get(obj)));
_efl_object_parent_set(_eo_obj_id_get(obj), efl_data_scope_get(_eo_obj_id_get(obj), EFL_OBJECT_CLASS), NULL);
}
}
efl_event_callback_call(_eo_obj_id_get(obj), EFL_EVENT_DEL, NULL);