From f8fd74f8d22658cba771f941be47085e7492fb22 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Thu, 7 Jul 2016 18:41:23 +0900 Subject: [PATCH] eo base - add weak object refs as per jpeg needs so after some discussion with jpeg, weak referenced keys are also a good idea. these need del track handling to be weak, so i made strong reffed keys also do del tracking again as it's just nice to do this and be more robust. also added and improved the test suites for this key value stuff. @feature --- src/lib/eo/eo_base.eo | 23 +++++++++ src/lib/eo/eo_base_class.c | 96 +++++++++++++++++++++++++++--------- src/tests/eo/suite/eo_test_general.c | 86 ++++++++++++++++++++++++++++++++ 3 files changed, 181 insertions(+), 24 deletions(-) diff --git a/src/lib/eo/eo_base.eo b/src/lib/eo/eo_base.eo index 72d7906..01ae857 100644 --- a/src/lib/eo/eo_base.eo +++ b/src/lib/eo/eo_base.eo @@ -253,6 +253,29 @@ abstract Eo.Base () } } } + @property key_obj_weak { + [[Generic weak object reference with string key to object. + + The object key will be removed if the object is removed, but + will not take or removed references like key_obj. + + This is the same key store used by key_data and key_value so keys + are shared and can store only one thing + ]] + keys { + key: string; [[the key associated with the object ref]] + } + set { + values { + objdata: const(Eo.Base); [[the object to set]] + } + } + get { + values { + objdata: Eo.Base; [[the object to set]] + } + } + } @property key_value { [[Value on with string key on the object. diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c index 82ab7d6..3a7f0a3 100644 --- a/src/lib/eo/eo_base_class.c +++ b/src/lib/eo/eo_base_class.c @@ -41,17 +41,19 @@ typedef struct typedef enum { DATA_PTR, DATA_OBJ, + DATA_OBJ_WEAK, DATA_VAL } Eo_Generic_Data_Node_Type; typedef struct { EINA_INLIST; + const Eo *obj; Eina_Stringshare *key; union { - Eina_Value *val; - Eo *obj; - void *ptr; + Eina_Value *val; + Eo *obj; + void *ptr; } d; Eo_Generic_Data_Node_Type d_type; } Eo_Generic_Data_Node; @@ -86,22 +88,25 @@ _eo_base_extension_noneed(Eo_Base_Data *pd) pd->ext = NULL; } - - +static void _key_generic_cb_del(void *data, const Eo_Event *event); static void _eo_generic_data_node_free(Eo_Generic_Data_Node *node) { switch (node->d_type) { + case DATA_PTR: + break; case DATA_OBJ: - eo_unref(node->d.obj); - break; + eo_event_callback_del(node->d.obj, EO_EVENT_DEL, _key_generic_cb_del, node); + eo_unref(node->d.obj); + break; + case DATA_OBJ_WEAK: + eo_event_callback_del(node->d.obj, EO_EVENT_DEL, _key_generic_cb_del, node); + break; case DATA_VAL: - eina_value_free(node->d.val); - break; - case DATA_PTR: - break; + eina_value_free(node->d.val); + break; } eina_stringshare_del(node->key); free(node); @@ -126,7 +131,17 @@ _eo_generic_data_del_all(Eo *obj EINA_UNUSED, Eo_Base_Data *pd) } static void -_eo_key_generic_del(const Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key) +_eo_key_generic_direct_del(Eo_Base_Data *pd, Eo_Generic_Data_Node *node, Eina_Bool call_free) +{ + Eo_Base_Extension *ext = pd->ext; + + ext->generic_data = eina_inlist_remove + (ext->generic_data, EINA_INLIST_GET(node)); + if (call_free) _eo_generic_data_node_free(node); +} + +static void +_eo_key_generic_del(const Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key, Eina_Bool call_free) { Eo_Generic_Data_Node *node; Eo_Base_Extension *ext = pd->ext; @@ -137,26 +152,26 @@ _eo_key_generic_del(const Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key { ext->generic_data = eina_inlist_remove (ext->generic_data, EINA_INLIST_GET(node)); - _eo_generic_data_node_free(node); + if (call_free) _eo_generic_data_node_free(node); return; } } } /* Return TRUE if the object was newly added. */ -static Eina_Bool -_key_generic_set(const Eo *obj, Eo_Base_Data *pd, const char *key, const void *data, Eo_Generic_Data_Node_Type d_type) +static Eo_Generic_Data_Node * +_key_generic_set(const Eo *obj, Eo_Base_Data *pd, const char *key, const void *data, Eo_Generic_Data_Node_Type d_type, Eina_Bool call_free) { Eo_Generic_Data_Node *node; Eo_Base_Extension *ext = pd->ext; - if (!key) return EINA_FALSE; + if (!key) return NULL; if (ext) { if (!data) { - _eo_key_generic_del(obj, pd, key); - return EINA_TRUE; + _eo_key_generic_del(obj, pd, key, call_free); + return NULL; } EINA_INLIST_FOREACH(ext->generic_data, node) { @@ -178,15 +193,16 @@ _key_generic_set(const Eo *obj, Eo_Base_Data *pd, const char *key, const void *d { node = calloc(1, sizeof(Eo_Generic_Data_Node)); if (!node) return EINA_FALSE; + node->obj = obj; node->key = eina_stringshare_add(key); node->d.ptr = (void *) data; node->d_type = d_type; ext->generic_data = eina_inlist_prepend (ext->generic_data, EINA_INLIST_GET(node)); - return EINA_TRUE; + return node; } - return EINA_FALSE; + return NULL; } static void * @@ -218,10 +234,18 @@ _key_generic_get(const Eo *obj, Eo_Base_Data *pd, const char *key, Eo_Generic_Da return NULL; } +static void +_key_generic_cb_del(void *data, const Eo_Event *event EINA_UNUSED) +{ + Eo_Generic_Data_Node *node = data; + Eo_Base_Data *pd = eo_data_scope_get(node->obj, EO_BASE_CLASS); + _eo_key_generic_direct_del(pd, node, EINA_FALSE); +} + EOLIAN static void _eo_base_key_data_set(Eo *obj, Eo_Base_Data *pd, const char *key, const void *data) { - _key_generic_set(obj, pd, key, data, DATA_PTR); + _key_generic_set(obj, pd, key, data, DATA_PTR, EINA_TRUE); } EOLIAN static void * @@ -233,8 +257,14 @@ _eo_base_key_data_get(Eo *obj, Eo_Base_Data *pd, const char *key) EOLIAN static void _eo_base_key_obj_set(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key, const Eo *objdata) { - if (_key_generic_set(obj, pd, key, objdata, DATA_OBJ)) - eo_ref(objdata); + Eo_Generic_Data_Node *node; + + node = _key_generic_set(obj, pd, key, objdata, DATA_OBJ, EINA_TRUE); + if (node) + { + eo_ref(objdata); + eo_event_callback_add((Eo *)objdata, EO_EVENT_DEL, _key_generic_cb_del, node); + } } EOLIAN static Eo * @@ -244,9 +274,27 @@ _eo_base_key_obj_get(Eo *obj, Eo_Base_Data *pd, const char *key) } EOLIAN static void +_eo_base_key_obj_weak_set(Eo *obj, Eo_Base_Data *pd, const char * key, const Eo_Base *objdata) +{ + Eo_Generic_Data_Node *node; + + node = _key_generic_set(obj, pd, key, objdata, DATA_OBJ_WEAK, EINA_TRUE); + if (node) + { + eo_event_callback_add((Eo *)objdata, EO_EVENT_DEL, _key_generic_cb_del, node); + } +} + +EOLIAN static Eo * +_eo_base_key_obj_weak_get(Eo *obj, Eo_Base_Data *pd, const char * key) +{ + return _key_generic_get(obj, pd, key, DATA_OBJ_WEAK); +} + +EOLIAN static void _eo_base_key_value_set(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key, Eina_Value *value) { - _key_generic_set(obj, pd, key, value, DATA_VAL); + _key_generic_set(obj, pd, key, value, DATA_VAL, EINA_TRUE); } EOLIAN static Eina_Value * diff --git a/src/tests/eo/suite/eo_test_general.c b/src/tests/eo/suite/eo_test_general.c index 2e2698d..ea94823 100644 --- a/src/tests/eo/suite/eo_test_general.c +++ b/src/tests/eo/suite/eo_test_general.c @@ -698,9 +698,12 @@ START_TEST(eo_generic_data) Eina_Value *value; Eina_Value *value2; + + eo_key_data_set(obj, "test1", (void *) 1); data = eo_key_data_get(obj, "test1"); fail_if(1 != (intptr_t) data); + eo_key_data_set(obj, "test1", NULL); data = eo_key_data_get(obj, "test1"); fail_if(data); @@ -709,17 +712,20 @@ START_TEST(eo_generic_data) eo_key_data_set(obj, "test2", (void *) 2); data = eo_key_data_get(obj, "test1"); fail_if(1 != (intptr_t) data); + data = eo_key_data_get(obj, "test2"); fail_if(2 != (intptr_t) data); data = eo_key_data_get(obj, "test2"); fail_if(2 != (intptr_t) data); + eo_key_data_set(obj, "test2", NULL); data = eo_key_data_get(obj, "test2"); fail_if(data); data = eo_key_data_get(obj, "test1"); fail_if(1 != (intptr_t) data); + eo_key_data_set(obj, "test1", NULL); data = eo_key_data_get(obj, "test1"); fail_if(data); @@ -729,29 +735,108 @@ START_TEST(eo_generic_data) eo_key_obj_set(obj, "test1", obj2); objtmp = eo_key_obj_get(obj, "test1"); fail_if(obj2 != objtmp); + eo_key_obj_set(obj, "test1", NULL); objtmp = eo_key_obj_get(obj, "test1"); fail_if(objtmp); eo_key_obj_set(obj, "test1", obj2); + fail_if(eo_ref_get(obj2) != 2); + eo_key_obj_set(obj, "test2", obj3); + fail_if(eo_ref_get(obj3) != 2); + objtmp = eo_key_obj_get(obj, "test1"); fail_if(obj2 != objtmp); + objtmp = eo_key_obj_get(obj, "test2"); fail_if(obj3 != objtmp); data = eo_key_obj_get(obj, "test2"); fail_if(obj3 != objtmp); + eo_key_obj_set(obj, "test2", NULL); + fail_if(eo_ref_get(obj3) != 1); + objtmp = eo_key_obj_get(obj, "test2"); fail_if(objtmp); objtmp = eo_key_obj_get(obj, "test1"); fail_if(obj2 != objtmp); + eo_key_obj_set(obj, "test1", NULL); + fail_if(eo_ref_get(obj2) != 1); + objtmp = eo_key_obj_get(obj, "test1"); fail_if(objtmp); + eo_key_obj_set(obj, "test1", obj2); + eo_key_obj_set(obj, "test2", obj3); + eo_del(obj2); + eo_del(obj2); + eo_del(obj3); + eo_del(obj3); + objtmp = eo_key_obj_get(obj, "test1"); + fail_if(objtmp); + + objtmp = eo_key_obj_get(obj, "test2"); + fail_if(objtmp); + + + + obj2 = eo_add(SIMPLE_CLASS, NULL); + obj3 = eo_add(SIMPLE_CLASS, NULL); + + eo_key_obj_weak_set(obj, "test1", obj2); + objtmp = eo_key_obj_weak_get(obj, "test1"); + fail_if(obj2 != objtmp); + + eo_key_obj_weak_set(obj, "test1", NULL); + objtmp = eo_key_obj_weak_get(obj, "test1"); + fail_if(objtmp); + + eo_key_obj_weak_set(obj, "test1", obj2); + fail_if(eo_ref_get(obj2) != 1); + + eo_key_obj_weak_set(obj, "test2", obj3); + fail_if(eo_ref_get(obj3) != 1); + + objtmp = eo_key_obj_weak_get(obj, "test1"); + fail_if(obj2 != objtmp); + + objtmp = eo_key_obj_weak_get(obj, "test2"); + fail_if(obj3 != objtmp); + + data = eo_key_obj_weak_get(obj, "test2"); + fail_if(obj3 != objtmp); + + eo_key_obj_weak_set(obj, "test2", NULL); + fail_if(eo_ref_get(obj3) != 1); + + objtmp = eo_key_obj_weak_get(obj, "test2"); + fail_if(objtmp); + + objtmp = eo_key_obj_weak_get(obj, "test1"); + fail_if(obj2 != objtmp); + + eo_key_obj_weak_set(obj, "test1", NULL); + fail_if(eo_ref_get(obj2) != 1); + + objtmp = eo_key_obj_weak_get(obj, "test1"); + fail_if(objtmp); + + eo_key_obj_weak_set(obj, "test1", obj2); + eo_key_obj_weak_set(obj, "test2", obj3); + eo_del(obj2); + eo_del(obj3); + objtmp = eo_key_obj_weak_get(obj, "test1"); + fail_if(objtmp); + + objtmp = eo_key_obj_weak_get(obj, "test2"); + fail_if(objtmp); + + + value = eina_value_new(EINA_VALUE_TYPE_INT); eina_value_set(value, 1234); value2 = eo_key_value_get(obj, "value1"); @@ -764,6 +849,7 @@ START_TEST(eo_generic_data) eo_key_value_set(obj, "value1", NULL); value2 = eo_key_value_get(obj, "value1"); fail_if(value2 != NULL); + eo_key_value_set(obj, "value1", NULL); eo_unref(obj); -- 2.7.4