From b12471008b879a4e5c3951b817d52a8ab4bfa699 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Tue, 20 Sep 2005 11:09:50 +0000 Subject: [PATCH] gst/gstelementfactory.c (gst_element_factory_create): Avoid eating the caller's refcount. Original commit message from CVS: 2005-09-20 Andy Wingo * gst/gstelementfactory.c (gst_element_factory_create): Avoid eating the caller's refcount. * gst/gstobject.h (GST_OBJECT_REFCOUNT) (GST_OBJECT_REFCOUNT_VALUE): Conditionally fondle the right refcount. * gst/gstconfig.h.in (GST_HAVE_GLIB_2_8): * configure.ac (GST_HAVE_GLIB_2_8_DEFINE): Make the availability of GLib 2.8 public, so we can know which refcount to check in tests. * gst/gstobject.c: Use the GST_HAVE_GLIB_2_8 define. (gst_object_init): Only set the gst refcount if we're going ahead with the refcount hack. --- ChangeLog | 18 ++++++++++++++++++ configure.ac | 4 +++- gst/gstconfig.h.in | 4 ++++ gst/gstelementfactory.c | 19 +++++++++++++++---- gst/gstobject.c | 4 +++- gst/gstobject.h | 7 ++++++- 6 files changed, 49 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05687ad..2cbb209 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2005-09-20 Andy Wingo + + * gst/gstelementfactory.c (gst_element_factory_create): Avoid + eating the caller's refcount. + + * gst/gstobject.h (GST_OBJECT_REFCOUNT) + (GST_OBJECT_REFCOUNT_VALUE): Conditionally fondle the right + refcount. + + * gst/gstconfig.h.in (GST_HAVE_GLIB_2_8): + * configure.ac (GST_HAVE_GLIB_2_8_DEFINE): Make the availability + of GLib 2.8 public, so we can know which refcount to check in + tests. + + * gst/gstobject.c: Use the GST_HAVE_GLIB_2_8 define. + (gst_object_init): Only set the gst refcount if we're going ahead + with the refcount hack. + 2005-09-20 Stefan Kost * check/gst-libs/controller.c: (plugin_init), (GST_START_TEST): diff --git a/configure.ac b/configure.ac index b0f4c0d..4588fa6 100644 --- a/configure.ac +++ b/configure.ac @@ -238,10 +238,12 @@ AC_SUBST(GLIB_CFLAGS) AC_MSG_CHECKING([glib version >= 2.8]) if pkg-config --atleast-version=2.8 glib-2.0; then AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_GLIB_2_8, [1], [Define to 1 if we can use API new in glib-2.8]) + GST_HAVE_GLIB_2_8_DEFINE="#define GST_HAVE_GLIB_2_8 1" else AC_MSG_RESULT(no) + GST_HAVE_GLIB_2_8_DEFINE="/* #undef GST_HAVE_GLIB_2_8 */" fi +AC_SUBST(GST_HAVE_GLIB_2_8_DEFINE) if test "x$HAVE_GLIB2" = "xno"; then AC_MSG_ERROR([GStreamer requires GLib $GLIB2_REQ to compile.]) diff --git a/gst/gstconfig.h.in b/gst/gstconfig.h.in index 0647d54..70b60eb 100644 --- a/gst/gstconfig.h.in +++ b/gst/gstconfig.h.in @@ -112,6 +112,10 @@ /* whether or not the CPU supports unaligned access */ @GST_HAVE_UNALIGNED_ACCESS_DEFINE@ +/* whether or not we are using glib 2.8 api, e.g. atomic gobject + refcounting */ +@GST_HAVE_GLIB_2_8_DEFINE@ + /***** Deal with XML stuff, we have to handle both loadsave and registry *****/ #if (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) ) diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c index 5afb15cd..c545b62 100644 --- a/gst/gstelementfactory.c +++ b/gst/gstelementfactory.c @@ -349,15 +349,27 @@ gst_element_factory_create (GstElementFactory * factory, const gchar * name) { GstElement *element; GstElementClass *oclass; + GstElementFactory *newfactory; g_return_val_if_fail (factory != NULL, NULL); - factory = + gst_object_ref (factory); + + newfactory = GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE (factory))); - if (factory == NULL) { - GST_DEBUG ("warning: loading the plugin for this factory returned NULL"); + if (newfactory == NULL) { + /* it could be factory is invalid. with ref-eating functions nothing is + certain! */ + GST_WARNING ("loading the plugin for factory %p returned NULL", factory); return NULL; + } else if (newfactory != factory) { + /* gst_plugin_feature_load ate the ref we added to the factory */ + factory = newfactory; + } else { + /* strip off our extra ref */ + gst_object_unref (factory); + factory = newfactory; } if (name) @@ -392,7 +404,6 @@ gst_element_factory_create (GstElementFactory * factory, const gchar * name) gst_object_set_name (GST_OBJECT (element), name); GST_DEBUG ("created \"%s\"", GST_PLUGIN_FEATURE_NAME (factory)); - gst_object_unref (factory); return element; } diff --git a/gst/gstobject.c b/gst/gstobject.c index 91bd7aa..79cc899 100644 --- a/gst/gstobject.c +++ b/gst/gstobject.c @@ -33,7 +33,7 @@ #endif #define DEBUG_REFCOUNT -#ifndef HAVE_GLIB_2_8 +#ifndef GST_HAVE_GLIB_2_8 #define REFCOUNT_HACK #endif @@ -218,7 +218,9 @@ gst_object_init (GTypeInstance * instance, gpointer g_class) object->parent = NULL; object->name = NULL; GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "%p new", object); +#ifdef REFCOUNT_HACK gst_atomic_int_set (&object->refcount, 1); +#endif PATCH_REFCOUNT (object); object->flags = 0; diff --git a/gst/gstobject.h b/gst/gstobject.h index 3f6cb67..31e2645 100644 --- a/gst/gstobject.h +++ b/gst/gstobject.h @@ -55,8 +55,13 @@ typedef enum GST_OBJECT_FLAG_LAST = 4 } GstObjectFlags; +#ifdef GST_HAVE_GLIB_2_8 +#define GST_OBJECT_REFCOUNT(obj) (((GObject*)(obj))->ref_count) +#define GST_OBJECT_REFCOUNT_VALUE(obj) (g_atomic_int_get (&((GObject*)(obj))->ref_count)) +#else #define GST_OBJECT_REFCOUNT(obj) ((GST_OBJECT_CAST(obj))->refcount) #define GST_OBJECT_REFCOUNT_VALUE(obj) (g_atomic_int_get (&(GST_OBJECT_CAST(obj))->refcount)) +#endif /* GST_HAVE_GLIB_2_8 */ /* we do a GST_OBJECT_CAST to avoid type checking, better call these * function with a valid object! */ @@ -84,7 +89,7 @@ struct _GstObject { GObject object; /*< public >*/ - gint refcount; + gint refcount; /* only used ifndef GST_HAVE_GLIB_0_8 */ /*< public >*/ /* with LOCK */ GMutex *lock; /* object LOCK */ -- 2.7.4