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 { @property key_value {
[[Value on with string key on the object. [[Value on with string key on the object.

View File

@ -41,17 +41,19 @@ typedef struct
typedef enum { typedef enum {
DATA_PTR, DATA_PTR,
DATA_OBJ, DATA_OBJ,
DATA_OBJ_WEAK,
DATA_VAL DATA_VAL
} Eo_Generic_Data_Node_Type; } Eo_Generic_Data_Node_Type;
typedef struct typedef struct
{ {
EINA_INLIST; EINA_INLIST;
const Eo *obj;
Eina_Stringshare *key; Eina_Stringshare *key;
union { union {
Eina_Value *val; Eina_Value *val;
Eo *obj; Eo *obj;
void *ptr; void *ptr;
} d; } d;
Eo_Generic_Data_Node_Type d_type; Eo_Generic_Data_Node_Type d_type;
} Eo_Generic_Data_Node; } Eo_Generic_Data_Node;
@ -86,22 +88,25 @@ _eo_base_extension_noneed(Eo_Base_Data *pd)
pd->ext = NULL; pd->ext = NULL;
} }
static void _key_generic_cb_del(void *data, const Eo_Event *event);
static void static void
_eo_generic_data_node_free(Eo_Generic_Data_Node *node) _eo_generic_data_node_free(Eo_Generic_Data_Node *node)
{ {
switch (node->d_type) 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: 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); eina_stringshare_del(node->key);
free(node); free(node);
@ -126,7 +131,17 @@ _eo_generic_data_del_all(Eo *obj EINA_UNUSED, Eo_Base_Data *pd)
} }
static void 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_Generic_Data_Node *node;
Eo_Base_Extension *ext = pd->ext; 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_remove
(ext->generic_data, EINA_INLIST_GET(node)); (ext->generic_data, EINA_INLIST_GET(node));
_eo_generic_data_node_free(node); if (call_free) _eo_generic_data_node_free(node);
return; return;
} }
} }
} }
/* Return TRUE if the object was newly added. */ /* Return TRUE if the object was newly added. */
static Eina_Bool 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) _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_Generic_Data_Node *node;
Eo_Base_Extension *ext = pd->ext; Eo_Base_Extension *ext = pd->ext;
if (!key) return EINA_FALSE; if (!key) return NULL;
if (ext) if (ext)
{ {
if (!data) if (!data)
{ {
_eo_key_generic_del(obj, pd, key); _eo_key_generic_del(obj, pd, key, call_free);
return EINA_TRUE; return NULL;
} }
EINA_INLIST_FOREACH(ext->generic_data, node) 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)); node = calloc(1, sizeof(Eo_Generic_Data_Node));
if (!node) return EINA_FALSE; if (!node) return EINA_FALSE;
node->obj = obj;
node->key = eina_stringshare_add(key); node->key = eina_stringshare_add(key);
node->d.ptr = (void *) data; node->d.ptr = (void *) data;
node->d_type = d_type; node->d_type = d_type;
ext->generic_data = eina_inlist_prepend ext->generic_data = eina_inlist_prepend
(ext->generic_data, EINA_INLIST_GET(node)); (ext->generic_data, EINA_INLIST_GET(node));
return EINA_TRUE; return node;
} }
return EINA_FALSE; return NULL;
} }
static void * static void *
@ -218,10 +234,18 @@ _key_generic_get(const Eo *obj, Eo_Base_Data *pd, const char *key, Eo_Generic_Da
return NULL; 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 EOLIAN static void
_eo_base_key_data_set(Eo *obj, Eo_Base_Data *pd, const char *key, const void *data) _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 * EOLIAN static void *
@ -233,8 +257,14 @@ _eo_base_key_data_get(Eo *obj, Eo_Base_Data *pd, const char *key)
EOLIAN static void EOLIAN static void
_eo_base_key_obj_set(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key, const Eo *objdata) _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_Generic_Data_Node *node;
eo_ref(objdata);
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 * 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); 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 EOLIAN static void
_eo_base_key_value_set(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key, Eina_Value *value) _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 * EOLIAN static Eina_Value *

View File

@ -698,9 +698,12 @@ START_TEST(eo_generic_data)
Eina_Value *value; Eina_Value *value;
Eina_Value *value2; Eina_Value *value2;
eo_key_data_set(obj, "test1", (void *) 1); eo_key_data_set(obj, "test1", (void *) 1);
data = eo_key_data_get(obj, "test1"); data = eo_key_data_get(obj, "test1");
fail_if(1 != (intptr_t) data); fail_if(1 != (intptr_t) data);
eo_key_data_set(obj, "test1", NULL); eo_key_data_set(obj, "test1", NULL);
data = eo_key_data_get(obj, "test1"); data = eo_key_data_get(obj, "test1");
fail_if(data); fail_if(data);
@ -709,17 +712,20 @@ START_TEST(eo_generic_data)
eo_key_data_set(obj, "test2", (void *) 2); eo_key_data_set(obj, "test2", (void *) 2);
data = eo_key_data_get(obj, "test1"); data = eo_key_data_get(obj, "test1");
fail_if(1 != (intptr_t) data); fail_if(1 != (intptr_t) data);
data = eo_key_data_get(obj, "test2"); data = eo_key_data_get(obj, "test2");
fail_if(2 != (intptr_t) data); fail_if(2 != (intptr_t) data);
data = eo_key_data_get(obj, "test2"); data = eo_key_data_get(obj, "test2");
fail_if(2 != (intptr_t) data); fail_if(2 != (intptr_t) data);
eo_key_data_set(obj, "test2", NULL); eo_key_data_set(obj, "test2", NULL);
data = eo_key_data_get(obj, "test2"); data = eo_key_data_get(obj, "test2");
fail_if(data); fail_if(data);
data = eo_key_data_get(obj, "test1"); data = eo_key_data_get(obj, "test1");
fail_if(1 != (intptr_t) data); fail_if(1 != (intptr_t) data);
eo_key_data_set(obj, "test1", NULL); eo_key_data_set(obj, "test1", NULL);
data = eo_key_data_get(obj, "test1"); data = eo_key_data_get(obj, "test1");
fail_if(data); fail_if(data);
@ -729,29 +735,108 @@ START_TEST(eo_generic_data)
eo_key_obj_set(obj, "test1", obj2); eo_key_obj_set(obj, "test1", obj2);
objtmp = eo_key_obj_get(obj, "test1"); objtmp = eo_key_obj_get(obj, "test1");
fail_if(obj2 != objtmp); fail_if(obj2 != objtmp);
eo_key_obj_set(obj, "test1", NULL); eo_key_obj_set(obj, "test1", NULL);
objtmp = eo_key_obj_get(obj, "test1"); objtmp = eo_key_obj_get(obj, "test1");
fail_if(objtmp); fail_if(objtmp);
eo_key_obj_set(obj, "test1", obj2); eo_key_obj_set(obj, "test1", obj2);
fail_if(eo_ref_get(obj2) != 2);
eo_key_obj_set(obj, "test2", obj3); eo_key_obj_set(obj, "test2", obj3);
fail_if(eo_ref_get(obj3) != 2);
objtmp = eo_key_obj_get(obj, "test1"); objtmp = eo_key_obj_get(obj, "test1");
fail_if(obj2 != objtmp); fail_if(obj2 != objtmp);
objtmp = eo_key_obj_get(obj, "test2"); objtmp = eo_key_obj_get(obj, "test2");
fail_if(obj3 != objtmp); fail_if(obj3 != objtmp);
data = eo_key_obj_get(obj, "test2"); data = eo_key_obj_get(obj, "test2");
fail_if(obj3 != objtmp); fail_if(obj3 != objtmp);
eo_key_obj_set(obj, "test2", NULL); eo_key_obj_set(obj, "test2", NULL);
fail_if(eo_ref_get(obj3) != 1);
objtmp = eo_key_obj_get(obj, "test2"); objtmp = eo_key_obj_get(obj, "test2");
fail_if(objtmp); fail_if(objtmp);
objtmp = eo_key_obj_get(obj, "test1"); objtmp = eo_key_obj_get(obj, "test1");
fail_if(obj2 != objtmp); fail_if(obj2 != objtmp);
eo_key_obj_set(obj, "test1", NULL); eo_key_obj_set(obj, "test1", NULL);
fail_if(eo_ref_get(obj2) != 1);
objtmp = eo_key_obj_get(obj, "test1"); objtmp = eo_key_obj_get(obj, "test1");
fail_if(objtmp); 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); value = eina_value_new(EINA_VALUE_TYPE_INT);
eina_value_set(value, 1234); eina_value_set(value, 1234);
value2 = eo_key_value_get(obj, "value1"); value2 = eo_key_value_get(obj, "value1");
@ -764,6 +849,7 @@ START_TEST(eo_generic_data)
eo_key_value_set(obj, "value1", NULL); eo_key_value_set(obj, "value1", NULL);
value2 = eo_key_value_get(obj, "value1"); value2 = eo_key_value_get(obj, "value1");
fail_if(value2 != NULL); fail_if(value2 != NULL);
eo_key_value_set(obj, "value1", NULL); eo_key_value_set(obj, "value1", NULL);
eo_unref(obj); eo_unref(obj);