forked from enlightenment/efl
eo - add object sotrage in generic values with ref/unref
this adds eo_key_obj_set/get/del() like with data but for object handles so the obj is ref'd as long as the key and parent obj exists and then unreffed on deletion. it also tracks deletion of reffed objects like weak refs and then removes the key automatically. @feature
This commit is contained in:
parent
5065356ae6
commit
8be56c9498
|
@ -154,6 +154,35 @@ abstract Eo.Base ()
|
|||
@in key: const(char)*; [[the key associated with the data]]
|
||||
}
|
||||
}
|
||||
key_obj_set {
|
||||
[[Set generic object reference to object.
|
||||
|
||||
The object will be automatically ref'd when set and unref'd
|
||||
when replaced or deleted or referring object is deleted. If
|
||||
the referenced object is deleted then the key is deleted
|
||||
automatically.
|
||||
|
||||
This is the same key store used by key_data_set etc. so keys
|
||||
are shared and can store only one thing
|
||||
]]
|
||||
params {
|
||||
@in key: const(char)*; [[the key associated with the object ref]]
|
||||
@in objdata: Eo *; [[the object to set]]
|
||||
}
|
||||
}
|
||||
key_obj_get @const {
|
||||
[[Get generic object reference from object.]]
|
||||
params {
|
||||
@in key: const(char)*; [[the key associated with the object ref]]
|
||||
}
|
||||
return: Eo *; [[the object reference for the key]]
|
||||
}
|
||||
key_obj_del {
|
||||
[[Del generic objecrt reference from object.]]
|
||||
params {
|
||||
@in key: const(char)*; [[the key associated with the object ref]]
|
||||
}
|
||||
}
|
||||
event_thaw {
|
||||
[[thaw events of object.
|
||||
|
||||
|
|
|
@ -33,7 +33,8 @@ typedef struct
|
|||
{
|
||||
EINA_INLIST;
|
||||
Eina_Stringshare *key;
|
||||
void *data;
|
||||
void *data;
|
||||
Eina_Bool data_is_obj : 1;
|
||||
} Eo_Generic_Data_Node;
|
||||
|
||||
static void
|
||||
|
@ -43,59 +44,224 @@ _eo_generic_data_node_free(Eo_Generic_Data_Node *node)
|
|||
free(node);
|
||||
}
|
||||
|
||||
static void
|
||||
_eo_generic_data_del_all(Eo_Base_Data *pd)
|
||||
static Eina_Bool
|
||||
_eo_base_cb_key_obj_del(void *data, const Eo_Event *event)
|
||||
{
|
||||
Eina_Inlist *nnode;
|
||||
Eo_Generic_Data_Node *node = NULL;
|
||||
Eo *parent_obj = data;
|
||||
Eo_Base_Data *pd = eo_data_scope_get(parent_obj, EO_BASE_CLASS);
|
||||
|
||||
EINA_INLIST_FOREACH_SAFE(pd->generic_data, nnode, node)
|
||||
if (pd)
|
||||
{
|
||||
pd->generic_data = eina_inlist_remove(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
Eo_Generic_Data_Node *node;
|
||||
|
||||
EINA_INLIST_FOREACH(pd->generic_data, node)
|
||||
{
|
||||
if ((node->data_is_obj) && (node->data == event->obj))
|
||||
{
|
||||
pd->generic_data = eina_inlist_remove(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
|
||||
_eo_base_cb_key_obj_del, data);
|
||||
eo_unref(node->data);
|
||||
_eo_generic_data_node_free(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_eo_generic_data_del_all(Eo *obj, Eo_Base_Data *pd)
|
||||
{
|
||||
Eo_Generic_Data_Node *node;
|
||||
|
||||
while (pd->generic_data)
|
||||
{
|
||||
node = (Eo_Generic_Data_Node *)pd->generic_data;
|
||||
pd->generic_data = eina_inlist_remove(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
if (node->data_is_obj)
|
||||
{
|
||||
eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
|
||||
_eo_base_cb_key_obj_del, obj);
|
||||
eo_unref(node->data);
|
||||
}
|
||||
_eo_generic_data_node_free(node);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Eo_Generic_Data_Node *node;
|
||||
|
||||
if (!key) return;
|
||||
|
||||
eo_key_data_del(obj, key);
|
||||
|
||||
node = malloc(sizeof(Eo_Generic_Data_Node));
|
||||
if (!node) return;
|
||||
node->key = eina_stringshare_add(key);
|
||||
node->data = (void *) data;
|
||||
pd->generic_data = eina_inlist_prepend(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
}
|
||||
|
||||
EOLIAN static void *
|
||||
_eo_base_key_data_get(const Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key)
|
||||
{
|
||||
/* We don't really change it... */
|
||||
Eo_Generic_Data_Node *node;
|
||||
if (!key) return NULL;
|
||||
|
||||
EINA_INLIST_FOREACH(pd->generic_data, node)
|
||||
{
|
||||
if (!strcmp(node->key, key))
|
||||
{
|
||||
pd->generic_data =
|
||||
eina_inlist_promote(pd->generic_data, EINA_INLIST_GET(node));
|
||||
return node->data;
|
||||
if ((!node->data_is_obj) && (node->data == data)) return;
|
||||
pd->generic_data = eina_inlist_remove(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
if (node->data_is_obj)
|
||||
{
|
||||
eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
|
||||
_eo_base_cb_key_obj_del, obj);
|
||||
eo_unref(node->data);
|
||||
}
|
||||
_eo_generic_data_node_free(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
node = calloc(1, sizeof(Eo_Generic_Data_Node));
|
||||
if (!node) return;
|
||||
node->key = eina_stringshare_add(key);
|
||||
node->data = (void *)data;
|
||||
node->data_is_obj = EINA_FALSE;
|
||||
pd->generic_data = eina_inlist_prepend(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
}
|
||||
|
||||
EOLIAN static void *
|
||||
_eo_base_key_data_get(const Eo *obj, Eo_Base_Data *pd, const char *key)
|
||||
{
|
||||
Eo_Generic_Data_Node *node;
|
||||
|
||||
if (!key) return NULL;
|
||||
EINA_INLIST_FOREACH(pd->generic_data, node)
|
||||
{
|
||||
if (!strcmp(node->key, key))
|
||||
{
|
||||
if (!node->data_is_obj)
|
||||
{
|
||||
pd->generic_data = eina_inlist_promote(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
return node->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Object %p key '%s' is an object, not raw data",
|
||||
obj, key);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_eo_base_key_data_del(Eo *obj, Eo_Base_Data *pd, const char *key)
|
||||
{
|
||||
Eo_Generic_Data_Node *node;
|
||||
|
||||
if (!key) return;
|
||||
EINA_INLIST_FOREACH(pd->generic_data, node)
|
||||
{
|
||||
if (!strcmp(node->key, key))
|
||||
{
|
||||
pd->generic_data = eina_inlist_remove(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
if (node->data_is_obj)
|
||||
{
|
||||
eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
|
||||
_eo_base_cb_key_obj_del, obj);
|
||||
eo_unref(node->data);
|
||||
}
|
||||
_eo_generic_data_node_free(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_eo_base_key_obj_set(Eo *obj, Eo_Base_Data *pd, const char *key, Eo *objdata)
|
||||
{
|
||||
Eo_Generic_Data_Node *node;
|
||||
|
||||
if (!key) return;
|
||||
EINA_INLIST_FOREACH(pd->generic_data, node)
|
||||
{
|
||||
if (!strcmp(node->key, key))
|
||||
{
|
||||
if ((node->data_is_obj) && (node->data == objdata)) return;
|
||||
pd->generic_data = eina_inlist_remove(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
if (node->data_is_obj)
|
||||
{
|
||||
eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
|
||||
_eo_base_cb_key_obj_del, obj);
|
||||
eo_unref(node->data);
|
||||
}
|
||||
_eo_generic_data_node_free(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
node = calloc(1, sizeof(Eo_Generic_Data_Node));
|
||||
if (!node) return;
|
||||
node->key = eina_stringshare_add(key);
|
||||
node->data = (void *)objdata;
|
||||
node->data_is_obj = EINA_TRUE;
|
||||
eo_event_callback_add(node->data, EO_BASE_EVENT_DEL,
|
||||
_eo_base_cb_key_obj_del, obj);
|
||||
eo_ref(node->data);
|
||||
pd->generic_data = eina_inlist_prepend(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
}
|
||||
|
||||
EOLIAN static Eo *
|
||||
_eo_base_key_obj_get(const Eo *obj, Eo_Base_Data *pd, const char *key)
|
||||
{
|
||||
Eo_Generic_Data_Node *node;
|
||||
|
||||
if (!key) return NULL;
|
||||
EINA_INLIST_FOREACH(pd->generic_data, node)
|
||||
{
|
||||
if (!strcmp(node->key, key))
|
||||
{
|
||||
if (node->data_is_obj)
|
||||
{
|
||||
pd->generic_data = eina_inlist_promote(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
return node->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Object %p key '%s' is an object, not an object",
|
||||
obj, key);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_eo_base_key_obj_del(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key)
|
||||
{
|
||||
Eo_Generic_Data_Node *node;
|
||||
|
||||
if (!key) return;
|
||||
EINA_INLIST_FOREACH(pd->generic_data, node)
|
||||
{
|
||||
if (!strcmp(node->key, key))
|
||||
{
|
||||
pd->generic_data = eina_inlist_remove(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
if (node->data_is_obj)
|
||||
{
|
||||
eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
|
||||
_eo_base_cb_key_obj_del, obj);
|
||||
eo_unref(node->data);
|
||||
}
|
||||
_eo_generic_data_node_free(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_eo_base_parent_set(Eo *obj, Eo_Base_Data *pd, Eo *parent_id)
|
||||
{
|
||||
|
@ -265,25 +431,6 @@ _eo_base_dbg_info_get(Eo *obj EINA_UNUSED, Eo_Base_Data *pd EINA_UNUSED, Eo_Dbg_
|
|||
return;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_eo_base_key_data_del(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key)
|
||||
{
|
||||
Eo_Generic_Data_Node *node;
|
||||
|
||||
if (!key) return;
|
||||
|
||||
EINA_INLIST_FOREACH(pd->generic_data, node)
|
||||
{
|
||||
if (!strcmp(node->key, key))
|
||||
{
|
||||
pd->generic_data = eina_inlist_remove(pd->generic_data,
|
||||
EINA_INLIST_GET(node));
|
||||
_eo_generic_data_node_free(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Weak reference. */
|
||||
|
||||
static inline size_t
|
||||
|
@ -996,7 +1143,7 @@ _eo_base_destructor(Eo *obj, Eo_Base_Data *pd)
|
|||
eo_parent_set(obj, NULL);
|
||||
}
|
||||
|
||||
_eo_generic_data_del_all(pd);
|
||||
_eo_generic_data_del_all(obj, pd);
|
||||
_wref_destruct(pd);
|
||||
_eo_callback_remove_all(pd);
|
||||
|
||||
|
|
|
@ -598,6 +598,9 @@ START_TEST(eo_generic_data)
|
|||
{
|
||||
eo_init();
|
||||
Eo *obj = eo_add(SIMPLE_CLASS, NULL);
|
||||
Eo *obj2 = eo_add(SIMPLE_CLASS, NULL);
|
||||
Eo *obj3 = eo_add(SIMPLE_CLASS, NULL);
|
||||
Eo *objtmp;
|
||||
void *data = NULL;
|
||||
|
||||
eo_key_data_set(obj, "test1", (void *) 1);
|
||||
|
@ -626,7 +629,37 @@ START_TEST(eo_generic_data)
|
|||
data = eo_key_data_get(obj, "test1");
|
||||
fail_if(data);
|
||||
|
||||
|
||||
|
||||
eo_key_obj_set(obj, "test1", obj2);
|
||||
objtmp = eo_key_obj_get(obj, "test1");
|
||||
fail_if(obj2 != objtmp);
|
||||
eo_key_obj_del(obj, "test1");
|
||||
objtmp = eo_key_obj_get(obj, "test1");
|
||||
fail_if(objtmp);
|
||||
|
||||
eo_key_obj_set(obj, "test1", obj2);
|
||||
eo_key_obj_set(obj, "test2", obj3);
|
||||
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_del(obj, "test2");
|
||||
objtmp = eo_key_obj_get(obj, "test2");
|
||||
fail_if(objtmp);
|
||||
|
||||
objtmp = eo_key_obj_get(obj, "test1");
|
||||
fail_if(obj2 != objtmp);
|
||||
eo_key_obj_del(obj, "test1");
|
||||
objtmp = eo_key_obj_get(obj, "test1");
|
||||
fail_if(objtmp);
|
||||
|
||||
eo_unref(obj);
|
||||
eo_unref(obj2);
|
||||
eo_unref(obj3);
|
||||
|
||||
eo_shutdown();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue