From 856cf05f5cb178459577a1c1eb5e74fe461e1315 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Tue, 17 Apr 2012 13:38:41 +0000 Subject: [PATCH] Eobj: Added weak ref. SVN revision: 70269 --- legacy/eobj/lib/Eobj.h | 50 +++++++++++++++++++++++++++ legacy/eobj/lib/eobj.c | 34 ++++++++++++++++++ legacy/eobj/tests/eobj_test_general.c | 35 ++++++++++++++++++- 3 files changed, 118 insertions(+), 1 deletion(-) diff --git a/legacy/eobj/lib/Eobj.h b/legacy/eobj/lib/Eobj.h index f418693c1c..635829d735 100644 --- a/legacy/eobj/lib/Eobj.h +++ b/legacy/eobj/lib/Eobj.h @@ -431,6 +431,56 @@ EAPI extern const Eobj_Event_Description _EOBJ_EV_DEL; */ #define EOBJ_EV_DEL (&(_EOBJ_EV_DEL)) +/** + * @addtogroup Eobj_Weak_Ref Weak reference for Eobj objects. + * @{ + */ + +/** + * @struct _Eobj_Weak_Ref + * This is exposed for performance, please use eobj_weak_ref_get() when you + * actually want to get the refed object. + */ +struct _Eobj_Weak_Ref +{ + Eobj *obj; /**< The object being referenced. */ +}; + +/** + * @typedef Eobj_Weak_Ref + * Weak reference type for Eobj. + */ +typedef struct _Eobj_Weak_Ref Eobj_Weak_Ref; + +/** + * @brief Create a new weak reference to obj. + * @param obj The object being referenced. + * @return A new weak reference. + */ +EAPI Eobj_Weak_Ref *eobj_weak_ref_new(const Eobj *obj); + +/** + * @brief Free the weak reference passed. + * @param wref the weak reference to free. + */ +EAPI void eobj_weak_ref_free(Eobj_Weak_Ref *wref); + +/** + * @brief Get the referenced object from the weak reference. + * @param wref the weak reference to get the object from. + * @return The object referenced by wref. + */ +static inline Eobj * +eobj_weak_ref_get(const Eobj_Weak_Ref *wref) +{ + return wref->obj; +} + +/** + * @} + */ + + /** * @addtogroup Eobj_Composite_Objects Composite Objects. * @{ diff --git a/legacy/eobj/lib/eobj.c b/legacy/eobj/lib/eobj.c index e449976135..e449575844 100644 --- a/legacy/eobj/lib/eobj.c +++ b/legacy/eobj/lib/eobj.c @@ -829,6 +829,40 @@ eobj_ref_get(const Eobj *obj) return obj->refcount; } +/* Weak reference. */ +Eina_Bool +_eobj_weak_ref_cb(void *data, Eobj *obj __UNUSED__, const Eobj_Event_Description *desc __UNUSED__, void *event_info __UNUSED__) +{ + Eobj_Weak_Ref *wref = data; + wref->obj = NULL; + + return EINA_TRUE; +} + +EAPI Eobj_Weak_Ref * +eobj_weak_ref_new(const Eobj *_obj) +{ + Eobj *obj = (Eobj *) _obj; + Eobj_Weak_Ref *wref = calloc(1, sizeof(*wref)); + wref->obj = obj; + eobj_event_callback_add(obj, EOBJ_EV_DEL, _eobj_weak_ref_cb, wref); + + return wref; +} + +EAPI void +eobj_weak_ref_free(Eobj_Weak_Ref *wref) +{ + if (wref->obj) + { + eobj_event_callback_del_full(wref->obj, EOBJ_EV_DEL, _eobj_weak_ref_cb, + wref); + } + free(wref); +} + +/* EOF Weak reference. */ + EAPI void eobj_del(Eobj *obj) { diff --git a/legacy/eobj/tests/eobj_test_general.c b/legacy/eobj/tests/eobj_test_general.c index d92dde9e31..390cefd85b 100644 --- a/legacy/eobj/tests/eobj_test_general.c +++ b/legacy/eobj/tests/eobj_test_general.c @@ -13,8 +13,40 @@ START_TEST(eobj_simple) { eobj_init(); Eobj *obj = eobj_add(EOBJ_CLASS_BASE, NULL); - fail_if(obj); + + eobj_shutdown(); +} +END_TEST + +START_TEST(eobj_weak_reference) +{ + eobj_init(); + + Eobj *obj = eobj_add(SIMPLE_CLASS, NULL); + Eobj_Weak_Ref *wref = eobj_weak_ref_new(obj); + fail_if(!eobj_weak_ref_get(wref)); + + eobj_unref(obj); + fail_if(eobj_weak_ref_get(wref)); + + eobj_weak_ref_free(wref); + + obj = eobj_add(SIMPLE_CLASS, NULL); + wref = eobj_weak_ref_new(obj); + + eobj_ref(obj); + fail_if(!eobj_weak_ref_get(wref)); + + eobj_del(obj); + fail_if(eobj_weak_ref_get(wref)); + + eobj_unref(obj); + fail_if(eobj_weak_ref_get(wref)); + + eobj_weak_ref_free(wref); + + eobj_shutdown(); } END_TEST @@ -91,4 +123,5 @@ void eobj_test_general(TCase *tc) tcase_add_test(tc, eobj_generic_data); tcase_add_test(tc, eobj_op_errors); tcase_add_test(tc, eobj_simple); + tcase_add_test(tc, eobj_weak_reference); }