X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=include%2Fbabeltrace%2Fobject-internal.h;h=4efba28e8278f8b721c7f06a45794a307dc61ec9;hp=e130a81e883d620cba525cffc28a4ffba2f90fcd;hb=312c056ae3d374b253fa0cfe5ed576c0b0e5e569;hpb=dc3fffef7b84cc4af1a7c99828fd57a106cd2257 diff --git a/include/babeltrace/object-internal.h b/include/babeltrace/object-internal.h index e130a81e..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,10 +41,18 @@ */ 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 @@ -57,7 +68,12 @@ 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); } } @@ -66,8 +82,27 @@ 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); } @@ -96,6 +131,11 @@ 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 @@ -106,6 +146,18 @@ void bt_object_set_parent(void *child_ptr, void *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) { @@ -113,7 +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 +void bt_object_set_parent_is_owner_listener(void *obj, + bt_object_release_func cb) +{ + BT_ASSERT(obj); + ((struct bt_object *) obj)->parent_is_owner_listener = cb; +} + #endif /* BABELTRACE_OBJECT_INTERNAL_H */