mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-12 19:36:38 +00:00
200 lines
7 KiB
Markdown
200 lines
7 KiB
Markdown
# 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.
|
||
|
||
``` c
|
||
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.
|
||
|
||
``` c
|
||
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.
|
||
|
||
``` c
|
||
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 `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.
|