From fda9686b35e0fd5ea9bbc6f9fbcd1856c7b102d1 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 2 Dec 2009 21:21:48 +0100 Subject: [PATCH] miniobject: work on making caps a boxed type More work on making miniobject a simple allocated struct. --- gst/gstbuffer.c | 65 +++--- gst/gstbufferlist.c | 77 ++++---- gst/gstbufferlist.h | 8 +- gst/gstbus.c | 32 +-- gst/gstcaps.c | 64 +++--- gst/gstcaps.h | 39 +++- gst/gstminiobject.c | 473 +++++++------------------------------------- gst/gstminiobject.h | 28 ++- 8 files changed, 223 insertions(+), 563 deletions(-) diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 7158930da2..4d897e1f03 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -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; } diff --git a/gst/gstbufferlist.c b/gst/gstbufferlist.c index 358b5d1d95..e34269e80d 100644 --- a/gst/gstbufferlist.c +++ b/gst/gstbufferlist.c @@ -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 diff --git a/gst/gstbufferlist.h b/gst/gstbufferlist.h index 519063f6dd..8d536912c7 100644 --- a/gst/gstbufferlist.h +++ b/gst/gstbufferlist.h @@ -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; /** diff --git a/gst/gstbus.c b/gst/gstbus.c index 78396f44b9..e418f4e0d5 100644 --- a/gst/gstbus.c +++ b/gst/gstbus.c @@ -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)); } diff --git a/gst/gstcaps.c b/gst/gstcaps.c index 6e6dd15939..849c4f2c7d 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -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 diff --git a/gst/gstcaps.h b/gst/gstcaps.h index c04cc45035..af12ec8f50 100644 --- a/gst/gstcaps.h +++ b/gst/gstcaps.h @@ -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: diff --git a/gst/gstminiobject.c b/gst/gstminiobject.c index b8919f1e69..027efae34b 100644 --- a/gst/gstminiobject.c +++ b/gst/gstminiobject.c @@ -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); -} diff --git a/gst/gstminiobject.h b/gst/gstminiobject.h index 61e6566164..139a6ca638 100644 --- a/gst/gstminiobject.h +++ b/gst/gstminiobject.h @@ -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);