forked from enlightenment/efl
Eobj: Add named (by obj ptr) ref - xref.
SVN revision: 70273
This commit is contained in:
parent
69afa9d2ad
commit
d6146c132e
|
@ -399,6 +399,25 @@ EAPI void eobj_unref(Eobj *obj);
|
|||
*/
|
||||
EAPI int eobj_ref_get(const Eobj *obj);
|
||||
|
||||
#define eobj_xref(obj, ref_obj) eobj_xref_internal(obj, ref_obj, __FILE__, __LINE__)
|
||||
|
||||
/**
|
||||
* @brief Increment the object's reference count by 1.
|
||||
* @param obj the object to work on.
|
||||
* @return The object passed.
|
||||
*
|
||||
* @see eobj_xunref()
|
||||
*/
|
||||
EAPI Eobj *eobj_xref_internal(Eobj *obj, const Eobj *ref_obj, const char *file, int line);
|
||||
|
||||
/**
|
||||
* @brief Decrement the object's reference count by 1 and free it if needed.
|
||||
* @param obj the object to work on.
|
||||
*
|
||||
* @see eobj_xref_internal()
|
||||
*/
|
||||
EAPI void eobj_xunref(Eobj *obj, const Eobj *ref_obj);
|
||||
|
||||
/**
|
||||
* @brief Delete the object passed (disregarding ref count).
|
||||
* @param obj the object to work on.
|
||||
|
|
|
@ -26,6 +26,10 @@ struct _Eobj {
|
|||
const Eobj_Class *klass;
|
||||
void *data_blob;
|
||||
int refcount;
|
||||
#ifndef NDEBUG
|
||||
Eina_Inlist *xrefs;
|
||||
#endif
|
||||
|
||||
Eina_List *composite_objects;
|
||||
|
||||
Eina_Inlist *callbacks;
|
||||
|
@ -755,6 +759,63 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EINA_INLIST;
|
||||
const Eobj *ref_obj;
|
||||
const char *file;
|
||||
int line;
|
||||
} Eobj_Xref_Node;
|
||||
|
||||
EAPI Eobj *
|
||||
eobj_xref_internal(Eobj *obj, const Eobj *ref_obj, const char *file, int line)
|
||||
{
|
||||
eobj_ref(obj);
|
||||
|
||||
#ifndef NDEBUG
|
||||
Eobj_Xref_Node *xref = calloc(1, sizeof(*xref));
|
||||
xref->ref_obj = ref_obj;
|
||||
xref->file = file;
|
||||
xref->line = line;
|
||||
|
||||
/* FIXME: Make it sorted. */
|
||||
obj->xrefs = eina_inlist_prepend(obj->xrefs, EINA_INLIST_GET(xref));
|
||||
#else
|
||||
(void) ref_obj;
|
||||
(void) file;
|
||||
(void) line;
|
||||
#endif
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
eobj_xunref(Eobj *obj, const Eobj *ref_obj)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
Eobj_Xref_Node *xref = NULL;
|
||||
EINA_INLIST_FOREACH(obj->xrefs, xref)
|
||||
{
|
||||
if (xref->ref_obj == ref_obj)
|
||||
break;
|
||||
}
|
||||
|
||||
if (xref)
|
||||
{
|
||||
obj->xrefs = eina_inlist_remove(obj->xrefs, EINA_INLIST_GET(xref));
|
||||
free(xref);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("ref_obj (%p) does not reference obj (%p). Aborting unref.", ref_obj, obj);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
(void) ref_obj;
|
||||
#endif
|
||||
eobj_unref(obj);
|
||||
}
|
||||
|
||||
EAPI Eobj *
|
||||
eobj_ref(Eobj *obj)
|
||||
{
|
||||
|
@ -804,6 +865,17 @@ eobj_unref(Eobj *obj)
|
|||
obj->kls_itr = nitr;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* If for some reason it's not empty, clear it. */
|
||||
while (obj->xrefs)
|
||||
{
|
||||
WRN("obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.");
|
||||
Eina_Inlist *nitr = nitr->next;
|
||||
free(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eobj_Kls_Itr_Node));
|
||||
obj->xrefs = nitr;
|
||||
}
|
||||
#endif
|
||||
|
||||
Eina_List *itr, *itr_n;
|
||||
Eobj *emb_obj;
|
||||
EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj)
|
||||
|
|
|
@ -19,6 +19,45 @@ START_TEST(eobj_simple)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(eobj_xrefs)
|
||||
{
|
||||
eobj_init();
|
||||
Eobj *obj = eobj_add(SIMPLE_CLASS, NULL);
|
||||
Eobj *obj2 = eobj_add(SIMPLE_CLASS, NULL);
|
||||
Eobj *obj3 = eobj_add(SIMPLE_CLASS, NULL);
|
||||
|
||||
eobj_xref(obj, obj2);
|
||||
fail_if(eobj_ref_get(obj) != 2);
|
||||
eobj_xref(obj, obj3);
|
||||
fail_if(eobj_ref_get(obj) != 3);
|
||||
|
||||
eobj_xunref(obj, obj2);
|
||||
fail_if(eobj_ref_get(obj) != 2);
|
||||
eobj_xunref(obj, obj3);
|
||||
fail_if(eobj_ref_get(obj) != 1);
|
||||
|
||||
#ifndef NDEBUG
|
||||
eobj_xunref(obj, obj3);
|
||||
fail_if(eobj_ref_get(obj) != 1);
|
||||
|
||||
eobj_xref(obj, obj2);
|
||||
fail_if(eobj_ref_get(obj) != 2);
|
||||
|
||||
eobj_xunref(obj, obj3);
|
||||
fail_if(eobj_ref_get(obj) != 2);
|
||||
|
||||
eobj_xunref(obj, obj2);
|
||||
fail_if(eobj_ref_get(obj) != 1);
|
||||
#endif
|
||||
|
||||
eobj_unref(obj);
|
||||
eobj_unref(obj2);
|
||||
eobj_unref(obj3);
|
||||
|
||||
eobj_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(eobj_weak_reference)
|
||||
{
|
||||
eobj_init();
|
||||
|
@ -161,4 +200,5 @@ void eobj_test_general(TCase *tc)
|
|||
tcase_add_test(tc, eobj_op_errors);
|
||||
tcase_add_test(tc, eobj_simple);
|
||||
tcase_add_test(tc, eobj_weak_reference);
|
||||
tcase_add_test(tc, eobj_xrefs);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue