Eo *ret = efl_finalize(eo_id);
ret = _efl_add_internal_end(eo_id, ret);
- if (is_ref && efl_parent_get(eo_id))
+ if (is_ref)
{
- efl_ref(eo_id);
+ if (efl_parent_get(eo_id))
+ {
+ efl_ref(eo_id);
+ }
+ _efl_object_parent_sink(eo_id);
}
if (is_fallback)
unsigned short event_freeze_count;
Eina_Bool deletions_waiting : 1;
Eina_Bool callback_stopped : 1;
+ Eina_Bool parent_sunk : 1; // If parent ref has already been settled (parent has been set, or we are in add_ref mode
} Efl_Object_Data;
typedef enum {
}
}
+void
+_efl_object_parent_sink(Eo *obj)
+{
+ Efl_Object_Data *pd = efl_data_scope_get(obj, EFL_OBJECT_CLASS);
+ pd->parent_sunk = EINA_TRUE;
+}
+
EOLIAN static void
_efl_object_parent_set(Eo *obj, Efl_Object_Data *pd, Eo *parent_id)
{
+ Eo *prev_parent = pd->parent;
if ((pd->parent == parent_id) ||
((parent_id) && (!_eo_id_domain_compatible(parent_id, obj))))
return;
// this error is highly unlikely so move it out of the normal
// instruction path to avoid l1 cache pollution
else goto err_impossible;
-
- /* Only unref if we don't have a new parent instead and we are not at
- * the process of deleting the object.*/
- if (!parent_id && !eo_obj->del_triggered) efl_unref(obj);
}
/* Set new parent */
pd->parent = parent_id;
parent_pd->children = eina_inlist_append(parent_pd->children,
EINA_INLIST_GET(eo_obj));
+ if (!prev_parent && pd->parent_sunk) efl_ref(obj);
+ pd->parent_sunk = EINA_TRUE;
}
else
{
pd->parent = NULL;
+ if (prev_parent) efl_unref(obj);
// unlikely this error happens, so move it out of execution path
// to improve l1 cache efficiency
goto err_parent;
}
}
- else pd->parent = NULL;
+ else
+ {
+ pd->parent = NULL;
+ if (prev_parent && !eo_obj->del_triggered) efl_unref(obj);
+ }
EO_OBJ_DONE(obj);
return;
efl_parent_set(obj2, obj);
efl_parent_set(obj3, obj);
- ck_assert_int_eq(efl_ref_get(obj2), 1);
- ck_assert_int_eq(efl_ref_get(obj3), 1);
+ ck_assert_int_eq(efl_ref_get(obj2), 2);
+ ck_assert_int_eq(efl_ref_get(obj3), 2);
efl_del(obj);
efl_del(obj2);