From 348563bc192cc24941e583452e6243ff61aac51e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 16 Mar 2011 10:50:39 +0100 Subject: [PATCH] iterator: Refactor GstIterator to be more binding friendly and have saner refcounting Fixes bug #638987. --- gst/gstiterator.c | 286 +++++++++++++++++++++++++++++++++--------------------- gst/gstiterator.h | 91 +++++++++-------- gst/gstplugin.c | 6 +- 3 files changed, 223 insertions(+), 160 deletions(-) diff --git a/gst/gstiterator.c b/gst/gstiterator.c index 7e13414..560565d 100644 --- a/gst/gstiterator.c +++ b/gst/gstiterator.c @@ -1,5 +1,6 @@ /* GStreamer * Copyright (C) 2004 Wim Taymans + * Copyright (C) 2011 Sebastian Dröge * * gstiterator.h: Base class for iterating datastructures. * @@ -46,7 +47,7 @@ * switch (gst_iterator_next (it, &item)) { * case GST_ITERATOR_OK: * ... use/change item here... - * gst_object_unref (item); + * g_value_reset (&item); * break; * case GST_ITERATOR_RESYNC: * ...rollback changes to items... @@ -61,6 +62,7 @@ * break; * } * } + * g_value_unset (&item); * gst_iterator_free (it); * * @@ -71,10 +73,16 @@ #include "gst_private.h" #include -static GstIterator * -gst_iterator_copy (GstIterator * it) +GstIterator * +gst_iterator_copy (const GstIterator * it) { - return g_slice_copy (it->size, it); + GstIterator *copy; + + copy = g_slice_copy (it->size, it); + if (it->copy) + it->copy (it, copy); + + return copy; } GType @@ -94,6 +102,7 @@ gst_iterator_init (GstIterator * it, GType type, GMutex * lock, guint32 * master_cookie, + GstIteratorCopyFunction copy, GstIteratorNextFunction next, GstIteratorItemFunction item, GstIteratorResyncFunction resync, GstIteratorFreeFunction free) @@ -103,6 +112,7 @@ gst_iterator_init (GstIterator * it, it->lock = lock; it->master_cookie = master_cookie; it->cookie = *master_cookie; + it->copy = copy; it->next = next; it->item = item; it->resync = resync; @@ -117,6 +127,7 @@ gst_iterator_init (GstIterator * it, * @lock: pointer to a #GMutex. * @master_cookie: pointer to a guint32 that is changed when the items in the * iterator changed. + * @copy: copy function * @next: function to get next item * @item: function to call on each item retrieved * @resync: function to resync the iterator @@ -137,6 +148,7 @@ gst_iterator_new (guint size, GType type, GMutex * lock, guint32 * master_cookie, + GstIteratorCopyFunction copy, GstIteratorNextFunction next, GstIteratorItemFunction item, GstIteratorResyncFunction resync, GstIteratorFreeFunction free) @@ -150,8 +162,8 @@ gst_iterator_new (guint size, g_return_val_if_fail (resync != NULL, NULL); g_return_val_if_fail (free != NULL, NULL); - result = g_slice_alloc (size); - gst_iterator_init (result, size, type, lock, master_cookie, next, item, + result = g_slice_alloc0 (size); + gst_iterator_init (result, size, type, lock, master_cookie, copy, next, item, resync, free); return result; @@ -163,21 +175,33 @@ gst_iterator_new (guint size, typedef struct _GstListIterator { GstIterator iterator; - gpointer owner; + GObject *owner; GList **orig; GList *list; /* pointer in list */ - GstIteratorDisposeFunction freefunc; + + void (*set_value) (GValue * value, gpointer item); } GstListIterator; +static void +gst_list_iterator_copy (const GstListIterator * it, GstListIterator * copy) +{ + if (copy->owner) + g_object_ref (copy->owner); +} + static GstIteratorResult -gst_list_iterator_next (GstListIterator * it, gpointer * elem) +gst_list_iterator_next (GstListIterator * it, GValue * elem) { + gpointer data; + if (it->list == NULL) return GST_ITERATOR_DONE; - *elem = it->list->data; + data = it->list->data; it->list = g_list_next (it->list); + it->set_value (elem, data); + return GST_ITERATOR_OK; } @@ -190,9 +214,8 @@ gst_list_iterator_resync (GstListIterator * it) static void gst_list_iterator_free (GstListIterator * it) { - if (it->freefunc) { - it->freefunc (it->owner); - } + if (it->owner) + g_object_unref (it->owner); } /** @@ -203,8 +226,7 @@ gst_list_iterator_free (GstListIterator * it) * is changed. * @list: pointer to the list * @owner: object owning the list - * @item: function to call for each item - * @free: function to call when the iterator is freed + * @item: function to call on each item retrieved * * Create a new iterator designed for iterating @list. * @@ -214,46 +236,52 @@ gst_list_iterator_free (GstListIterator * it) * The iterator will use @lock to retrieve the next item of the list and it * will then call the @item function before releasing @lock again. * - * The @item function usualy makes sure that the item remains alive while - * @lock is released and the application is using the item. The application is - * responsible for freeing/unreffing the item after usage as explained in - * gst_iterator_next(). - * * When a concurrent update to the list is performed, usually by @owner while * holding @lock, @master_cookie will be updated. The iterator implementation * will notice the update of the cookie and will return %GST_ITERATOR_RESYNC to * the user of the iterator in the next call to gst_iterator_next(). * - * @owner will be passed to the @free function when the iterator is freed. - * * Returns: the new #GstIterator for @list. * * MT safe. */ GstIterator * gst_iterator_new_list (GType type, - GMutex * lock, - guint32 * master_cookie, - GList ** list, - gpointer owner, - GstIteratorItemFunction item, GstIteratorDisposeFunction free) + GMutex * lock, guint32 * master_cookie, GList ** list, GObject * owner, + GstIteratorItemFunction item) { GstListIterator *result; + gpointer set_value; + + if (g_type_is_a (type, G_TYPE_OBJECT)) { + set_value = g_value_set_object; + } else if (g_type_is_a (type, G_TYPE_BOXED)) { + set_value = g_value_set_boxed; + } else if (g_type_is_a (type, G_TYPE_POINTER)) { + set_value = g_value_set_pointer; + } else if (g_type_is_a (type, G_TYPE_STRING)) { + set_value = g_value_set_string; + } else { + g_critical ("List iterators can only be created for lists containing " + "instances of GObject, boxed types, pointer types and strings"); + return NULL; + } /* no need to lock, nothing can change here */ result = (GstListIterator *) gst_iterator_new (sizeof (GstListIterator), type, lock, master_cookie, + (GstIteratorCopyFunction) gst_list_iterator_copy, (GstIteratorNextFunction) gst_list_iterator_next, (GstIteratorItemFunction) item, (GstIteratorResyncFunction) gst_list_iterator_resync, (GstIteratorFreeFunction) gst_list_iterator_free); - result->owner = owner; + result->owner = owner ? g_object_ref (owner) : NULL; result->orig = list; result->list = *list; - result->freefunc = free; + result->set_value = set_value; return GST_ITERATOR (result); } @@ -275,9 +303,10 @@ gst_iterator_pop (GstIterator * it) * Get the next item from the iterator in @elem. * * Only when this function returns %GST_ITERATOR_OK, @elem will contain a valid - * value. For iterators that return refcounted objects, the returned object - * will have its refcount increased and should therefore be unreffed after - * usage. + * value. @elem must have been initialized to the type of the iterator or + * initialized to zeroes with g_value_unset(). The caller is responsible for + * unsetting or resetting @elem with g_value_unset() or g_value_reset() + * after usage. * * When this function returns %GST_ITERATOR_DONE, no more elements can be * retrieved from @it. @@ -288,18 +317,22 @@ gst_iterator_pop (GstIterator * it) * * A return value of %GST_ITERATOR_ERROR indicates an unrecoverable fatal error. * - * Returns: The result of the iteration. Unref @elem after usage if this - * is a refcounted object. + * Returns: The result of the iteration. Unset @elem after usage. * * MT safe. */ GstIteratorResult -gst_iterator_next (GstIterator * it, gpointer * elem) +gst_iterator_next (GstIterator * it, GValue * elem) { GstIteratorResult result; g_return_val_if_fail (it != NULL, GST_ITERATOR_ERROR); g_return_val_if_fail (elem != NULL, GST_ITERATOR_ERROR); + g_return_val_if_fail (G_VALUE_TYPE (elem) == G_TYPE_INVALID + || G_VALUE_HOLDS (elem, it->type), GST_ITERATOR_ERROR); + + if (G_VALUE_TYPE (elem) == G_TYPE_INVALID) + g_value_init (elem, it->type); restart: if (it->pushed) { @@ -325,14 +358,16 @@ restart: if (result == GST_ITERATOR_OK && it->item) { GstIteratorItem itemres; - itemres = it->item (it, *elem); + itemres = it->item (it, elem); switch (itemres) { case GST_ITERATOR_ITEM_SKIP: if (G_LIKELY (it->lock)) g_mutex_unlock (it->lock); + g_value_reset (elem); goto restart; case GST_ITERATOR_ITEM_END: result = GST_ITERATOR_DONE; + g_value_reset (elem); break; case GST_ITERATOR_ITEM_PASS: break; @@ -425,29 +460,28 @@ typedef struct _GstIteratorFilter GstIterator *slave; GCompareFunc func; - gpointer user_data; + GValue user_data; + gboolean have_user_data; } GstIteratorFilter; static GstIteratorResult -filter_next (GstIteratorFilter * it, gpointer * elem) +filter_next (GstIteratorFilter * it, GValue * elem) { GstIteratorResult result = GST_ITERATOR_ERROR; gboolean done = FALSE; - - *elem = NULL; + GValue item = { 0, }; while (G_LIKELY (!done)) { - gpointer item; - result = gst_iterator_next (it->slave, &item); switch (result) { case GST_ITERATOR_OK: if (G_LIKELY (GST_ITERATOR (it)->lock)) g_mutex_unlock (GST_ITERATOR (it)->lock); - if (it->func (item, it->user_data) == 0) { - *elem = item; + if (it->func (&item, &it->user_data) == 0) { + g_value_copy (&item, elem); done = TRUE; } + g_value_reset (&item); if (G_LIKELY (GST_ITERATOR (it)->lock)) g_mutex_lock (GST_ITERATOR (it)->lock); break; @@ -460,25 +494,33 @@ filter_next (GstIteratorFilter * it, gpointer * elem) break; } } + g_value_unset (&item); return result; } static void -filter_resync (GstIteratorFilter * it) +filter_copy (const GstIteratorFilter * it, GstIteratorFilter * copy) { - gst_iterator_resync (it->slave); + copy->slave = gst_iterator_copy (it->slave); + + if (it->have_user_data) { + memset (©->user_data, 0, sizeof (copy->user_data)); + g_value_init (©->user_data, G_VALUE_TYPE (&it->user_data)); + g_value_copy (&it->user_data, ©->user_data); + } } static void -filter_uninit (GstIteratorFilter * it) +filter_resync (GstIteratorFilter * it) { - it->slave->lock = GST_ITERATOR (it)->lock; + gst_iterator_resync (it->slave); } static void filter_free (GstIteratorFilter * it) { - filter_uninit (it); + if (it->have_user_data) + g_value_unset (&it->user_data); gst_iterator_free (it->slave); } @@ -490,8 +532,9 @@ filter_free (GstIteratorFilter * it) * * Create a new iterator from an existing iterator. The new iterator * will only return those elements that match the given compare function @func. - * @func should return 0 for elements that should be included - * in the iterator. + * The first parameter that is passed to @func is the #GValue of the current + * iterator element and the second parameter is @user_data. @func should + * return 0 for elements that should be included in the filtered iterator. * * When this iterator is freed, @it will also be freed. * @@ -500,7 +543,8 @@ filter_free (GstIteratorFilter * it) * MT safe. */ GstIterator * -gst_iterator_filter (GstIterator * it, GCompareFunc func, gpointer user_data) +gst_iterator_filter (GstIterator * it, GCompareFunc func, + const GValue * user_data) { GstIteratorFilter *result; @@ -509,13 +553,21 @@ gst_iterator_filter (GstIterator * it, GCompareFunc func, gpointer user_data) result = (GstIteratorFilter *) gst_iterator_new (sizeof (GstIteratorFilter), it->type, it->lock, it->master_cookie, + (GstIteratorCopyFunction) filter_copy, (GstIteratorNextFunction) filter_next, (GstIteratorItemFunction) NULL, (GstIteratorResyncFunction) filter_resync, (GstIteratorFreeFunction) filter_free); + it->lock = NULL; result->func = func; - result->user_data = user_data; + if (user_data) { + g_value_init (&result->user_data, G_VALUE_TYPE (user_data)); + g_value_copy (user_data, &result->user_data); + result->have_user_data = TRUE; + } else { + result->have_user_data = FALSE; + } result->slave = it; return GST_ITERATOR (result); @@ -531,8 +583,7 @@ gst_iterator_filter (GstIterator * it, GCompareFunc func, gpointer user_data) * Folds @func over the elements of @iter. That is to say, @func will be called * as @func (object, @ret, @user_data) for each object in @it. The normal use * of this procedure is to accumulate the results of operating on the objects in - * @ret. If object is a refcounted object its refcount will be increased - * before @func is called, and it should be unrefed after use in @func. + * @ret. * * This procedure can be used (and is used internally) to implement the * gst_iterator_foreach() and gst_iterator_find_custom() operations. @@ -553,17 +604,18 @@ GstIteratorResult gst_iterator_fold (GstIterator * it, GstIteratorFoldFunction func, GValue * ret, gpointer user_data) { - gpointer item; + GValue item = { 0, }; GstIteratorResult result; while (1) { result = gst_iterator_next (it, &item); switch (result) { case GST_ITERATOR_OK: - if (!func (item, ret, user_data)) + if (!func (&item, ret, user_data)) goto fold_done; - else - break; + + g_value_reset (&item); + break; case GST_ITERATOR_RESYNC: case GST_ITERATOR_ERROR: goto fold_done; @@ -573,17 +625,19 @@ gst_iterator_fold (GstIterator * it, GstIteratorFoldFunction func, } fold_done: + g_value_unset (&item); + return result; } typedef struct { - GFunc func; + GstIteratorForeachFunction func; gpointer user_data; } ForeachFoldData; static gboolean -foreach_fold_func (gpointer item, GValue * unused, ForeachFoldData * data) +foreach_fold_func (const GValue * item, GValue * unused, ForeachFoldData * data) { data->func (item, data->user_data); return TRUE; @@ -596,9 +650,7 @@ foreach_fold_func (gpointer item, GValue * unused, ForeachFoldData * data) * @user_data: (closure): user data passed to the function * * Iterate over all element of @it and call the given function @func for - * each element. As in gst_iterator_fold(), the refcount of a refcounted - * object will be increased before @func is called, and should be unrefed - * after use. + * each element. * * Returns: the result call to gst_iterator_fold(). The iterator will not be * freed. @@ -606,7 +658,8 @@ foreach_fold_func (gpointer item, GValue * unused, ForeachFoldData * data) * MT safe. */ GstIteratorResult -gst_iterator_foreach (GstIterator * it, GFunc func, gpointer user_data) +gst_iterator_foreach (GstIterator * it, GstIteratorForeachFunction func, + gpointer user_data) { ForeachFoldData data; @@ -621,26 +674,22 @@ typedef struct { GCompareFunc func; gpointer user_data; + gboolean found; } FindCustomFoldData; static gboolean -find_custom_fold_func (gpointer item, GValue * ret, FindCustomFoldData * data) +find_custom_fold_func (const GValue * item, GValue * ret, + FindCustomFoldData * data) { if (data->func (item, data->user_data) == 0) { - g_value_set_pointer (ret, item); + data->found = TRUE; + g_value_copy (item, ret); return FALSE; } else { return TRUE; } } -/* FIXME 0.11: - * We should store ref/unref (or copy/free) functions for the type - * in GstIterator. The unref but only if it's not a match behaviour - * of find_custom() is very bad for bindings. The ref/unref functions - * are also useful for the fold and filter cases. - */ - /** * gst_iterator_find_custom: * @it: The #GstIterator to iterate @@ -648,66 +697,81 @@ find_custom_fold_func (gpointer item, GValue * ret, FindCustomFoldData * data) * @user_data: (closure): user data passed to the compare function * * Find the first element in @it that matches the compare function @func. - * @func should return 0 when the element is found. As in gst_iterator_fold(), - * the refcount of a refcounted object will be increased before @func is - * called, and should be unrefed after use in @func unless it is the matching - * element. + * @func should return 0 when the element is found. The first parameter + * to @func will be the current element of the iterator and the + * second parameter will be @user_data. + * The result will be stored in @elem if a result is found. * * The iterator will not be freed. * - * This function will return NULL if an error happened to the iterator. + * This function will return FALSE if an error happened to the iterator + * or if the element wasn't found. * - * Returns: (transfer full): The element in the iterator that matches the compare - * function or NULL when no element matched. + * Returns: Returns TRUE if the element was found, else FALSE. * * MT safe. */ -gpointer +gboolean gst_iterator_find_custom (GstIterator * it, GCompareFunc func, - gpointer user_data) + GValue * elem, gpointer user_data) { - GValue ret = { 0, }; GstIteratorResult res; FindCustomFoldData data; - g_value_init (&ret, G_TYPE_POINTER); + g_return_val_if_fail (G_VALUE_TYPE (elem) == G_TYPE_INVALID + || G_VALUE_HOLDS (elem, it->type), GST_ITERATOR_ERROR); + + if (G_VALUE_TYPE (elem) == G_TYPE_INVALID) + g_value_init (elem, it->type); + data.func = func; data.user_data = user_data; + data.found = FALSE; do { res = gst_iterator_fold (it, (GstIteratorFoldFunction) find_custom_fold_func, - &ret, &data); + elem, &data); if (res == GST_ITERATOR_RESYNC) gst_iterator_resync (it); } while (res == GST_ITERATOR_RESYNC); - /* no need to unset, it's just a pointer */ - return g_value_get_pointer (&ret); + if (!data.found) + g_value_unset (elem); + + return data.found; } typedef struct { GstIterator parent; - gpointer object; - GstCopyFunction copy; - GFreeFunc free; + GValue object; gboolean visited; + gboolean empty; } GstSingleObjectIterator; static guint32 _single_object_dummy_cookie = 0; +static void +gst_single_object_iterator_copy (const GstSingleObjectIterator * it, + GstSingleObjectIterator * copy) +{ + if (!it->empty) { + memset (©->object, 0, sizeof (copy->object)); + g_value_init (©->object, it->parent.type); + g_value_copy (&it->object, ©->object); + } +} + static GstIteratorResult -gst_single_object_iterator_iterator_next (GstSingleObjectIterator * it, - gpointer * result) +gst_single_object_iterator_next (GstSingleObjectIterator * it, GValue * result) { - if (it->visited || !it->object) { - *result = NULL; + if (it->visited || it->empty) return GST_ITERATOR_DONE; - } - *result = it->copy (it->object); + g_value_copy (&it->object, result); it->visited = TRUE; + return GST_ITERATOR_OK; } @@ -720,16 +784,14 @@ gst_single_object_iterator_resync (GstSingleObjectIterator * it) static void gst_single_object_iterator_free (GstSingleObjectIterator * it) { - if (it->object) - it->free (it->object); + if (!it->empty) + g_value_unset (&it->object); } /** * gst_iterator_new_single: * @type: #GType of the passed object * @object: object that this iterator should return - * @copy: Function that returns a copy of @object or increases its refcount - * @free: Function to be called for freeing @object * * This #GstIterator is a convenient iterator for the common * case where a #GstIterator needs to be returned but only @@ -741,25 +803,27 @@ gst_single_object_iterator_free (GstSingleObjectIterator * it) * Since: 0.10.25 */ GstIterator * -gst_iterator_new_single (GType type, gpointer object, GstCopyFunction copy, - GFreeFunc free) +gst_iterator_new_single (GType type, const GValue * object) { GstSingleObjectIterator *result; - g_return_val_if_fail (copy != NULL, NULL); - g_return_val_if_fail (free != NULL, NULL); - result = (GstSingleObjectIterator *) gst_iterator_new (sizeof (GstSingleObjectIterator), type, NULL, &_single_object_dummy_cookie, - (GstIteratorNextFunction) gst_single_object_iterator_iterator_next, NULL, + (GstIteratorCopyFunction) gst_single_object_iterator_copy, + (GstIteratorNextFunction) gst_single_object_iterator_next, + (GstIteratorItemFunction) NULL, (GstIteratorResyncFunction) gst_single_object_iterator_resync, (GstIteratorFreeFunction) gst_single_object_iterator_free); - result->object = (object) ? copy (object) : NULL; - result->copy = copy; - result->free = free; + if (object) { + g_value_init (&result->object, type); + g_value_copy (object, &result->object); + result->empty = FALSE; + } else { + result->empty = TRUE; + } result->visited = FALSE; - return (GstIterator *) result; + return GST_ITERATOR (result); } diff --git a/gst/gstiterator.h b/gst/gstiterator.h index 701c267..4a8a5a0 100644 --- a/gst/gstiterator.h +++ b/gst/gstiterator.h @@ -1,5 +1,6 @@ /* GStreamer * Copyright (C) 2004 Wim Taymans + * Copyright (C) 2011 Sebastian Dröge * * gstiterator.h: Header for GstIterator * @@ -62,37 +63,38 @@ typedef enum { } GstIteratorItem; /** - * GstIteratorDisposeFunction: - * @owner: the owner of the iterator + * GstIteratorCopyFunction: + * @it: The original iterator + * @copy: The copied iterator * - * The function that will be called when a #GList iterator is freed. The - * owner of the #GList iterator can then clean up its resources. + * This function will be called when creating a copy of @it and should + * create a copy of all custom iterator fields or increase their + * reference counts. */ -typedef void (*GstIteratorDisposeFunction) (gpointer owner); +typedef void (*GstIteratorCopyFunction) (const GstIterator *it, GstIterator *copy); /** - * GstIteratorNextFunction: + * GstIteratorItemFunction: * @it: the iterator - * @result: a pointer to hold the next item + * @item: the item being retrieved. * - * The function that will be called when the next element of the iterator - * should be retrieved. + * The function that will be called after the next item of the iterator + * has been retrieved. This function can be used to skip items or stop + * the iterator. * - * Implementors of a #GstIterator should implement this - * function and pass it to the constructor of the custom iterator. * The function will be called with the iterator lock held. * * Returns: the result of the operation. */ -typedef GstIteratorResult (*GstIteratorNextFunction) (GstIterator *it, gpointer *result); +typedef GstIteratorItem (*GstIteratorItemFunction) (GstIterator *it, const GValue * item); + /** - * GstIteratorItemFunction: + * GstIteratorNextFunction: * @it: the iterator - * @item: the item being retrieved. + * @result: a pointer to hold the next item * - * The function that will be called after the next item of the iterator - * has been retrieved. This function will typically increase the refcount - * of the item or make a copy. + * The function that will be called when the next element of the iterator + * should be retrieved. * * Implementors of a #GstIterator should implement this * function and pass it to the constructor of the custom iterator. @@ -100,7 +102,7 @@ typedef GstIteratorResult (*GstIteratorNextFunction) (GstIterator *it, gpointer * * Returns: the result of the operation. */ -typedef GstIteratorItem (*GstIteratorItemFunction) (GstIterator *it, gpointer item); +typedef GstIteratorResult (*GstIteratorNextFunction) (GstIterator *it, GValue *result); /** * GstIteratorResyncFunction: * @it: the iterator @@ -128,6 +130,15 @@ typedef void (*GstIteratorResyncFunction) (GstIterator *it); typedef void (*GstIteratorFreeFunction) (GstIterator *it); /** + * GstIteratorForeachFunction: + * @item: The item + * @user_data: User data + * + * A function that is called by gst_iterator_foreach() for every element. + */ +typedef void (*GstIteratorForeachFunction) (const GValue * item, gpointer user_data); + +/** * GstIteratorFoldFunction: * @item: the item to fold * @ret: a #GValue collecting the result @@ -137,20 +148,7 @@ typedef void (*GstIteratorFreeFunction) (GstIterator *it); * * Returns: TRUE if the fold should continue, FALSE if it should stop. */ -typedef gboolean (*GstIteratorFoldFunction) (gpointer item, GValue *ret, gpointer user_data); - -/** - * GstCopyFunction: - * @object: The object to copy - * - * A function to create a copy of some object or - * increase its reference count. - * - * Returns: a copy of the object or the same object with increased reference count - * - * Since: 0.10.25 - */ -typedef gpointer (*GstCopyFunction) (gpointer object); +typedef gboolean (*GstIteratorFoldFunction) (const GValue * item, GValue * ret, gpointer user_data); /** * GST_ITERATOR: @@ -206,6 +204,7 @@ typedef gpointer (*GstCopyFunction) (gpointer object); */ struct _GstIterator { /*< protected >*/ + GstIteratorCopyFunction copy; GstIteratorNextFunction next; GstIteratorItemFunction item; GstIteratorResyncFunction resync; @@ -221,7 +220,7 @@ struct _GstIterator { guint size; /*< private >*/ - gpointer _gst_reserved[GST_PADDING-1]; + gpointer _gst_reserved[GST_PADDING]; }; GType gst_iterator_get_type (void); @@ -231,26 +230,26 @@ GstIterator* gst_iterator_new (guint size, GType type, GMutex *lock, guint32 *master_cookie, + GstIteratorCopyFunction copy, GstIteratorNextFunction next, - GstIteratorItemFunction item, + GstIteratorItemFunction item, GstIteratorResyncFunction resync, GstIteratorFreeFunction free); -GstIterator* gst_iterator_new_list (GType type, +GstIterator* gst_iterator_new_list (GType type, GMutex *lock, guint32 *master_cookie, GList **list, - gpointer owner, - GstIteratorItemFunction item, - GstIteratorDisposeFunction free); + GObject * owner, + GstIteratorItemFunction item); GstIterator* gst_iterator_new_single (GType type, - gpointer object, - GstCopyFunction copy, - GFreeFunc free); + const GValue * object); + +GstIterator* gst_iterator_copy (const GstIterator *it); /* using iterators */ -GstIteratorResult gst_iterator_next (GstIterator *it, gpointer *elem); +GstIteratorResult gst_iterator_next (GstIterator *it, GValue * elem); void gst_iterator_resync (GstIterator *it); void gst_iterator_free (GstIterator *it); @@ -258,14 +257,14 @@ void gst_iterator_push (GstIterator *it, GstIterator *other); /* higher-order functions that operate on iterators */ GstIterator* gst_iterator_filter (GstIterator *it, GCompareFunc func, - gpointer user_data); + const GValue * user_data); GstIteratorResult gst_iterator_fold (GstIterator *it, GstIteratorFoldFunction func, GValue *ret, gpointer user_data); GstIteratorResult gst_iterator_foreach (GstIterator *it, - GFunc func, gpointer user_data); -gpointer gst_iterator_find_custom (GstIterator *it, GCompareFunc func, - gpointer user_data); + GstIteratorForeachFunction func, gpointer user_data); +gboolean gst_iterator_find_custom (GstIterator *it, GCompareFunc func, + GValue *elem, gpointer user_data); G_END_DECLS diff --git a/gst/gstplugin.c b/gst/gstplugin.c index 8f1f01e..31a0e44 100644 --- a/gst/gstplugin.c +++ b/gst/gstplugin.c @@ -1538,7 +1538,7 @@ gst_plugin_ext_dep_scan_dir_and_match_names (GstPlugin * plugin, GDir *dir; guint hash = 0; - recurse_dirs = !!(flags & GST_PLUGIN_DEPENDENCY_FLAG_RECURSE); + recurse_dirs = ! !(flags & GST_PLUGIN_DEPENDENCY_FLAG_RECURSE); dir = g_dir_open (path, 0, &err); if (dir == NULL) { @@ -1600,8 +1600,8 @@ gst_plugin_ext_dep_scan_path_with_filenames (GstPlugin * plugin, if (filenames == NULL || *filenames == NULL) filenames = empty_filenames; - recurse_into_dirs = !!(flags & GST_PLUGIN_DEPENDENCY_FLAG_RECURSE); - partial_names = !!(flags & GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX); + recurse_into_dirs = ! !(flags & GST_PLUGIN_DEPENDENCY_FLAG_RECURSE); + partial_names = ! !(flags & GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX); /* if we can construct the exact paths to check with the data we have, just * stat them one by one; this is more efficient than opening the directory -- 2.7.4