7 KiB
GstMiniObject
This document describes the design of the GstMiniObject
base class.
The GstMiniObject
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 withgst_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 LOCKABLE
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.