2016-12-05 21:12:24 +00:00
|
|
|
|
# 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
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
Users of the `GstMiniObject` infrastructure will need to define a
|
|
|
|
|
structure that includes the `GstMiniObject` structure as the first field.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
|
|
|
|
``` 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
|
2016-12-28 05:11:56 +00:00
|
|
|
|
structure with `gst_mini_object_init()`. Copy and Free functions are
|
|
|
|
|
provided to the `gst_mini_object_init()` function.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
|
|
|
|
``` 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
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
`GstMiniObject` is refcounted. When a `GstMiniObject` is first created, it
|
2016-12-05 21:12:24 +00:00
|
|
|
|
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
|
2016-12-28 05:11:56 +00:00
|
|
|
|
`gst_mini_object_ref()` when a reference is kept to a miniobject or
|
|
|
|
|
`gst_mini_object_unref()` when a reference is released.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
|
|
|
|
When the refcount reaches 0, and thus no objects hold a reference to the
|
|
|
|
|
miniobject anymore, we can free the miniobject.
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
When freeing the miniobject, first the `GstMiniObjectDisposeFunction` is
|
2016-12-05 21:12:24 +00:00
|
|
|
|
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
|
2016-12-28 05:11:56 +00:00
|
|
|
|
the buffer back into the `GstBufferPool` when needed.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
When the dispose function returns TRUE, the `GstMiniObjectFreeFunction`
|
2016-12-05 21:12:24 +00:00
|
|
|
|
will be called and the miniobject will be freed.
|
|
|
|
|
|
|
|
|
|
## Copy
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
A miniobject can be copied with `gst_mini_object_copy()`. This function
|
2016-12-05 21:12:24 +00:00
|
|
|
|
will call the custom copy function that was provided when registering
|
2016-12-28 05:11:56 +00:00
|
|
|
|
the new `GstMiniObject` subclass.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
|
|
|
|
The copy function should try to preserve as much info from the original
|
|
|
|
|
object as possible.
|
|
|
|
|
|
|
|
|
|
The new copy should be writable.
|
|
|
|
|
|
|
|
|
|
## Access management
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
`GstMiniObject` can be shared between multiple threads. It is important
|
|
|
|
|
that when a thread writes to a `GstMiniObject` that the other threads
|
2016-12-05 21:12:24 +00:00
|
|
|
|
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.
|
2016-12-28 05:11:56 +00:00
|
|
|
|
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()`.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
This will create a writable copy when the object was not writable.
|
|
|
|
|
|
|
|
|
|
### non-LOCKABLE GstMiniObjects
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
These `GstMiniObjects` have the LOCKABLE flag unset. They use the refcount value
|
2016-12-05 21:12:24 +00:00
|
|
|
|
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
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
These `GstMiniObjects` have the LOCKABLE flag set. They use a separate counter
|
2016-12-05 21:12:24 +00:00
|
|
|
|
for controlling writability and access to the object.
|
|
|
|
|
|
|
|
|
|
It consists of 2 components:
|
|
|
|
|
|
|
|
|
|
#### exclusive counter
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
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.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
|
|
|
|
The exclusive counter counts the amount of objects that share this
|
2016-12-28 05:11:56 +00:00
|
|
|
|
`GstMiniObject`. The counter is initially 0, meaning that the object is not
|
|
|
|
|
shared with any object.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
When a reference to a `GstMiniObject` release, both the ref count and the
|
2016-12-05 21:12:24 +00:00
|
|
|
|
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
|
2016-12-28 05:11:56 +00:00
|
|
|
|
exclusive counter is > 1. Indeed a `GstMiniObject` object with an exclusive
|
2016-12-05 21:12:24 +00:00
|
|
|
|
counter > 1 is locked EXCLUSIVELY by at least 2 objects and is therefore not
|
|
|
|
|
writable.
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
Once the `GstMiniObject` is locked with a certain access mode, it can be
|
2016-12-05 21:12:24 +00:00
|
|
|
|
recursively locked with the same or narrower access mode. For example, first
|
2016-12-28 05:11:56 +00:00
|
|
|
|
locking the `GstMiniObject` in READWRITE mode allows you to recusively lock the
|
2016-12-05 21:12:24 +00:00
|
|
|
|
GstMiniObject in READWRITE, READ and WRITE mode. Memory locked in READ mode
|
|
|
|
|
cannot be locked recursively in WRITE or READWRITE mode.
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
Note that multiple threads can READ lock the `GstMiniObject` concurrently but
|
2016-12-05 21:12:24 +00:00
|
|
|
|
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.
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
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
|
2016-12-05 21:12:24 +00:00
|
|
|
|
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
|
2016-12-28 05:11:56 +00:00
|
|
|
|
reference in `GObject`.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
|
|
|
|
## Weak references
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
`GstMiniObject` has support for weak references. A callback will be called
|
2016-12-05 21:12:24 +00:00
|
|
|
|
when the object is freed for all registered weak references.
|
|
|
|
|
|
|
|
|
|
## QData
|
|
|
|
|
|
2016-12-28 05:11:56 +00:00
|
|
|
|
Extra data can be associated with a `GstMiniObject` by using the `QData`
|
2016-12-05 21:12:24 +00:00
|
|
|
|
API.
|