gst/gstbin.c: If a child is removed from a bin while we remove the child from the bin and while we're retrieving its ...

Original commit message from CVS:
* gst/gstbin.c: (gst_bin_add_func), (cb_parent_unset),
(gst_bin_get_state):
If a child is removed from a bin while we remove the child from
the bin and while we're retrieving its state, signal this to the
get_state function so we abort the wait (instead of waiting for
a timeout) and can immediately re-iterate over all other elements.
This commit is contained in:
Ronald S. Bultje 2005-05-12 12:17:23 +00:00
parent 88d6683316
commit e805d1b78b
2 changed files with 33 additions and 6 deletions

View file

@ -1,3 +1,12 @@
2005-05-12 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* gst/gstbin.c: (gst_bin_add_func), (cb_parent_unset),
(gst_bin_get_state):
If a child is removed from a bin while we remove the child from
the bin and while we're retrieving its state, signal this to the
get_state function so we abort the wait (instead of waiting for
a timeout) and can immediately re-iterate over all other elements.
2005-05-12 Wim Taymans <wim@fluendo.com>
* gst/base/Makefile.am:

View file

@ -364,6 +364,7 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
GST_UNLOCK (element);
GST_LOCK (bin);
/* then check to see if the element's name is already taken in the bin,
* we can safely take the lock here. This check is probably bogus because
* you can safely change the element name after adding it to the bin. */
@ -759,6 +760,19 @@ gst_bin_iterate_sinks (GstBin * bin)
return result;
}
/*
* This function will be called if the child is removed from the bin
* while we try to get its state. We should abort the _get_state()
* immediately to prevent pointless further blocking.
*/
static void
cb_parent_unset (GstElement * child, GstElement * parent, gpointer data)
{
GST_STATE_LOCK (child);
GST_STATE_BROADCAST (child);
GST_STATE_UNLOCK (child);
}
/* this functions loops over all children, as soon as one does
* not return SUCCESS, we return that value.
*
@ -785,31 +799,35 @@ restart:
children_cookie = bin->children_cookie;
while (children) {
GstElement *child = GST_ELEMENT_CAST (children->data);
gulong sig;
gst_object_ref (GST_OBJECT_CAST (child));
GST_UNLOCK (bin);
/* ret is ASYNC if some child is still performing the state change */
sig = g_signal_connect (child, "parent-unset",
G_CALLBACK (cb_parent_unset), NULL);
ret = gst_element_get_state (child, NULL, NULL, timeout);
g_signal_handler_disconnect (child, sig);
gst_object_unref (GST_OBJECT_CAST (child));
if (ret != GST_STATE_SUCCESS) {
/* some child is still busy or in error, we can report that
* right away. */
goto done;
}
/* now grab the lock to iterate to the next child */
GST_LOCK (bin);
if (G_UNLIKELY (children_cookie != bin->children_cookie))
/* child added/removed during state change, restart */
goto restart;
if (ret != GST_STATE_SUCCESS) {
/* some child is still busy or in error, we can report that
* right away. */
break;
}
children = g_list_next (children);
}
GST_UNLOCK (bin);
done:
/* now we can take the state lock */
GST_STATE_LOCK (bin);
switch (ret) {