+2005-08-24 Jan Schmidt <thaytan@mad.scientist.com>
+
+ * docs/pwg/advanced-types.xml:
+ Well done to Michael for catching my deliberate introduction
+ of this spelling mistake.
+ * gst/gstbin.c: (gst_bin_remove_func), (bin_bus_handler):
+ * gst/gstelement.h:
+ Add GST_ELEMENT_UNPARENTING to prevent races so that we can
+ unlink pads before removing the element from the bin.
+
2005-08-24 Andy Wingo <wingo@pobox.com>
* gst/gst.c (parse_debug_list): Accept e.g. GST_DEBUG=4 to mean
gchar *elem_name;
GstIterator *it;
- /* grab element name so we can print it */
GST_LOCK (element);
+ /* Check if the element is already being removed and immediately
+ * return */
+ if (G_UNLIKELY (GST_FLAG_IS_SET (element, GST_ELEMENT_UNPARENTING)))
+ goto already_removing;
+
+ GST_FLAG_SET (element, GST_ELEMENT_UNPARENTING);
+ /* grab element name so we can print it */
elem_name = g_strdup (GST_ELEMENT_NAME (element));
GST_UNLOCK (element);
+ /* unlink all linked pads */
+ it = gst_element_iterate_pads (element);
+ gst_iterator_foreach (it, (GFunc) unlink_pads, element);
+ gst_iterator_free (it);
+
GST_LOCK (bin);
/* the element must be in the bin's list of children */
if (G_UNLIKELY (g_list_find (bin->children, element) == NULL))
elem_name);
g_free (elem_name);
- /* unlink all linked pads */
- it = gst_element_iterate_pads (element);
- gst_iterator_foreach (it, (GFunc) unlink_pads, element);
- gst_iterator_free (it);
-
gst_element_set_bus (element, NULL);
/* unlock any waiters for the state change. It is possible that
GST_STATE_UNLOCK (element);
/* we ref here because after the _unparent() the element can be disposed
- * and we still need it to fire a signal. */
+ * and we still need it to reset the UNPARENTING flag and fire a signal. */
gst_object_ref (element);
gst_object_unparent (GST_OBJECT_CAST (element));
+ GST_LOCK (element);
+ GST_FLAG_UNSET (element, GST_ELEMENT_UNPARENTING);
+ GST_UNLOCK (element);
+
g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
+
/* element is really out of our control now */
gst_object_unref (element);
g_free (elem_name);
return FALSE;
}
+already_removing:
+ {
+ GST_UNLOCK (element);
+ return FALSE;
+ }
}
/**
{
/* ignore state changes from parent */
GST_ELEMENT_LOCKED_STATE,
-
+
/* the element is a sink */
GST_ELEMENT_IS_SINK,
+ /* Child is being removed from the parent bin. gst_bin_remove on a
+ * child already being removed immediately returns FALSE */
+ GST_ELEMENT_UNPARENTING,
+
/* use some padding for future expansion */
GST_ELEMENT_FLAG_LAST = GST_OBJECT_FLAG_LAST + 16
} GstElementFlags;