Port: __STRINGIFY exists on Cygwin
[babeltrace.git] / include / babeltrace / object-internal.h
index afba44790723d212465bb9e423278e3ffb647970..9859e329d36a34565bb86daedb75762387d8cacb 100644 (file)
  */
 
 #include <babeltrace/ref-internal.h>
+#include <babeltrace/ref.h>
 
 /**
  * All objects publicly exposed by Babeltrace APIs must contain this structure
  * as their first member. This allows the unification of all ref counting
- * mechanism and may be used to provide more base functionality to all
+ * mechanisms and may be used to provide more base functionality to all
  * objects.
  */
 struct bt_object {
        struct bt_ref ref_count;
+       /* 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;
 };
 
 static inline
-void bt_object_init(void *obj, bt_object_release_func release)
+long bt_object_get_ref_count(const void *ptr)
 {
-       bt_ref_init(&((struct bt_object *) obj)->ref_count, release);
+       const struct bt_object *obj = ptr;
+
+       return obj->ref_count.count;
+}
+
+static inline
+void bt_object_release(void *ptr)
+{
+       struct bt_object *obj = ptr;
+
+#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 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(parent);
+       } else {
+               bt_object_release(obj);
+       }
+}
+
+static inline
+struct bt_object *bt_object_borrow_parent(void *ptr)
+{
+       struct bt_object *obj = ptr;
+
+       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
+void bt_object_set_parent(void *child_ptr, void *parent)
+{
+       struct bt_object *child = child_ptr;
+
+       if (!child) {
+               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);
+}
+
+static inline
+void bt_object_init(void *ptr, bt_object_release_func release)
+{
+       struct bt_object *obj = ptr;
+
+       obj->release = release;
+       obj->parent = NULL;
+       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 */
This page took 0.024481 seconds and 4 git commands to generate.