miniobject: work on making caps a boxed type

More work on making miniobject a simple allocated struct.
This commit is contained in:
Wim Taymans 2009-12-02 21:21:48 +01:00
parent 086aac764d
commit fda9686b35
8 changed files with 223 additions and 563 deletions

View file

@ -128,20 +128,15 @@
#include "gstminiobject.h"
#include "gstversion.h"
static void gst_buffer_finalize (GstBuffer * buffer);
static GstBuffer *_gst_buffer_copy (GstBuffer * buffer);
static GType _gst_buffer_type = 0;
GType
gst_buffer_get_type (void)
{
static GType gst_buffer_type = 0;
if (G_UNLIKELY (gst_buffer_type == 0)) {
gst_buffer_type = g_boxed_type_register_static ("GstBuffer",
(GBoxedCopyFunc) gst_buffer_copy_conditional,
(GBoxedFreeFunc) gst_buffer_unref);
if (G_UNLIKELY (_gst_buffer_type == 0)) {
_gst_buffer_type = gst_mini_object_register ("GstBuffer");
}
return gst_buffer_type;
return _gst_buffer_type;
}
/* buffer alignment in bytes
@ -183,23 +178,6 @@ _gst_buffer_initialize (void)
#endif
}
static void
gst_buffer_finalize (GstBuffer * buffer)
{
g_return_if_fail (buffer != NULL);
GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
/* free our data */
if (G_LIKELY (buffer->malloc_data))
buffer->free_func (buffer->malloc_data);
gst_caps_replace (&GST_BUFFER_CAPS (buffer), NULL);
if (buffer->parent)
gst_buffer_unref (buffer->parent);
}
/**
* gst_buffer_copy_metadata:
* @dest: a destination #GstBuffer
@ -299,18 +277,20 @@ _gst_buffer_copy (GstBuffer * buffer)
}
static void
gst_buffer_init (GstBuffer * buffer)
_gst_buffer_free (GstBuffer * buffer)
{
GST_CAT_LOG (GST_CAT_BUFFER, "init %p", buffer);
g_return_if_fail (buffer != NULL);
buffer->mini_object.copy = (GstMiniObjectCopyFunction) _gst_buffer_copy;
buffer->mini_object.free = (GstMiniObjectFreeeFunction) gst_buffer_finalize;
GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
GST_BUFFER_FREE_FUNC (buffer) = g_free;
/* free our data */
if (G_LIKELY (buffer->malloc_data))
buffer->free_func (buffer->malloc_data);
gst_caps_replace (&GST_BUFFER_CAPS (buffer), NULL);
if (buffer->parent)
gst_buffer_unref (buffer->parent);
}
/**
@ -327,10 +307,21 @@ gst_buffer_new (void)
{
GstBuffer *newbuf;
newbuf = (GstBuffer *) gst_mini_object_new (GST_TYPE_BUFFER);
newbuf = g_slice_new0 (GstBuffer);
GST_CAT_LOG (GST_CAT_BUFFER, "new %p", newbuf);
gst_mini_object_init (GST_MINI_OBJECT_CAST (newbuf),
_gst_buffer_type, sizeof (GstBuffer));
newbuf->mini_object.copy = (GstMiniObjectCopyFunction) _gst_buffer_copy;
newbuf->mini_object.free = (GstMiniObjectFreeFunction) _gst_buffer_free;
GST_BUFFER_TIMESTAMP (newbuf) = GST_CLOCK_TIME_NONE;
GST_BUFFER_DURATION (newbuf) = GST_CLOCK_TIME_NONE;
GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET_NONE;
GST_BUFFER_OFFSET_END (newbuf) = GST_BUFFER_OFFSET_NONE;
GST_BUFFER_FREE_FUNC (newbuf) = g_free;
return newbuf;
}

View file

@ -145,11 +145,6 @@ struct _GstBufferList
GList *buffers;
};
struct _GstBufferListClass
{
GstMiniObjectClass mini_object_class;
};
/**
* GstBufferListIterator:
*
@ -166,8 +161,6 @@ struct _GstBufferListIterator
static GType _gst_buffer_list_type = 0;
G_DEFINE_TYPE (GstBufferList, gst_buffer_list, GST_TYPE_MINI_OBJECT);
void
_gst_buffer_list_initialize (void)
{
@ -177,37 +170,6 @@ _gst_buffer_list_initialize (void)
_gst_buffer_list_type = type;
}
static void
gst_buffer_list_init (GstBufferList * list)
{
list->buffers = NULL;
GST_LOG ("init %p", list);
}
static void
gst_buffer_list_finalize (GstBufferList * list)
{
GList *tmp;
g_return_if_fail (list != NULL);
GST_LOG ("finalize %p", list);
tmp = list->buffers;
while (tmp) {
if (tmp->data != GROUP_START && tmp->data != STOLEN) {
gst_buffer_unref (GST_BUFFER_CAST (tmp->data));
}
tmp = tmp->next;
}
g_list_free (list->buffers);
/* Not chaining up because GstMiniObject::finalize() does nothing
GST_MINI_OBJECT_CLASS (gst_buffer_list_parent_class)->finalize
(GST_MINI_OBJECT_CAST (list));*/
}
static GstBufferList *
_gst_buffer_list_copy (GstBufferList * list)
{
@ -234,12 +196,24 @@ _gst_buffer_list_copy (GstBufferList * list)
}
static void
gst_buffer_list_class_init (GstBufferListClass * list_class)
_gst_buffer_list_free (GstBufferList * list)
{
list_class->mini_object_class.copy =
(GstMiniObjectCopyFunction) _gst_buffer_list_copy;
list_class->mini_object_class.finalize =
(GstMiniObjectFinalizeFunction) gst_buffer_list_finalize;
GList *tmp;
g_return_if_fail (list != NULL);
GST_LOG ("free %p", list);
tmp = list->buffers;
while (tmp) {
if (tmp->data != GROUP_START && tmp->data != STOLEN) {
gst_buffer_unref (GST_BUFFER_CAST (tmp->data));
}
tmp = tmp->next;
}
g_list_free (list->buffers);
g_slice_free (GstBufferList, list);
}
/**
@ -260,7 +234,13 @@ gst_buffer_list_new (void)
{
GstBufferList *list;
list = (GstBufferList *) gst_mini_object_new (_gst_buffer_list_type);
list = g_slice_new0 (GstBufferList);
gst_mini_object_init (GST_MINI_OBJECT_CAST (list), _gst_buffer_list_type,
sizeof (GstBufferList));
list->mini_object.copy = (GstMiniObjectCopyFunction) _gst_buffer_list_copy;
list->mini_object.free = (GstMiniObjectFreeFunction) _gst_buffer_list_free;
GST_LOG ("new %p", list);
@ -422,6 +402,15 @@ gst_buffer_list_get (GstBufferList * list, guint group, guint idx)
return NULL;
}
GType
gst_buffer_list_get_type (void)
{
if (G_UNLIKELY (_gst_buffer_list_type == 0)) {
_gst_buffer_list_type = gst_mini_object_register ("GstBufferList");
}
return _gst_buffer_list_type;
}
/**
* gst_buffer_list_iterate:
* @list: a #GstBufferList

View file

@ -28,15 +28,11 @@
G_BEGIN_DECLS
#define GST_TYPE_BUFFER_LIST (gst_buffer_list_get_type ())
#define GST_IS_BUFFER_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_BUFFER_LIST))
#define GST_IS_BUFFER_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_BUFFER_LIST))
#define GST_BUFFER_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BUFFER_LIST, GstBufferListClass))
#define GST_BUFFER_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BUFFER_LIST, GstBufferList))
#define GST_BUFFER_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BUFFER_LIST, GstBufferListClass))
#define GST_IS_BUFFER_LIST(obj) (GST_MINI_OBJECT_TYPE(obj) == GST_TYPE_BUFFER_LIST)
#define GST_BUFFER_LIST_CAST(obj) ((GstBufferList *)obj)
#define GST_BUFFER_LIST(obj) (GST_BUFFER_LIST_CAST(obj))
typedef struct _GstBufferList GstBufferList;
typedef struct _GstBufferListClass GstBufferListClass;
typedef struct _GstBufferListIterator GstBufferListIterator;
/**

View file

@ -106,34 +106,6 @@ struct _GstBusPrivate
G_DEFINE_TYPE (GstBus, gst_bus, GST_TYPE_OBJECT);
/* fixme: do something about this */
static void
marshal_VOID__MINIOBJECT (GClosure * closure, GValue * return_value,
guint n_param_values, const GValue * param_values, gpointer invocation_hint,
gpointer marshal_data)
{
typedef void (*marshalfunc_VOID__MINIOBJECT) (gpointer obj, gpointer arg1,
gpointer data2);
register marshalfunc_VOID__MINIOBJECT callback;
register GCClosure *cc = (GCClosure *) closure;
register gpointer data1, data2;
g_return_if_fail (n_param_values == 2);
if (G_CCLOSURE_SWAP_DATA (closure)) {
data1 = closure->data;
data2 = g_value_peek_pointer (param_values + 0);
} else {
data1 = g_value_peek_pointer (param_values + 0);
data2 = closure->data;
}
callback =
(marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data :
cc->callback);
callback (data1, gst_value_get_mini_object (param_values + 1), data2);
}
static void
gst_bus_class_init (GstBusClass * klass)
{
@ -162,7 +134,7 @@ gst_bus_class_init (GstBusClass * klass)
g_signal_new ("sync-message", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
G_STRUCT_OFFSET (GstBusClass, sync_message), NULL, NULL,
marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
/**
* GstBus::message:
@ -177,7 +149,7 @@ gst_bus_class_init (GstBusClass * klass)
g_signal_new ("message", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
G_STRUCT_OFFSET (GstBusClass, message), NULL, NULL,
marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
g_type_class_add_private (klass, sizeof (GstBusPrivate));
}

View file

@ -141,6 +141,32 @@ gst_caps_get_type (void)
}
/* creation/deletion */
static void
_gst_caps_free (GstCaps * caps)
{
GstStructure *structure;
guint i, len;
/* The refcount must be 0, but since we're only called by gst_caps_unref,
* don't bother testing. */
len = caps->structs->len;
/* This can be used to get statistics about caps sizes */
/*GST_CAT_INFO (GST_CAT_CAPS, "caps size: %d", len); */
for (i = 0; i < len; i++) {
structure = (GstStructure *) gst_caps_get_structure_unchecked (caps, i);
gst_structure_set_parent_refcount (structure, NULL);
gst_structure_free (structure);
}
g_ptr_array_free (caps->structs, TRUE);
#ifdef USE_POISONING
memset (caps, 0xff, sizeof (GstCaps));
#endif
#ifdef DEBUG_REFCOUNT
GST_CAT_LOG (GST_CAT_CAPS, "freeing caps %p", caps);
#endif
g_slice_free (GstCaps, caps);
}
/**
* gst_caps_new_empty:
@ -156,9 +182,12 @@ gst_caps_new_empty (void)
{
GstCaps *caps = g_slice_new (GstCaps);
caps->type = GST_TYPE_CAPS;
caps->refcount = 1;
caps->flags = 0;
gst_mini_object_init (GST_MINI_OBJECT_CAST (caps),
GST_TYPE_CAPS, sizeof (GstCaps));
caps->mini_object.copy = (GstMiniObjectCopyFunction) gst_caps_copy;
caps->mini_object.free = (GstMiniObjectFreeFunction) _gst_caps_free;
caps->structs = g_ptr_array_new ();
/* the 32 has been determined by logging caps sizes in _gst_caps_free
* but g_ptr_array uses 16 anyway if it expands once, so this does not help
@ -186,7 +215,7 @@ gst_caps_new_any (void)
{
GstCaps *caps = gst_caps_new_empty ();
caps->flags = GST_CAPS_FLAGS_ANY;
GST_CAPS_FLAG_SET (caps, GST_CAPS_FLAGS_ANY);
return caps;
}
@ -309,33 +338,6 @@ gst_caps_copy (const GstCaps * caps)
return newcaps;
}
static void
_gst_caps_free (GstCaps * caps)
{
GstStructure *structure;
guint i, len;
/* The refcount must be 0, but since we're only called by gst_caps_unref,
* don't bother testing. */
len = caps->structs->len;
/* This can be used to get statistics about caps sizes */
/*GST_CAT_INFO (GST_CAT_CAPS, "caps size: %d", len); */
for (i = 0; i < len; i++) {
structure = (GstStructure *) gst_caps_get_structure_unchecked (caps, i);
gst_structure_set_parent_refcount (structure, NULL);
gst_structure_free (structure);
}
g_ptr_array_free (caps->structs, TRUE);
#ifdef USE_POISONING
memset (caps, 0xff, sizeof (GstCaps));
#endif
#ifdef DEBUG_REFCOUNT
GST_CAT_LOG (GST_CAT_CAPS, "freeing caps %p", caps);
#endif
g_slice_free (GstCaps, caps);
}
/**
* gst_caps_make_writable:
* @caps: (transfer full): the #GstCaps to make writable

View file

@ -40,7 +40,7 @@ G_BEGIN_DECLS
* Extra flags for a caps.
*/
typedef enum {
GST_CAPS_FLAGS_ANY = (1 << 0)
GST_CAPS_FLAGS_ANY = (GST_MINI_OBJECT_FLAG_LAST << 0)
} GstCapsFlags;
/**
@ -99,6 +99,14 @@ typedef enum {
typedef struct _GstCaps GstCaps;
typedef struct _GstStaticCaps GstStaticCaps;
/**
* GST_CAPS_FLAGS:
* @caps: a #GstCaps.
*
* A flags word containing #GstCapsFlags flags set on this caps.
*/
#define GST_CAPS_FLAGS(caps) GST_MINI_OBJECT_FLAGS(caps)
/* refcount */
/**
* GST_CAPS_REFCOUNT:
@ -106,14 +114,39 @@ typedef struct _GstStaticCaps GstStaticCaps;
*
* Get access to the reference count field of the caps
*/
#define GST_CAPS_REFCOUNT(caps) ((GST_CAPS(caps))->refcount)
#define GST_CAPS_REFCOUNT(caps) GST_MINI_OBJECT_REFCOUNT(caps)
/**
* GST_CAPS_REFCOUNT_VALUE:
* @caps: a #GstCaps
*
* Get the reference count value of the caps.
*/
#define GST_CAPS_REFCOUNT_VALUE(caps) (g_atomic_int_get (&(GST_CAPS(caps))->refcount))
#define GST_CAPS_REFCOUNT_VALUE(caps) GST_MINI_OBJECT_REFCOUNT_VALUE(caps)
/**
* GST_CAPS_FLAG_IS_SET:
* @caps: a #GstBuffer.
* @flag: the #GstBufferFlag to check.
*
* Gives the status of a specific flag on a caps.
*/
#define GST_CAPS_FLAG_IS_SET(caps,flag) GST_MINI_OBJECT_FLAG_IS_SET (caps, flag)
/**
* GST_CAPS_FLAG_SET:
* @caps: a #GstBuffer.
* @flag: the #GstBufferFlag to set.
*
* Sets a caps flag on a caps.
*/
#define GST_CAPS_FLAG_SET(caps,flag) GST_MINI_OBJECT_FLAG_SET (caps, flag)
/**
* GST_CAPS_FLAG_UNSET:
* @caps: a #GstBuffer.
* @flag: the #GstBufferFlag to clear.
*
* Clears a caps flag.
*/
#define GST_CAPS_FLAG_UNSET(caps,flag) GST_MINI_OBJECT_FLAG_UNSET (caps, flag)
/**
* GstCaps:

View file

@ -46,153 +46,66 @@ static GstAllocTrace *_gst_mini_object_trace;
#define GST_MINI_OBJECT_GET_CLASS_UNCHECKED(obj) \
((GstMiniObjectClass *) (((GTypeInstance*)(obj))->g_class))
#if 0
static void gst_mini_object_base_init (gpointer g_class);
static void gst_mini_object_base_finalize (gpointer g_class);
#endif
static void gst_mini_object_class_init (gpointer g_class, gpointer class_data);
static void gst_mini_object_init (GTypeInstance * instance, gpointer klass);
static void gst_value_mini_object_init (GValue * value);
static void gst_value_mini_object_free (GValue * value);
static void gst_value_mini_object_copy (const GValue * src_value,
GValue * dest_value);
static gpointer gst_value_mini_object_peek_pointer (const GValue * value);
static gchar *gst_value_mini_object_collect (GValue * value,
guint n_collect_values, GTypeCValue * collect_values, guint collect_flags);
static gchar *gst_value_mini_object_lcopy (const GValue * value,
guint n_collect_values, GTypeCValue * collect_values, guint collect_flags);
static GstMiniObject *gst_mini_object_copy_default (const GstMiniObject * obj);
static void gst_mini_object_finalize (GstMiniObject * obj);
GType
gst_mini_object_get_type (void)
{
static volatile GType _gst_mini_object_type = 0;
if (g_once_init_enter (&_gst_mini_object_type)) {
GType _type;
static const GTypeValueTable value_table = {
gst_value_mini_object_init,
gst_value_mini_object_free,
gst_value_mini_object_copy,
gst_value_mini_object_peek_pointer,
(char *) "p",
gst_value_mini_object_collect,
(char *) "p",
gst_value_mini_object_lcopy
};
static const GTypeInfo mini_object_info = {
sizeof (GstMiniObjectClass),
#if 0
gst_mini_object_base_init,
gst_mini_object_base_finalize,
#else
NULL, NULL,
#endif
gst_mini_object_class_init,
NULL,
NULL,
sizeof (GstMiniObject),
0,
(GInstanceInitFunc) gst_mini_object_init,
&value_table
};
static const GTypeFundamentalInfo mini_object_fundamental_info = {
(G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE |
G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE)
};
_type = g_type_fundamental_next ();
g_type_register_fundamental (_type, "GstMiniObject",
&mini_object_info, &mini_object_fundamental_info, G_TYPE_FLAG_ABSTRACT);
#ifndef GST_DISABLE_TRACE
_gst_mini_object_trace = gst_alloc_trace_register (g_type_name (_type));
#endif
g_once_init_leave (&_gst_mini_object_type, _type);
}
return _gst_mini_object_type;
}
#if 0
static void
gst_mini_object_base_init (gpointer g_class)
{
/* do nothing */
}
static void
gst_mini_object_base_finalize (gpointer g_class)
{
/* do nothing */
}
#endif
static void
gst_mini_object_class_init (gpointer g_class, gpointer class_data)
{
GstMiniObjectClass *mo_class = GST_MINI_OBJECT_CLASS (g_class);
mo_class->copy = gst_mini_object_copy_default;
mo_class->finalize = gst_mini_object_finalize;
}
static void
gst_mini_object_init (GTypeInstance * instance, gpointer klass)
{
GstMiniObject *mini_object = GST_MINI_OBJECT_CAST (instance);
mini_object->refcount = 1;
}
/* boxed copy and free functions. Don't real copy or free but simply
* change the refcount */
static GstMiniObject *
gst_mini_object_copy_default (const GstMiniObject * obj)
_gst_mini_object_boxed_copy (GstMiniObject * mini_object)
{
g_warning ("GstMiniObject classes must implement GstMiniObject::copy");
return NULL;
if (mini_object)
return gst_mini_object_ref (mini_object);
else
return NULL;
}
static void
gst_mini_object_finalize (GstMiniObject * obj)
_gst_mini_object_boxed_free (GstMiniObject * mini_object)
{
/* do nothing */
/* WARNING: if anything is ever put in this method, make sure that the
* following sub-classes' finalize method chains up to this one:
* gstbuffer
* gstevent
* gstmessage
* gstquery
*/
if (mini_object)
gst_mini_object_unref (mini_object);
}
/**
* gst_mini_object_new:
* @type: the #GType of the mini-object to create
* gst_mini_object_register:
* @name: name of the new boxed type
*
* Creates a new mini-object of the desired type.
* This function creates a new G_TYPE_BOXED derived type id for a new boxed type
* with name @name. The default miniobject refcounting copy and free function
* are used for the boxed type.
*
* Returns: a new G_TYPE_BOXED derived type id for @name.
*/
GType
gst_mini_object_register (const gchar * name)
{
GType type;
g_return_val_if_fail (name != NULL, 0);
type = g_boxed_type_register_static (name,
(GBoxedCopyFunc) _gst_mini_object_boxed_copy,
(GBoxedFreeFunc) _gst_mini_object_boxed_free);
return type;
}
/**
* gst_mini_object_init:
* @mini_object: a #GstMiniObject
* @type: the #GType of the mini-object to create
* @size: the size of the data
*
* Initializes a mini-object with the desired type and size.
*
* MT safe
*
* Returns: (transfer full): the new mini-object.
*/
GstMiniObject *
gst_mini_object_new (GType type)
void
gst_mini_object_init (GstMiniObject * mini_object, GType type, gsize size)
{
GstMiniObject *mini_object;
/* we don't support dynamic types because they really aren't useful,
* and could cause refcount problems */
mini_object = (GstMiniObject *) g_type_create_instance (type);
#ifndef GST_DISABLE_TRACE
gst_alloc_trace_new (_gst_mini_object_trace, mini_object);
#endif
return mini_object;
mini_object->type = type;
mini_object->refcount = 1;
mini_object->size = size;
}
/* FIXME 0.11: Current way of doing the copy makes it impossible
@ -222,13 +135,16 @@ gst_mini_object_new (GType type)
GstMiniObject *
gst_mini_object_copy (const GstMiniObject * mini_object)
{
GstMiniObjectClass *mo_class;
GstMiniObject *copy;
g_return_val_if_fail (mini_object != NULL, NULL);
mo_class = GST_MINI_OBJECT_GET_CLASS (mini_object);
if (mini_object->copy)
copy = mo_class->copy (mini_object);
else
copy = NULL;
return mo_class->copy (mini_object);
return copy;
}
/**
@ -320,33 +236,6 @@ gst_mini_object_ref (GstMiniObject * mini_object)
return mini_object;
}
static void
gst_mini_object_free (GstMiniObject * mini_object)
{
GstMiniObjectClass *mo_class;
/* At this point, the refcount of the object is 0. We increase the refcount
* here because if a subclass recycles the object and gives out a new
* reference we don't want to free the instance anymore. */
GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p ref %d->%d", mini_object,
GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object),
GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) + 1);
g_atomic_int_inc (&mini_object->refcount);
mo_class = GST_MINI_OBJECT_GET_CLASS_UNCHECKED (mini_object);
mo_class->finalize (mini_object);
/* decrement the refcount again, if the subclass recycled the object we don't
* want to free the instance anymore */
if (G_LIKELY (g_atomic_int_dec_and_test (&mini_object->refcount))) {
#ifndef GST_DISABLE_TRACE
gst_alloc_trace_free (_gst_mini_object_trace, mini_object);
#endif
g_type_free_instance ((GTypeInstance *) mini_object);
}
}
/**
* gst_mini_object_unref:
* @mini_object: the mini-object
@ -366,7 +255,23 @@ gst_mini_object_unref (GstMiniObject * mini_object)
GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) - 1);
if (G_UNLIKELY (g_atomic_int_dec_and_test (&mini_object->refcount))) {
gst_mini_object_free (mini_object);
/* At this point, the refcount of the object is 0. We increase the refcount
* here because if a subclass recycles the object and gives out a new
* reference we don't want to free the instance anymore. */
gst_mini_object_ref (mini_object);
if (mini_object->dispose)
mini_object->dispose (mini_object);
/* decrement the refcount again, if the subclass recycled the object we don't
* want to free the instance anymore */
if (G_LIKELY (g_atomic_int_dec_and_test (&mini_object->refcount))) {
#ifndef GST_DISABLE_TRACE
gst_alloc_trace_free (_gst_mini_object_trace, mini_object);
#endif
if (mini_object->free)
mini_object->free (mini_object);
}
}
}
@ -407,247 +312,3 @@ gst_mini_object_replace (GstMiniObject ** olddata, GstMiniObject * newdata)
if (olddata_val)
gst_mini_object_unref (olddata_val);
}
static void
gst_value_mini_object_init (GValue * value)
{
value->data[0].v_pointer = NULL;
}
static void
gst_value_mini_object_free (GValue * value)
{
if (value->data[0].v_pointer) {
gst_mini_object_unref (GST_MINI_OBJECT_CAST (value->data[0].v_pointer));
}
}
static void
gst_value_mini_object_copy (const GValue * src_value, GValue * dest_value)
{
if (src_value->data[0].v_pointer) {
dest_value->data[0].v_pointer =
gst_mini_object_ref (GST_MINI_OBJECT_CAST (src_value->data[0].
v_pointer));
} else {
dest_value->data[0].v_pointer = NULL;
}
}
static gpointer
gst_value_mini_object_peek_pointer (const GValue * value)
{
return value->data[0].v_pointer;
}
static gchar *
gst_value_mini_object_collect (GValue * value, guint n_collect_values,
GTypeCValue * collect_values, guint collect_flags)
{
if (collect_values[0].v_pointer) {
value->data[0].v_pointer =
gst_mini_object_ref (collect_values[0].v_pointer);
} else {
value->data[0].v_pointer = NULL;
}
return NULL;
}
static gchar *
gst_value_mini_object_lcopy (const GValue * value, guint n_collect_values,
GTypeCValue * collect_values, guint collect_flags)
{
gpointer *mini_object_p = collect_values[0].v_pointer;
if (!mini_object_p) {
return g_strdup_printf ("value location for '%s' passed as NULL",
G_VALUE_TYPE_NAME (value));
}
if (!value->data[0].v_pointer)
*mini_object_p = NULL;
else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
*mini_object_p = value->data[0].v_pointer;
else
*mini_object_p = gst_mini_object_ref (value->data[0].v_pointer);
return NULL;
}
/**
* gst_value_set_mini_object:
* @value: a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
* @mini_object: (transfer none): mini object value to set
*
* Set the contents of a %GST_TYPE_MINI_OBJECT derived #GValue to
* @mini_object.
* The caller retains ownership of the reference.
*/
void
gst_value_set_mini_object (GValue * value, GstMiniObject * mini_object)
{
gpointer *pointer_p;
g_return_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value));
g_return_if_fail (mini_object == NULL || GST_IS_MINI_OBJECT (mini_object));
pointer_p = &value->data[0].v_pointer;
gst_mini_object_replace ((GstMiniObject **) pointer_p, mini_object);
}
/**
* gst_value_take_mini_object:
* @value: a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
* @mini_object: (transfer full): mini object value to take
*
* Set the contents of a %GST_TYPE_MINI_OBJECT derived #GValue to
* @mini_object.
* Takes over the ownership of the caller's reference to @mini_object;
* the caller doesn't have to unref it any more.
*/
void
gst_value_take_mini_object (GValue * value, GstMiniObject * mini_object)
{
gpointer *pointer_p;
g_return_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value));
g_return_if_fail (mini_object == NULL || GST_IS_MINI_OBJECT (mini_object));
pointer_p = &value->data[0].v_pointer;
/* takes additional refcount */
gst_mini_object_replace ((GstMiniObject **) pointer_p, mini_object);
/* remove additional refcount */
if (mini_object)
gst_mini_object_unref (mini_object);
}
/**
* gst_value_get_mini_object:
* @value: a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
*
* Get the contents of a %GST_TYPE_MINI_OBJECT derived #GValue.
* Does not increase the refcount of the returned object.
*
* Returns: (transfer none): mini object contents of @value
*/
GstMiniObject *
gst_value_get_mini_object (const GValue * value)
{
g_return_val_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value), NULL);
return value->data[0].v_pointer;
}
/**
* gst_value_dup_mini_object:
* @value: a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
*
* Get the contents of a %GST_TYPE_MINI_OBJECT derived #GValue,
* increasing its reference count.
*
* Returns: (transfer full): mini object contents of @value
*
* Since: 0.10.20
*/
GstMiniObject *
gst_value_dup_mini_object (const GValue * value)
{
g_return_val_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value), NULL);
return gst_mini_object_ref (value->data[0].v_pointer);
}
/* param spec */
static void
param_mini_object_init (GParamSpec * pspec)
{
/* GParamSpecMiniObject *ospec = G_PARAM_SPEC_MINI_OBJECT (pspec); */
}
static void
param_mini_object_set_default (GParamSpec * pspec, GValue * value)
{
value->data[0].v_pointer = NULL;
}
static gboolean
param_mini_object_validate (GParamSpec * pspec, GValue * value)
{
GstMiniObject *mini_object = value->data[0].v_pointer;
gboolean changed = FALSE;
if (mini_object
&& !g_value_type_compatible (G_OBJECT_TYPE (mini_object),
pspec->value_type)) {
gst_mini_object_unref (mini_object);
value->data[0].v_pointer = NULL;
changed = TRUE;
}
return changed;
}
static gint
param_mini_object_values_cmp (GParamSpec * pspec,
const GValue * value1, const GValue * value2)
{
guint8 *p1 = value1->data[0].v_pointer;
guint8 *p2 = value2->data[0].v_pointer;
/* not much to compare here, try to at least provide stable lesser/greater result */
return p1 < p2 ? -1 : p1 > p2;
}
GType
gst_param_spec_mini_object_get_type (void)
{
static GType type;
if (G_UNLIKELY (type) == 0) {
static const GParamSpecTypeInfo pspec_info = {
sizeof (GstParamSpecMiniObject), /* instance_size */
16, /* n_preallocs */
param_mini_object_init, /* instance_init */
G_TYPE_OBJECT, /* value_type */
NULL, /* finalize */
param_mini_object_set_default, /* value_set_default */
param_mini_object_validate, /* value_validate */
param_mini_object_values_cmp, /* values_cmp */
};
/* FIXME 0.11: Should really be GstParamSpecMiniObject */
type = g_param_type_register_static ("GParamSpecMiniObject", &pspec_info);
}
return type;
}
/**
* gst_param_spec_mini_object:
* @name: the canonical name of the property
* @nick: the nickname of the property
* @blurb: a short description of the property
* @object_type: the #GstMiniObject #GType for the property
* @flags: a combination of #GParamFlags
*
* Creates a new #GParamSpec instance that hold #GstMiniObject references.
*
* Returns: (transfer full): a newly allocated #GParamSpec instance
*/
GParamSpec *
gst_param_spec_mini_object (const char *name, const char *nick,
const char *blurb, GType object_type, GParamFlags flags)
{
GstParamSpecMiniObject *ospec;
g_return_val_if_fail (g_type_is_a (object_type, GST_TYPE_MINI_OBJECT), NULL);
ospec = g_param_spec_internal (GST_TYPE_PARAM_MINI_OBJECT,
name, nick, blurb, flags);
G_PARAM_SPEC (ospec)->value_type = object_type;
return G_PARAM_SPEC (ospec);
}

View file

@ -38,20 +38,28 @@ typedef struct _GstMiniObject GstMiniObject;
* GstMiniObjectCopyFunction:
* @obj: MiniObject to copy
*
* Virtual function prototype for methods to create copies of instances.
* Function prototype for methods to create copies of instances.
*
* Returns: reference to cloned instance.
*/
typedef GstMiniObject * (*GstMiniObjectCopyFunction) (const GstMiniObject *obj);
/**
* GstMiniObjectDisposeFunction:
* @obj: MiniObject to dispose
*
* Function prototype for when a miniobject has lost its last refcount.
* Implementation of the mini object are allowed to revive the
* passed object by doing a gst_mini_object_ref(). If the object is not
* revived after the dispose function, the memory associated with the
* object is freed.
*/
typedef void (*GstMiniObjectDisposeFunction) (GstMiniObject *obj);
/**
* GstMiniObjectFreeFunction:
* @obj: MiniObject to free
*
* Virtual function prototype for methods to free ressources used by
* mini-objects. Subclasses of the mini object are allowed to revive the
* passed object by doing a gst_mini_object_ref(). If the object is not
* revived after the free function, the memory associated with the
* object is freed.
* mini-objects.
*/
typedef void (*GstMiniObjectFreeFunction) (GstMiniObject *obj);
@ -131,6 +139,9 @@ typedef enum
* @instance: type instance
* @refcount: atomic refcount
* @flags: extra flags.
* @copy: a copy function
* @dispose: a dispose function
* @free: the free function
*
* Base class for refcounted lightweight objects.
* Ref Func: gst_mini_object_ref
@ -144,12 +155,17 @@ struct _GstMiniObject {
/*< public >*/ /* with COW */
gint refcount;
guint flags;
gsize size;
GstMiniObjectCopyFunction copy;
GstMiniObjectDisposeFunction dispose;
GstMiniObjectFreeFunction free;
};
GType gst_mini_object_get_type (void);
GType gst_mini_object_register (const gchar *name);
void gst_mini_object_init (GstMiniObject *mini_object,
GType type, gsize size);
GstMiniObject* gst_mini_object_copy (const GstMiniObject *mini_object);
gboolean gst_mini_object_is_writable (const GstMiniObject *mini_object);