| GstMiniObject |
| ------------- |
| |
| This document describes the design of the miniobject base class. |
| |
| The miniobject abstract base class is used to construct lightweight refcounted |
| and boxed types that are frequently created and destroyed. |
| |
| Requirements |
| ~~~~~~~~~~~~ |
| |
| - Be lightweight |
| - Refcounted |
| - I must be possible to control access to the object, ie. when the object is |
| readable and writable. |
| - Subclasses must be able to use their own allocator for the memory. |
| |
| |
| Usage |
| ~~~~~ |
| |
| Users of the GstMiniObject infrastructure will need to define a structure that |
| includes the GstMiniObject structure as the first field. |
| |
| struct { |
| GstMiniObject mini_object; |
| |
| /* my fields */ |
| ... |
| } MyObject |
| |
| The subclass should then implement a constructor method where it allocates the |
| memory for its structure and initializes the miniobject structure with |
| gst_mini_object_init(). Copy and Free functions are provided to the |
| gst_mini_object_init() function. |
| |
| MyObject * |
| my_object_new() |
| { |
| MyObject *res = g_slice_new (MyObject); |
| |
| gst_mini_object_init (GST_MINI_OBJECT_CAST (res), 0, |
| MY_TYPE_OBJECT, |
| (GstMiniObjectCopyFunction) _my_object_copy, |
| (GstMiniObjectDisposeFunction) NULL, |
| (GstMiniObjectFreeFunction) _my_object_free); |
| |
| /* other init */ |
| ..... |
| |
| return res; |
| } |
| |
| The Free function is responsible for freeing the allocated memory for |
| the structure. |
| |
| static void |
| _my_object_free (MyObject *obj) |
| { |
| /* other cleanup */ |
| ... |
| |
| g_slice_free (MyObject, obj); |
| } |
| |
| |
| Lifecycle |
| ~~~~~~~~~ |
| |
| GstMiniObject is refcounted. When a GstMiniObject is first created, |
| it has a refcount of 1. |
| |
| Each variable holding a reference to a GstMiniObject is responsible for |
| updating the refcount. This includes incrementing the refcount with |
| gst_mini_object_ref() when a reference is kept to a miniobject or |
| gst_mini_object_unref() when a reference is released. |
| |
| When the refcount reaches 0, and thus no objects hold a reference to the |
| miniobject anymore, we can free the miniobject. |
| |
| When freeing the miniobject, first the GstMiniObjectDisposeFunction is called. |
| This function is allowed to revive the object again by incrementing the |
| refcount, in which case it should return FALSE from the dispose function. The |
| dispose function is used by GstBuffer to revive the buffer back into the |
| GstBufferPool when needed. |
| |
| When the dispose function returns TRUE, the GstMiniObjectFreeFunction will be |
| called and the miniobject will be freed. |
| |
| |
| Copy |
| ~~~~ |
| |
| A miniobject can be copied with gst_mini_object_copy(). This function will |
| call the custom copy function that was provided when registering the new |
| GstMiniObject subclass. |
| |
| The copy function should try to preserve as much info from the original object |
| as possible. |
| |
| The new copy should be writable. |
| |
| |
| Access management |
| ~~~~~~~~~~~~~~~~~ |
| |
| GstMiniObject can be shared between multiple threads. It is important that when |
| a thread writes to a GstMiniObject that the other threads don't not see the |
| changes. |
| |
| To avoid exposing changes from one thread to another thread, the miniobjects |
| are managed in a Copy-On-Write way. A copy is only made when it is known that |
| the object is shared between multiple objects or threads. |
| |
| There are 2 methods implemented for controlling access to the miniobject. |
| |
| - A first method relies on the refcount of the object to control writability. |
| Objects using this method have the LOCKABLE flag unset. |
| |
| - A second method relies on a separate counter for controlling |
| the access to the object. Objects using this method have the LOCKABLE flag |
| set. |
| |
| You can check if an object is writable with gst_mini_object_is_writable() and |
| you can make any miniobject writable with gst_mini_object_make_writable(). |
| This will create a writable copy when the object was not writable. |
| |
| |
| non-LOCKABLE GstMiniObjects |
| --------------------------- |
| |
| These GstMiniObjects have the LOCKABLE flag unset. They use the refcount value |
| to control writability of the object. |
| |
| When the refcount of the miniobject is > 1, the objects it referenced by at |
| least 2 objects and is thus considered unwritable. A copy must be made before a |
| modification to the object can be done. |
| |
| Using the refcount to control writability is problematic for many language |
| bindings that can keep additional references to the objects. This method is |
| mainly for historical reasons until all users of the miniobjects are |
| converted to use the LOCAKBLE flag. |
| |
| |
| LOCKABLE GstMiniObjects |
| ----------------------- |
| |
| These GstMiniObjects have the LOCKABLE flag set. They use a separate counter |
| for controlling writability and access to the object. |
| |
| It consists of 2 components: |
| |
| * exclusive counter |
| |
| Each object that wants to keep a reference to a GstMiniObject and doesn't want to |
| see the changes from other owners of the same GstMiniObject needs to lock the |
| GstMiniObject in EXCLUSIVE mode, which will increase the exclusive counter. |
| |
| The exclusive counter counts the amount of objects that share this |
| GstMiniObject. The counter is initially 0, meaning that the object is not shared with |
| any object. |
| |
| When a reference to a GstMiniObject release, both the ref count and the |
| exclusive counter will be decreased with gst_mini_object_unref() and |
| gst_mini_object_unlock () respectively. |
| |
| * locking |
| |
| All read and write access must be performed between a gst_mini_object_lock() and |
| gst_mini_object_unlock() pair with the requested access method. |
| |
| A gst_mini_object_lock() can fail when a WRITE lock is requested and the exclusive |
| counter is > 1. Indeed a GstMiniObject object with an exclusive counter > 1 is |
| locked EXCLUSIVELY by at least 2 objects and is therefore not writable. |
| |
| Once the GstMiniObject is locked with a certain access mode, it can be recursively |
| locked with the same or narrower access mode. For example, first locking the |
| GstMiniObject in READWRITE mode allows you to recusively lock the |
| GstMiniObject in |
| READWRITE, READ and WRITE mode. Memory locked in READ mode cannot be locked |
| recursively in WRITE or READWRITE mode. |
| |
| Note that multiple threads can READ lock the GstMiniObject concurrently but cannot |
| lock the object in WRITE mode because the exclusive counter must be > 1. |
| |
| All calls to gst_mini_object_lock() need to be paired with one |
| gst_mini_object_unlock() call with the same access mode. When the last refcount |
| of the object is removed, there should be no more outstanding locks. |
| |
| Note that a shared counter of both 0 and 1 leaves the GstMiniObject writable. The |
| reason is to make it easy to create and pass ownership of the GstMiniObject to |
| another object while keeping it writable. When the GstMiniObject is |
| created with a shared count of 0, it is writable. When the GstMiniObject is then |
| added to another object, the shared count is incremented to 1 and the |
| GstMiniObject remains writable. The 0 share counter has a similar purpose as the floating |
| reference in GObject. |
| |
| |
| Weak references |
| ~~~~~~~~~~~~~~~ |
| |
| GstMiniObject has support for weak references. A callback will be called when |
| the object is freed for all registered weak references. |
| |
| |
| QData |
| ~~~~~ |
| |
| Extra data can be associated with a GstMiniObject by using the QData API. |