forked from enlightenment/efl
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:
parent
9be9da17bf
commit
f8fd74f8d2
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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 *
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue