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
This commit is contained in:
Carsten Haitzler 2016-07-07 18:41:23 +09:00
parent 9be9da17bf
commit f8fd74f8d2
3 changed files with 182 additions and 25 deletions

View File

@ -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.

View File

@ -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_OBJ:
eo_unref(node->d.obj);
break;
case DATA_VAL:
eina_value_free(node->d.val);
break;
case DATA_PTR:
break;
break;
case DATA_OBJ:
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;
}
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 *
@ -243,10 +273,28 @@ _eo_base_key_obj_get(Eo *obj, Eo_Base_Data *pd, const char *key)
return _key_generic_get(obj, pd, key, DATA_OBJ);
}
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 *

View File

@ -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);