X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=include%2Fbabeltrace%2Fobject-internal.h;h=9859e329d36a34565bb86daedb75762387d8cacb;hb=36712f1d9ad9269638e493ca36a50979fe4da989;hp=4bf4def69c070f3182003d5e57feae19d2ad6f2d;hpb=7c56f3cc43c4a45c87a6edd3146885d7d1976856;p=babeltrace.git diff --git a/include/babeltrace/object-internal.h b/include/babeltrace/object-internal.h index 4bf4def6..9859e329 100644 --- a/include/babeltrace/object-internal.h +++ b/include/babeltrace/object-internal.h @@ -38,8 +38,10 @@ */ 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; }; @@ -57,7 +59,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,19 +73,44 @@ 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 @@ -90,12 +122,18 @@ 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); } @@ -109,4 +147,12 @@ void bt_object_init(void *ptr, bt_object_release_func release) 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) +{ + assert(obj); + ((struct bt_object *) obj)->parent_is_owner_listener = cb; +} + #endif /* BABELTRACE_OBJECT_INTERNAL_H */