Add CONTRIBUTING.adoc
[deliverable/babeltrace.git] / doc / ref-counting.md
diff --git a/doc/ref-counting.md b/doc/ref-counting.md
deleted file mode 100644 (file)
index 32b8608..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-# Babeltrace Object Reference Counting and Lifetime
-
-This document covers the rationale behind the design of Babeltrace's object
-lifetime management.
-
-Starting from Babeltrace 2.x, all publicly exposed objects inherit a common
-base: bt_object. This base provides a number of facilities to all objects, chief
-amongst which are lifetime management functions.
-
-The reference count of all public objects is controlled by invoking
-the `bt_get()` and `bt_put()` functions which respectively
-increment and decrement an object's reference count.
-
-As far as lifetime management in concerned, Babeltrace makes a clear
-distinction between regular objects, which have a single parent, and root
-objects, which don't.
-
-## The Problem
-
-Let us consider a problematic case to illustrate the need for this
-distinction.
-
-A user of the CTF Writer library declares a Trace, which *has* a
-Stream Class (the declaration of a stream) and that Stream Class, in
-turn, *has* an Event Class (the declaration of an event).
-
-Nothing prevents this user from releasing his reference on any one of
-these objects in any order. However, all objects in the "Trace <->
-Stream <-> Event" hierarchy can be retrieved from any other.
-
-For instance, the user could discard his reference on both the Event
-Class and the Stream Class, only keeping a reference on the Trace.
-From this Trace reference, Stream Classes can be enumerated, providing
-the user with a new reference to the Stream Class he discarded
-earlier. Event Classes can also be enumerated from Stream Classes,
-providing the user with references to the individual Event Classes.
-
-Conversely, the user could also hold a reference to an Event Class and
-retrieve its parent Stream Class. The Trace, in turn, can then be
-retrieved from the Stream Class.
-
-This example illustrates what could be interpreted as a circular
-reference dependency existing between these objects. Of course, if the
-objects in such a scenario were to hold references to each other (in
-both directions), we would be in presence of a circular ownership
-resulting in a leak of both objects as their reference counts would
-never reach zero.
-
-Nonetheless, the API must offer the guarantee that holding a node to any node of
-the graph keeps all other reachable nodes alive.
-
-## The Solution
-
-The scheme employed in Babeltrace to break this cycle consists in the
-"children" holding *Reverse Component References* to their parents.  That
-is, in the context of CTF-IR, that Event Classes hold a reference to
-their Stream Class and Stream Classes hold a reference to their Trace.
-
-On the other hand, parents hold *Claiming Aggregation References* to
-their children. A claiming aggregation reference means that the
-object being referenced should not be deleted as long as the reference
-still exists. In this respect, it can be said that parents truly hold the
-ownership of their children, since they control their lifetime. Conversely,
-the reference counting mechanism is leveraged by children to notify parents
-that no other child indirectly exposes the parent.
-
-When a parented object's reference count reaches zero, it invokes
-`bt_put()` on its parent and does **not** free itself. However, from that
-point, the object depends on its parent to signal the moment when it
-can be safely reclaimed.
-
-The invocation of `bt_put()` by the last children holding a reference to its
-parent might trigger a cascade of `bt_put()` from child to parent. Eventually,
-a **root** object is reached. At that point, if this orphaned object's
-reference count reaches zero, the object will invoke the `destroy()` method
-defined by every one of its children as part of their base `struct bt_object`.
-The key point here is that the cascade of `destroy()` will necessarily originate
-from the root and propagate in pre-order to the children. These children will
-propagate the destruction to their own children before reclaiming their own
-memory. This ensures that a node's pointer to its parent is *always* valid
-since the parent has the responsibility of tearing-down their children before
-cleaning themselves-up.
-
-Assuming a reference to an object is *acquired* by calling `bt_get()` while its
-reference count is zero, the object will, in turn, acquire a reference on its
-parent using `bt_get()`. At that point, the child can be thought of as having
-converted its weak reference to its parent into a regular reference. That is
-why this reference is referred to as a *claiming* aggregation reference.
-
-## Caveats
-
-This scheme imposes a number of strict rules defining the relation
-between objects:
-
-  * Objects may only have one parent,
-  * Objects, beside the root, are only retrievable from their direct parent or
-    children.
-
-## Walking through an example
-
-The initial situation is rather simple. **User A** is holding a reference to a
-trace, **TC1**. As per the rules previously enounced, Stream Classes **SC1** and
-**SC2** don't hold a reference to **TC1** since their own reference counts are
-zero. The same holds true for **EC1**, **EC2** and **EC3** with respect to
-**SC1** and **SC2**.
-
-![](images/bt-ref01.svg)
-
-In this second step, we can see that User A has acquired a reference on **SC2**
-through the Trace, **TC1**.
-
-The Stream Class' reference count transitions from zero to one, triggering the
-acquisition of a strong reference on **TC1** from **SC2**.
-
-Hence, at this point, the Trace's ownership is shared by **User A** and
-**SC2**.
-
-![](images/bt-ref02.svg)
-
-Next, **User A** acquires a reference on the **EC3** Event Class through its
-parent Stream Class, **SC2**. Again, the transition of an object's reference
-count from 0 to 1 triggers the acquisition of a reference on its parent.
-
-Note that SC2's reference count was incremented to 2. The Trace's reference
-count remains unchanged.
-
-![](images/bt-ref03.svg)
-
-**User A** decides to drop its reference on **SC2**. **SC2**'s reference count
-returns back to 1, everything else remaining unchanged.
-
-![](images/bt-ref04.svg)
-
-**User A** can then decide to drop its reference on the Trace. This results in
-a reversal of the initial situation: **User A** now owns an event, **EC3**,
-which is keeping everything else alive and reachable.
-
-![](images/bt-ref05.svg)
-
-If another object, **User B**, enters the picture and acquires a reference on
-the **SC1** Stream Class, we see that **SC1**'s reference count
-transitioned from 0 to 1, triggering the acquisition of a reference on **TC1**.
-
-![](images/bt-ref06.svg)
-
-**User B** hands off a reference to **EC1**, acquired through **SC1**, to
-another object, **User C**. The acquisition of a reference on **EC1**, which
-transitions from 0 to 1, triggers the acquisition of a reference on its parent,
-**SC1**.
-
-![](images/bt-ref07.svg)
-
-At some point, **User A** releases its reference on **EC3**. Since **EC3**'s
-reference count transitions to zero, it releases its reference on **SC2**.
-**SC2**'s reference count, in turn, reaches zero and it releases its reference
-to **TC1**.
-
-**TC1**'s reference count is now 1 and no further action is taken.
-
-![](images/bt-ref08.svg)
-
-**User B** releases its reference on **SC1**. **User C** becomes the sole owner
-of the whole hierarchy through his ownership of **EC1**.
-
-![](images/bt-ref09.svg)
-
-Finally, **User C** releases his ownership of **EC1**, triggering the release of
-the whole hierarchy. We will walk through the reclamation of the whole graph.
-
-Mirroring what happened when **User A** released its last reference on **EC3**,
-the release of **EC1** by **User C** causes its reference count to fall to zero.
-
-This transition to zero causes **EC1** to release its reference on **SC1**.
-**SC1**'s reference count reaching zero causes it to release its reference on
-**TC1**.
-
-![](images/bt-ref10.svg)
-
-Since the reference count of **TC1**, a root object, has reached zero, it
-invokes the `destroy()` method on its children. This method is recursive and
-causes the Stream Classes to call the `destroy()` method on their Event Classes.
-
-The Event Classes are reached and, having no children of their own, are
-reclaimed.
-
-![](images/bt-ref11.svg)
-
-The Stream Classes having destroyed their children, are then reclaimed by the
-Trace.
-
-![](images/bt-ref12.svg)
-
-Finally, the Stream Classes having been reclaimed, **TC1** is reclaimed.
-
-![](images/bt-ref13.svg)
This page took 0.025087 seconds and 5 git commands to generate.