tasn pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=25242e6af9b44ce0b31c66396ba1afbc75bb29a8
commit 25242e6af9b44ce0b31c66396ba1afbc75bb29a8 Author: Tom Hacohen <t...@stosb.com> Date: Fri Oct 21 15:02:27 2016 +0100 Eo: Fix references of objects --- src/lib/eo/eo.c | 8 ++++++-- src/lib/eo/eo_base_class.c | 22 +++++++++++++++++----- src/lib/eo/eo_private.h | 2 ++ src/tests/eo/suite/eo_test_general.c | 4 ++-- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index 8ce82f3..ad8306d 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -850,9 +850,13 @@ _efl_add_end(Eo *eo_id, Eina_Bool is_ref, Eina_Bool is_fallback) 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) diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c index f64ebca..bc85105 100644 --- a/src/lib/eo/eo_base_class.c +++ b/src/lib/eo/eo_base_class.c @@ -39,6 +39,7 @@ typedef struct 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 { @@ -533,9 +534,17 @@ _efl_object_del(const Eo *obj, Efl_Object_Data *pd EINA_UNUSED) } } +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; @@ -552,10 +561,6 @@ _efl_object_parent_set(Eo *obj, Efl_Object_Data *pd, Eo *parent_id) // 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 */ @@ -569,16 +574,23 @@ _efl_object_parent_set(Eo *obj, Efl_Object_Data *pd, Eo *parent_id) 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; diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h index 54975ff..035d84c 100644 --- a/src/lib/eo/eo_private.h +++ b/src/lib/eo/eo_private.h @@ -196,6 +196,8 @@ typedef struct int line; } Eo_Xref_Node; +void _efl_object_parent_sink(Eo *obj); + static inline Eo *_eo_header_id_get(const Eo_Header *header) { diff --git a/src/tests/eo/suite/eo_test_general.c b/src/tests/eo/suite/eo_test_general.c index 648f733..e142d67 100644 --- a/src/tests/eo/suite/eo_test_general.c +++ b/src/tests/eo/suite/eo_test_general.c @@ -611,8 +611,8 @@ START_TEST(efl_refs) 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); --