X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=include%2Fbabeltrace%2Fobject-internal.h;h=4efba28e8278f8b721c7f06a45794a307dc61ec9;hb=312c056ae3d374b253fa0cfe5ed576c0b0e5e569;hp=fb37d97a3bf485e4d0d2e291dffad5b768bdd5c6;hpb=78586d8a10bfb11d34d187697ae15e9255c6ddf4;p=babeltrace.git diff --git a/include/babeltrace/object-internal.h b/include/babeltrace/object-internal.h index fb37d97a..4efba28e 100644 --- a/include/babeltrace/object-internal.h +++ b/include/babeltrace/object-internal.h @@ -27,8 +27,11 @@ * SOFTWARE. */ +#include #include #include +#include +#include /** * All objects publicly exposed by Babeltrace APIs must contain this structure @@ -38,44 +41,85 @@ */ struct bt_object { struct bt_ref ref_count; - /* Class-specific release function. */ + /* Class-specific, optional release function. */ bt_object_release_func release; + /* Class-specific, optional "parent is owner" notification listener. */ + bt_object_release_func parent_is_owner_listener; /* @see doc/ref-counting.md */ struct bt_object *parent; + + /* + * True if this object is shared, that is, it uses reference + * counting. Only used in developer mode. + */ + bool is_shared; }; static inline -long bt_object_get_ref_count(const void *); -static inline -void bt_object_set_parent(void *, void *); +long bt_object_get_ref_count(const void *ptr) +{ + const struct bt_object *obj = ptr; -static + return obj->ref_count.count; +} + +static inline void bt_object_release(void *ptr) { struct bt_object *obj = ptr; - if (obj && obj->release && !bt_object_get_ref_count(obj)) { +#ifdef BT_LOGV + BT_LOGV("Releasing object: addr=%p, ref-count=%lu", ptr, + obj->ref_count.count); +#endif + + if (obj && obj->release && bt_object_get_ref_count(obj) == 0) { obj->release(obj); } } -static +static inline void generic_release(struct bt_object *obj) { if (obj->parent) { + struct bt_object *parent = obj->parent; + +#ifdef BT_LOGV + BT_LOGV("Releasing parented object: addr=%p, ref-count=%lu, " + "parent-addr=%p, parent-ref-count=%lu", + obj, obj->ref_count.count, + parent, parent->ref_count.count); +#endif + + if (obj->parent_is_owner_listener) { + /* + * Object has a chance to destroy itself here + * under certain conditions and notify its + * parent. At this point the parent is + * guaranteed to exist because it's not put yet. + */ + obj->parent_is_owner_listener(obj); + } + /* The release function will be invoked by the parent. */ - bt_put(obj->parent); + bt_put(parent); } else { bt_object_release(obj); } } static inline -struct bt_object *bt_object_get_parent(void *ptr) +struct bt_object *bt_object_borrow_parent(void *ptr) { struct bt_object *obj = ptr; - return ptr ? bt_get(obj->parent) : NULL; + return obj ? obj->parent : NULL; +} + +static inline +struct bt_object *bt_object_get_parent(void *ptr) +{ + return bt_get(bt_object_borrow_parent(ptr)); } static inline @@ -87,15 +131,33 @@ void bt_object_set_parent(void *child_ptr, void *parent) return; } +#ifdef BT_LOGV + BT_LOGV("Setting object's parent: addr=%p, parent-addr=%p", + child_ptr, parent); +#endif + /* * It is assumed that a "child" being "parented" is publicly reachable. * Therefore, a reference to its parent must be taken. The reference * to the parent will be released once the object's reference count * falls to zero. */ + BT_PUT(child->parent); child->parent = bt_get(parent); } +#ifdef BT_DEV_MODE +static inline +void _bt_object_set_is_shared(struct bt_object *obj, bool is_shared) +{ + obj->is_shared = is_shared; +} + +# define bt_object_set_is_shared _bt_object_set_is_shared +#else +# define bt_object_set_is_shared(_obj, _is_shared) +#endif + static inline void bt_object_init(void *ptr, bt_object_release_func release) { @@ -103,15 +165,16 @@ void bt_object_init(void *ptr, bt_object_release_func release) obj->release = release; obj->parent = NULL; + bt_object_set_is_shared(obj, true); bt_ref_init(&obj->ref_count, generic_release); } static inline -long bt_object_get_ref_count(const void *ptr) +void bt_object_set_parent_is_owner_listener(void *obj, + bt_object_release_func cb) { - const struct bt_object *obj = ptr; - - return obj->ref_count.count; + BT_ASSERT(obj); + ((struct bt_object *) obj)->parent_is_owner_listener = cb; } #endif /* BABELTRACE_OBJECT_INTERNAL_H */