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);
|
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).
|
* @brief Delete the object passed (disregarding ref count).
|
||||||
* @param obj the object to work on.
|
* @param obj the object to work on.
|
||||||
|
|
|
@ -26,6 +26,10 @@ struct _Eobj {
|
||||||
const Eobj_Class *klass;
|
const Eobj_Class *klass;
|
||||||
void *data_blob;
|
void *data_blob;
|
||||||
int refcount;
|
int refcount;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
Eina_Inlist *xrefs;
|
||||||
|
#endif
|
||||||
|
|
||||||
Eina_List *composite_objects;
|
Eina_List *composite_objects;
|
||||||
|
|
||||||
Eina_Inlist *callbacks;
|
Eina_Inlist *callbacks;
|
||||||
|
@ -755,6 +759,63 @@ fail:
|
||||||
return NULL;
|
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 *
|
EAPI Eobj *
|
||||||
eobj_ref(Eobj *obj)
|
eobj_ref(Eobj *obj)
|
||||||
{
|
{
|
||||||
|
@ -804,6 +865,17 @@ eobj_unref(Eobj *obj)
|
||||||
obj->kls_itr = nitr;
|
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;
|
Eina_List *itr, *itr_n;
|
||||||
Eobj *emb_obj;
|
Eobj *emb_obj;
|
||||||
EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj)
|
EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj)
|
||||||
|
|
|
@ -19,6 +19,45 @@ START_TEST(eobj_simple)
|
||||||
}
|
}
|
||||||
END_TEST
|
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)
|
START_TEST(eobj_weak_reference)
|
||||||
{
|
{
|
||||||
eobj_init();
|
eobj_init();
|
||||||
|
@ -161,4 +200,5 @@ void eobj_test_general(TCase *tc)
|
||||||
tcase_add_test(tc, eobj_op_errors);
|
tcase_add_test(tc, eobj_op_errors);
|
||||||
tcase_add_test(tc, eobj_simple);
|
tcase_add_test(tc, eobj_simple);
|
||||||
tcase_add_test(tc, eobj_weak_reference);
|
tcase_add_test(tc, eobj_weak_reference);
|
||||||
|
tcase_add_test(tc, eobj_xrefs);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue