Commit 3b16efa1 authored by Wim Taymans's avatar Wim Taymans

miniobject: add lock functionality to GstMiniObject

Move the locking methods from GstMemory to GstMiniObject.
Add a miniobject flag to enable LOCKABLE objects. LOCKABLE objects can
use the lock/unlock API to control the access to the object.
Add a minobject flag that allows you to lock an object in readonly mode.
Modify the _is_writable() method to check the shared counter for LOCKABLE
objects. This allows us to control writability separately from the refcount for
LOCKABLE objects.
parent afd5db3c
......@@ -1339,7 +1339,7 @@ gst_memory_new_wrapped
gst_memory_ref
gst_memory_unref
gst_memory_is_exclusive
gst_memory_is_writable
gst_memory_get_sizes
gst_memory_resize
......
......@@ -265,8 +265,10 @@ _replace_memory (GstBuffer * buffer, guint len, guint idx, guint length,
/* unref old memory */
for (i = idx; i < end; i++) {
gst_memory_unlock (GST_BUFFER_MEM_PTR (buffer, i), GST_LOCK_FLAG_EXCLUSIVE);
gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
GstMemory *old = GST_BUFFER_MEM_PTR (buffer, i);
gst_memory_unlock (old, GST_LOCK_FLAG_EXCLUSIVE);
gst_memory_unref (old);
}
if (mem != NULL) {
......@@ -536,7 +538,7 @@ _gst_buffer_free (GstBuffer * buffer)
static void
gst_buffer_init (GstBufferImpl * buffer, gsize size)
{
gst_mini_object_init (GST_MINI_OBJECT_CAST (buffer), _gst_buffer_type,
gst_mini_object_init (GST_MINI_OBJECT_CAST (buffer), 0, _gst_buffer_type,
(GstMiniObjectCopyFunction) _gst_buffer_copy,
(GstMiniObjectDisposeFunction) _gst_buffer_dispose,
(GstMiniObjectFreeFunction) _gst_buffer_free);
......@@ -818,7 +820,7 @@ _get_mapped (GstBuffer * buffer, guint idx, GstMapInfo * info,
* any call that modifies the memory in @buffer.
*
* Since this call does not influence the refcount of the memory,
* gst_memory_is_exclusive() can be used to check if @buffer is the sole owner
* gst_memory_is_writable() can be used to check if @buffer is the sole owner
* of the returned memory.
*
* Returns: (transfer none): the #GstMemory at @idx.
......@@ -924,6 +926,7 @@ gst_buffer_replace_memory_range (GstBuffer * buffer, guint idx, gint length,
g_return_if_fail (GST_IS_BUFFER (buffer));
g_return_if_fail (gst_buffer_is_writable (buffer));
len = GST_BUFFER_MEM_LEN (buffer);
g_return_if_fail ((len == 0 && idx == 0 && length == -1) ||
(length == -1 && idx < len) || (length > 0 && length + idx <= len));
......@@ -1230,7 +1233,7 @@ gst_buffer_resize_range (GstBuffer * buffer, guint idx, gint length,
left = MIN (bsize - offset, size);
if (offset != 0 || left != bsize) {
if (gst_memory_is_exclusive (mem)) {
if (gst_memory_is_writable (mem)) {
gst_memory_resize (mem, offset, left);
} else {
GstMemory *newmem;
......
......@@ -319,9 +319,8 @@ void gst_buffer_unmap (GstBuffer *buffer, GstMapInfo *info)
* Increases the refcount of the given buffer by one.
*
* Note that the refcount affects the writeability
* of @buf and its metadata, see gst_buffer_is_writable() and
* gst_buffer_is_metadata_writable(). It is
* important to note that keeping additional references to
* of @buf and its metadata, see gst_buffer_is_writable().
* It is important to note that keeping additional references to
* GstBuffer instances can potentially increase the number
* of memcpy operations in a pipeline.
*
......@@ -426,10 +425,9 @@ void gst_buffer_copy_into (GstBuffer *dest, GstBuffer *src
* gst_buffer_is_writable:
* @buf: a #GstBuffer
*
* Tests if you can safely write data into a buffer's data array or validly
* modify the caps and timestamp metadata. Metadata in a GstBuffer is always
* writable, but it is only safe to change it when there is only one owner
* of the buffer - ie, the refcount is 1.
* Tests if you can safely write to a buffer's metadata or its memory array.
* It is only safe to change buffer metadata when the current reference is
* writable, i.e. nobody can see the modifications you will make.
*/
#define gst_buffer_is_writable(buf) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (buf))
/**
......
......@@ -103,7 +103,7 @@ _gst_buffer_list_free (GstBufferList * list)
static void
gst_buffer_list_init (GstBufferList * list, guint asize)
{
gst_mini_object_init (GST_MINI_OBJECT_CAST (list), _gst_buffer_list_type,
gst_mini_object_init (GST_MINI_OBJECT_CAST (list), 0, _gst_buffer_list_type,
(GstMiniObjectCopyFunction) _gst_buffer_list_copy, NULL,
(GstMiniObjectFreeFunction) _gst_buffer_list_free);
......
......@@ -185,7 +185,7 @@ _gst_caps_free (GstCaps * caps)
static void
gst_caps_init (GstCaps * caps)
{
gst_mini_object_init (GST_MINI_OBJECT_CAST (caps), _gst_caps_type,
gst_mini_object_init (GST_MINI_OBJECT_CAST (caps), 0, _gst_caps_type,
(GstMiniObjectCopyFunction) _gst_caps_copy, NULL,
(GstMiniObjectFreeFunction) _gst_caps_free);
......
......@@ -262,7 +262,7 @@ gst_caps_copy (const GstCaps * caps)
* @caps: a #GstCaps
*
* Tests if you can safely modify @caps. It is only safe to modify caps when
* there is only one owner of the caps - ie, the refcount is 1.
* there is only one owner of the caps - ie, the object is writable.
*/
#define gst_caps_is_writable(caps) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (caps))
......
......@@ -261,7 +261,7 @@ _gst_event_copy (GstEvent * event)
static void
gst_event_init (GstEventImpl * event, GstEventType type)
{
gst_mini_object_init (GST_MINI_OBJECT_CAST (event), _gst_event_type,
gst_mini_object_init (GST_MINI_OBJECT_CAST (event), 0, _gst_event_type,
(GstMiniObjectCopyFunction) _gst_event_copy, NULL,
(GstMiniObjectFreeFunction) _gst_event_free);
......
......@@ -133,8 +133,6 @@ _gst_memory_copy (GstMemory * mem)
static void
_gst_memory_free (GstMemory * mem)
{
/* there should be no outstanding mappings */
g_return_if_fail ((g_atomic_int_get (&mem->state) & LOCK_MASK) < 4);
mem->allocator->info.mem_free (mem);
}
......@@ -145,15 +143,13 @@ _default_mem_init (GstMemoryDefault * mem, GstMemoryFlags flags,
gsize maxsize, gsize offset, gsize size, gsize align,
gpointer user_data, GDestroyNotify notify)
{
gst_mini_object_init (GST_MINI_OBJECT_CAST (mem), GST_TYPE_MEMORY,
gst_mini_object_init (GST_MINI_OBJECT_CAST (mem),
flags | GST_MINI_OBJECT_FLAG_LOCKABLE, GST_TYPE_MEMORY,
(GstMiniObjectCopyFunction) _gst_memory_copy, NULL,
(GstMiniObjectFreeFunction) _gst_memory_free);
mem->mem.mini_object.flags = flags;
mem->mem.allocator = _default_mem_impl;
mem->mem.parent = parent ? gst_memory_ref (parent) : NULL;
mem->mem.state = (flags & GST_MEMORY_FLAG_READONLY ? GST_LOCK_FLAG_READ : 0);
mem->mem.maxsize = maxsize;
mem->mem.align = align;
mem->mem.offset = offset;
......@@ -434,25 +430,6 @@ gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
return (GstMemory *) mem;
}
/**
* gst_memory_is_exclusive:
* @mem: a #GstMemory
*
* Check if the current EXCLUSIVE lock on @mem is the only one, this means that
* changes to the object will not be visible to any other object.
*/
gboolean
gst_memory_is_exclusive (GstMemory * mem)
{
gint state;
g_return_val_if_fail (mem != NULL, FALSE);
state = g_atomic_int_get (&mem->state);
return (state & SHARE_MASK) < 2;
}
/**
* gst_memory_get_sizes:
* @mem: a #GstMemory
......@@ -507,99 +484,6 @@ gst_memory_resize (GstMemory * mem, gssize offset, gsize size)
mem->size = size;
}
/**
* gst_memory_lock:
* @mem: a #GstMemory
* @flags: #GstLockFlags
*
* Lock the memory with the specified access mode in @flags.
*
* Returns: %TRUE if the memory could be locked.
*/
gboolean
gst_memory_lock (GstMemory * mem, GstLockFlags flags)
{
gint access_mode, state, newstate;
access_mode = flags & FLAG_MASK;
do {
newstate = state = g_atomic_int_get (&mem->state);
GST_CAT_TRACE (GST_CAT_MEMORY, "lock %p: state %08x, access_mode %d",
mem, state, access_mode);
if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) {
/* shared ref */
newstate += SHARE_ONE;
access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE;
}
if (access_mode) {
if ((state & LOCK_FLAG_MASK) == 0) {
/* shared counter > 1 and write access */
if (state > SHARE_ONE && access_mode & GST_LOCK_FLAG_WRITE)
goto lock_failed;
/* nothing mapped, set access_mode */
newstate |= access_mode;
} else {
/* access_mode must match */
if ((state & access_mode) != access_mode)
goto lock_failed;
}
/* increase refcount */
newstate += LOCK_ONE;
}
} while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
return TRUE;
lock_failed:
{
GST_CAT_DEBUG (GST_CAT_MEMORY, "lock failed %p: state %08x, access_mode %d",
mem, state, access_mode);
return FALSE;
}
}
/**
* gst_memory_unlock:
* @mem: a #GstMemory
* @flags: #GstLockFlags
*
* Unlock the memory with the specified access mode in @flags.
*/
void
gst_memory_unlock (GstMemory * mem, GstLockFlags flags)
{
gint access_mode, state, newstate;
access_mode = flags & FLAG_MASK;
do {
newstate = state = g_atomic_int_get (&mem->state);
GST_CAT_TRACE (GST_CAT_MEMORY, "unlock %p: state %08x, access_mode %d",
mem, state, access_mode);
if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) {
/* shared counter */
g_return_if_fail (state >= SHARE_ONE);
newstate -= SHARE_ONE;
access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE;
}
if (access_mode) {
g_return_if_fail ((state & access_mode) == access_mode);
/* decrease the refcount */
newstate -= LOCK_ONE;
/* last refcount, unset access_mode */
if ((newstate & LOCK_FLAG_MASK) == access_mode)
newstate &= ~LOCK_FLAG_MASK;
}
} while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
}
/**
* gst_memory_make_mapped:
* @mem: (transfer full): a #GstMemory
......@@ -721,8 +605,6 @@ gst_memory_unmap (GstMemory * mem, GstMapInfo * info)
g_return_if_fail (mem != NULL);
g_return_if_fail (info != NULL);
g_return_if_fail (info->memory == mem);
/* there must be a ref */
g_return_if_fail (g_atomic_int_get (&mem->state) >= 4);
mem->allocator->info.mem_unmap (mem);
gst_memory_unlock (mem, info->flags);
......@@ -861,7 +743,7 @@ gst_allocator_new (const GstMemoryInfo * info, gpointer user_data,
allocator = g_slice_new0 (GstAllocator);
gst_mini_object_init (GST_MINI_OBJECT_CAST (allocator), GST_TYPE_ALLOCATOR,
gst_mini_object_init (GST_MINI_OBJECT_CAST (allocator), 0, GST_TYPE_ALLOCATOR,
(GstMiniObjectCopyFunction) _gst_allocator_copy, NULL,
(GstMiniObjectFreeFunction) _gst_allocator_free);
......
......@@ -66,10 +66,10 @@ GST_EXPORT gsize gst_memory_alignment;
* Flags for wrapped memory.
*/
typedef enum {
GST_MEMORY_FLAG_READONLY = (GST_MINI_OBJECT_FLAG_LAST << 0),
GST_MEMORY_FLAG_NO_SHARE = (GST_MINI_OBJECT_FLAG_LAST << 1),
GST_MEMORY_FLAG_ZERO_PREFIXED = (GST_MINI_OBJECT_FLAG_LAST << 2),
GST_MEMORY_FLAG_ZERO_PADDED = (GST_MINI_OBJECT_FLAG_LAST << 3),
GST_MEMORY_FLAG_READONLY = GST_MINI_OBJECT_FLAG_LOCK_READONLY,
GST_MEMORY_FLAG_NO_SHARE = (GST_MINI_OBJECT_FLAG_LAST << 0),
GST_MEMORY_FLAG_ZERO_PREFIXED = (GST_MINI_OBJECT_FLAG_LAST << 1),
GST_MEMORY_FLAG_ZERO_PADDED = (GST_MINI_OBJECT_FLAG_LAST << 2),
GST_MEMORY_FLAG_LAST = (GST_MINI_OBJECT_FLAG_LAST << 16)
} GstMemoryFlags;
......@@ -133,7 +133,6 @@ typedef enum {
* @mini_object: parent structure
* @allocator: pointer to the #GstAllocator
* @parent: parent memory block
* @state: private state
* @maxsize: the maximum size allocated
* @align: the alignment of the memory
* @offset: the offset where valid data starts
......@@ -148,37 +147,12 @@ struct _GstMemory {
GstAllocator *allocator;
GstMemory *parent;
volatile gint state;
gsize maxsize;
gsize align;
gsize offset;
gsize size;
};
/**
* GstLockFlags:
* @GST_LOCK_FLAG_READ: lock for read access
* @GST_LOCK_FLAG_WRITE: lock for write access
* @GST_LOCK_FLAG_EXCLUSIVE: lock for exclusive access
* @GST_LOCK_FLAG_LAST: first flag that can be used for custom purposes
*
* Flags used when locking memory
*/
typedef enum {
GST_LOCK_FLAG_READ = (1 << 0),
GST_LOCK_FLAG_WRITE = (1 << 1),
GST_LOCK_FLAG_EXCLUSIVE = (1 << 2),
GST_LOCK_FLAG_LAST = (1 << 4)
} GstLockFlags;
/**
* GST_LOCK_FLAG_READWRITE:
*
* GstLockFlags value alias for GST_LOCK_FLAG_READ | GST_LOCK_FLAG_WRITE
*/
#define GST_LOCK_FLAG_READWRITE (GST_LOCK_FLAG_READ | GST_LOCK_FLAG_WRITE)
/**
* GstMapFlags:
* @GST_MAP_READ: map for read access
......@@ -487,17 +461,14 @@ gst_memory_unref (GstMemory * memory)
gst_mini_object_unref (GST_MINI_OBJECT_CAST (memory));
}
/* locking */
gboolean gst_memory_is_exclusive (GstMemory *mem);
gboolean gst_memory_lock (GstMemory *mem, GstLockFlags flags);
void gst_memory_unlock (GstMemory *mem, GstLockFlags flags);
/* getting/setting memory properties */
gsize gst_memory_get_sizes (GstMemory *mem, gsize *offset, gsize *maxsize);
void gst_memory_resize (GstMemory *mem, gssize offset, gsize size);
#define gst_memory_lock(m,f) gst_mini_object_lock (GST_MINI_OBJECT_CAST (m), (f))
#define gst_memory_unlock(m,f) gst_mini_object_unlock (GST_MINI_OBJECT_CAST (m), (f))
#define gst_memory_is_writable(m) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (m))
/* retrieving data */
GstMemory * gst_memory_make_mapped (GstMemory *mem, GstMapInfo *info, GstMapFlags flags);
gboolean gst_memory_map (GstMemory *mem, GstMapInfo *info, GstMapFlags flags);
......
......@@ -239,7 +239,7 @@ static void
gst_message_init (GstMessageImpl * message, GstMessageType type,
GstObject * src)
{
gst_mini_object_init (GST_MINI_OBJECT_CAST (message), _gst_message_type,
gst_mini_object_init (GST_MINI_OBJECT_CAST (message), 0, _gst_message_type,
(GstMiniObjectCopyFunction) _gst_message_copy, NULL,
(GstMiniObjectFreeFunction) _gst_message_free);
......
......@@ -68,6 +68,13 @@ static GstAllocTrace *_gst_mini_object_trace;
G_LOCK_DEFINE_STATIC (qdata_mutex);
static GQuark weak_ref_quark;
#define SHARE_ONE (1 << 16)
#define SHARE_MASK (~(SHARE_ONE - 1))
#define LOCK_ONE (GST_LOCK_FLAG_LAST)
#define FLAG_MASK (GST_LOCK_FLAG_LAST - 1)
#define LOCK_MASK ((SHARE_ONE - 1) - FLAG_MASK)
#define LOCK_FLAG_MASK (SHARE_ONE - 1)
typedef struct
{
GQuark quark;
......@@ -94,7 +101,7 @@ _priv_gst_mini_object_initialize (void)
/**
* gst_mini_object_init: (skip)
* @mini_object: a #GstMiniObject
* @mini_object: a #GstMiniObject
* @type: the #GType of the mini-object to create
* @copy_func: the copy function, or NULL
* @dispose_func: the dispose function, or NULL
......@@ -108,14 +115,16 @@ _priv_gst_mini_object_initialize (void)
* Returns: (transfer full): the new mini-object.
*/
void
gst_mini_object_init (GstMiniObject * mini_object, GType type,
gst_mini_object_init (GstMiniObject * mini_object, guint flags, GType type,
GstMiniObjectCopyFunction copy_func,
GstMiniObjectDisposeFunction dispose_func,
GstMiniObjectFreeFunction free_func)
{
mini_object->type = type;
mini_object->refcount = 1;
mini_object->flags = 0;
mini_object->lockstate =
(flags & GST_MINI_OBJECT_FLAG_LOCK_READONLY ? GST_LOCK_FLAG_READ : 0);
mini_object->flags = flags;
mini_object->copy = copy_func;
mini_object->dispose = dispose_func;
......@@ -154,24 +163,138 @@ gst_mini_object_copy (const GstMiniObject * mini_object)
return copy;
}
/**
* gst_mini_object_lock:
* @object: the mini-object to lock
* @flags: #GstLockFlags
*
* Lock the mini-object with the specified access mode in @flags.
*
* Returns: %TRUE if @object could be locked.
*/
gboolean
gst_mini_object_lock (GstMiniObject * object, GstLockFlags flags)
{
gint access_mode, state, newstate;
g_return_val_if_fail (object != NULL, FALSE);
g_return_val_if_fail (GST_MINI_OBJECT_IS_LOCKABLE (object), FALSE);
access_mode = flags & FLAG_MASK;
do {
newstate = state = g_atomic_int_get (&object->lockstate);
GST_CAT_TRACE (GST_CAT_LOCKING, "lock %p: state %08x, access_mode %d",
object, state, access_mode);
if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) {
/* shared ref */
newstate += SHARE_ONE;
access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE;
}
if (access_mode) {
if ((state & LOCK_FLAG_MASK) == 0) {
/* shared counter > 1 and write access */
if (state > SHARE_ONE && access_mode & GST_LOCK_FLAG_WRITE)
goto lock_failed;
/* nothing mapped, set access_mode */
newstate |= access_mode;
} else {
/* access_mode must match */
if ((state & access_mode) != access_mode)
goto lock_failed;
}
/* increase refcount */
newstate += LOCK_ONE;
}
} while (!g_atomic_int_compare_and_exchange (&object->lockstate, state,
newstate));
return TRUE;
lock_failed:
{
GST_CAT_DEBUG (GST_CAT_LOCKING,
"lock failed %p: state %08x, access_mode %d", object, state,
access_mode);
return FALSE;
}
}
/**
* gst_mini_object_unlock:
* @object: the mini-object to unlock
* @flags: #GstLockFlags
*
* Unlock the mini-object with the specified access mode in @flags.
*/
void
gst_mini_object_unlock (GstMiniObject * object, GstLockFlags flags)
{
gint access_mode, state, newstate;
g_return_if_fail (object != NULL);
g_return_if_fail (GST_MINI_OBJECT_IS_LOCKABLE (object));
access_mode = flags & FLAG_MASK;
do {
newstate = state = g_atomic_int_get (&object->lockstate);
GST_CAT_TRACE (GST_CAT_LOCKING, "unlock %p: state %08x, access_mode %d",
object, state, access_mode);
if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) {
/* shared counter */
g_return_if_fail (state >= SHARE_ONE);
newstate -= SHARE_ONE;
access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE;
}
if (access_mode) {
g_return_if_fail ((state & access_mode) == access_mode);
/* decrease the refcount */
newstate -= LOCK_ONE;
/* last refcount, unset access_mode */
if ((newstate & LOCK_FLAG_MASK) == access_mode)
newstate &= ~LOCK_FLAG_MASK;
}
} while (!g_atomic_int_compare_and_exchange (&object->lockstate, state,
newstate));
}
/**
* gst_mini_object_is_writable:
* @mini_object: the mini-object to check
*
* Checks if a mini-object is writable. A mini-object is writable
* if the reference count is one. Modification of a mini-object should
* only be done after verifying that it is writable.
* If @mini_object has the LOCKABLE flag set, check if the current EXCLUSIVE
* lock on @object is the only one, this means that changes to the object will
* not be visible to any other object.
*
* MT safe
* If the LOCKABLE flag is not set, check if the refcount of @mini_object is
* exactly 1, meaning that no other reference exists to the object and that the
* object is therefore writable.
*
* Modification of a mini-object should only be done after verifying that it
* is writable.
*
* Returns: TRUE if the object is writable.
*/
gboolean
gst_mini_object_is_writable (const GstMiniObject * mini_object)
{
gboolean result;
g_return_val_if_fail (mini_object != NULL, FALSE);
return (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1);
if (GST_MINI_OBJECT_IS_LOCKABLE (mini_object)) {
result = (g_atomic_int_get (&mini_object->lockstate) & SHARE_MASK) < 2;
} else {
result = (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1);
}
return result;
}
/**
......@@ -328,6 +451,10 @@ gst_mini_object_unref (GstMiniObject * mini_object)
/* if the subclass recycled the object (and returned FALSE) we don't
* want to free the instance anymore */
if (G_LIKELY (do_free)) {
/* there should be no outstanding locks */
g_return_if_fail ((g_atomic_int_get (&mini_object->lockstate) & LOCK_MASK)
< 4);
if (mini_object->n_qdata) {
call_finalize_notify (mini_object);
g_free (mini_object->qdata);
......
......@@ -84,6 +84,7 @@ typedef void (*GstMiniObjectNotify) (gpointer user_data, GstMiniObject * obj);
* This macro returns the type of the mini-object.
*/
#define GST_MINI_OBJECT_TYPE(obj) (GST_MINI_OBJECT_CAST(obj)->type)
/**
* GST_MINI_OBJECT_FLAGS:
* @obj: MiniObject to return flags for.
......@@ -118,16 +119,55 @@ typedef void (*GstMiniObjectNotify) (gpointer user_data, GstMiniObject * obj);
/**
* GstMiniObjectFlags:
* @GST_MINI_OBJECT_FLAG_LOCKABLE: the object can be locked and unlocked with
* gst_mini_object_lock() and gst_mini_object_unlock().
* @GST_MINI_OBJECT_FLAG_LOCK_READONLY: the object is permanently locked in
* READONLY mode. Only read locks can be performed on the object.
* @GST_MINI_OBJECT_FLAG_LAST: first flag that can be used by subclasses.
*
* Flags for the mini object
*/
typedef enum
{
GST_MINI_OBJECT_FLAG_LOCKABLE = (1 << 0),
GST_MINI_OBJECT_FLAG_LOCK_READONLY = (1 << 1),
/* padding */
GST_MINI_OBJECT_FLAG_LAST = (1<<4)
GST_MINI_OBJECT_FLAG_LAST = (1 << 4)
} GstMiniObjectFlags;
/**
* GST_MINI_OBJECT_IS_LOCKABLE:
* @obj: a #GstMiniObject
*
* Check if @obj is lockable. A lockable object can be locked and unlocked with
* gst_mini_object_lock() and gst_mini_object_unlock().
*/
#define GST_MINI_OBJECT_IS_LOCKABLE(obj) GST_MINI_OBJECT_FLAG_IS_SET(obj, GST_MINI_OBJECT_FLAG_LOCKABLE)
/**
* GstLockFlags:
* @GST_LOCK_FLAG_READ: lock for read access
* @GST_LOCK_FLAG_WRITE: lock for write access
* @GST_LOCK_FLAG_EXCLUSIVE: lock for exclusive access
* @GST_LOCK_FLAG_LAST: first flag that can be used for custom purposes
*
* Flags used when locking miniobjects
*/
typedef enum {
GST_LOCK_FLAG_READ = (1 << 0),
GST_LOCK_FLAG_WRITE = (1 << 1),
GST_LOCK_FLAG_EXCLUSIVE = (1 << 2),
GST_LOCK_FLAG_LAST = (1 << 4)
} GstLockFlags;
/**
* GST_LOCK_FLAG_READWRITE:
*
* GstLockFlags value alias for GST_LOCK_FLAG_READ | GST_LOCK_FLAG_WRITE
*/
#define GST_LOCK_FLAG_READWRITE (GST_LOCK_FLAG_READ | GST_LOCK_FLAG_WRITE)
/**
* GST_MINI_OBJECT_REFCOUNT:
* @obj: a #GstMiniObject
......@@ -147,6 +187,7 @@ typedef enum
* GstMiniObject:
* @type: the GType of the object
* @refcount: atomic refcount
* @lockstate: atomic state of the locks
* @flags: extra flags.
* @copy: a copy function
* @dispose: a dispose function
......@@ -163,6 +204,7 @@ struct _GstMiniObject {
/*< public >*/ /* with COW */
gint refcount;
gint lockstate;
guint flags;
GstMiniObjectCopyFunction copy;
......@@ -175,14 +217,12 @@ struct _GstMiniObject {
gpointer qdata;
};
void gst_mini_object_init (GstMiniObject *mini_object, GType type,