mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-25 01:54:17 +00:00
gst/gstpad.c: Use thread-safe internal links iterator. Fixes #549504.
Original commit message from CVS: Patch by: Olivier Crete <tester at tester dot ca> * gst/gstpad.c: (gst_pad_iterate_internal_links_default), (gst_pad_event_default_dispatch), (gst_pad_dispatcher): Use thread-safe internal links iterator. Fixes #549504.
This commit is contained in:
parent
68037404b8
commit
390369246e
2 changed files with 122 additions and 53 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2008-09-01 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||||
|
|
||||||
|
Patch by: Olivier Crete <tester at tester dot ca>
|
||||||
|
|
||||||
|
* gst/gstpad.c: (gst_pad_iterate_internal_links_default),
|
||||||
|
(gst_pad_event_default_dispatch), (gst_pad_dispatcher):
|
||||||
|
Use thread-safe internal links iterator. Fixes #549504.
|
||||||
|
|
||||||
2008-09-01 Wim Taymans <wim.taymans@collabora.co.uk>
|
2008-09-01 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||||
|
|
||||||
Based on patch by: Olivier Crete <tester at tester dot ca>
|
Based on patch by: Olivier Crete <tester at tester dot ca>
|
||||||
|
|
167
gst/gstpad.c
167
gst/gstpad.c
|
@ -2962,9 +2962,9 @@ GstIterator *
|
||||||
gst_pad_iterate_internal_links_default (GstPad * pad)
|
gst_pad_iterate_internal_links_default (GstPad * pad)
|
||||||
{
|
{
|
||||||
GstIterator *res;
|
GstIterator *res;
|
||||||
GstElement *parent = NULL;
|
|
||||||
GList **padlist;
|
GList **padlist;
|
||||||
guint32 *cookie;
|
guint32 *cookie;
|
||||||
|
GMutex *lock;
|
||||||
gpointer owner;
|
gpointer owner;
|
||||||
GstIteratorDisposeFunction dispose;
|
GstIteratorDisposeFunction dispose;
|
||||||
|
|
||||||
|
@ -2995,9 +2995,13 @@ gst_pad_iterate_internal_links_default (GstPad * pad)
|
||||||
padlist = &data->list;
|
padlist = &data->list;
|
||||||
owner = data;
|
owner = data;
|
||||||
dispose = (GstIteratorDisposeFunction) int_link_iter_data_free;
|
dispose = (GstIteratorDisposeFunction) int_link_iter_data_free;
|
||||||
|
/* reuse the pad lock, it's all we have here */
|
||||||
|
lock = GST_OBJECT_GET_LOCK (pad);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
GstElement *parent;
|
||||||
|
|
||||||
GST_OBJECT_LOCK (pad);
|
GST_OBJECT_LOCK (pad);
|
||||||
parent = GST_PAD_PARENT (pad);
|
parent = GST_PAD_PARENT (pad);
|
||||||
if (!parent || !GST_IS_ELEMENT (parent))
|
if (!parent || !GST_IS_ELEMENT (parent))
|
||||||
|
@ -3016,11 +3020,12 @@ gst_pad_iterate_internal_links_default (GstPad * pad)
|
||||||
cookie = &parent->pads_cookie;
|
cookie = &parent->pads_cookie;
|
||||||
owner = parent;
|
owner = parent;
|
||||||
dispose = (GstIteratorDisposeFunction) gst_object_unref;
|
dispose = (GstIteratorDisposeFunction) gst_object_unref;
|
||||||
|
lock = GST_OBJECT_GET_LOCK (parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
res = gst_iterator_new_list (GST_TYPE_PAD,
|
res = gst_iterator_new_list (GST_TYPE_PAD,
|
||||||
GST_OBJECT_GET_LOCK (parent),
|
lock, cookie, padlist, owner, (GstIteratorItemFunction) iterate_pad,
|
||||||
cookie, padlist, owner, (GstIteratorItemFunction) iterate_pad, dispose);
|
dispose);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
@ -3156,52 +3161,86 @@ gst_pad_get_internal_links (GstPad * pad)
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
|
gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
|
||||||
{
|
{
|
||||||
GList *orig, *pads;
|
gboolean result = FALSE;
|
||||||
gboolean result;
|
GstIterator *iter;
|
||||||
|
gboolean done = FALSE;
|
||||||
|
gpointer item;
|
||||||
|
GstPad *eventpad;
|
||||||
|
GList *pushed_pads = NULL;
|
||||||
|
|
||||||
GST_INFO_OBJECT (pad, "Sending event %p (%s) to all internally linked pads",
|
GST_INFO_OBJECT (pad, "Sending event %p (%s) to all internally linked pads",
|
||||||
event, GST_EVENT_TYPE_NAME (event));
|
event, GST_EVENT_TYPE_NAME (event));
|
||||||
|
|
||||||
orig = pads = gst_pad_get_internal_links (pad);
|
iter = gst_pad_iterate_internal_links (pad);
|
||||||
|
|
||||||
if (!pads) {
|
if (!iter)
|
||||||
/* If this is a sinkpad and we don't have pads to send the event to, we
|
goto no_iter;
|
||||||
* return TRUE. This is so that when using the default handler on a sink
|
|
||||||
* element, we don't fail to push it. */
|
|
||||||
result = (GST_PAD_DIRECTION (pad) == GST_PAD_SINK);
|
|
||||||
} else {
|
|
||||||
/* we have pads, the result will be TRUE if one of the pads handled the
|
|
||||||
* event in the code below. */
|
|
||||||
result = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (pads) {
|
while (!done) {
|
||||||
GstPad *eventpad = GST_PAD_CAST (pads->data);
|
switch (gst_iterator_next (iter, &item)) {
|
||||||
|
case GST_ITERATOR_OK:
|
||||||
|
eventpad = GST_PAD (item);
|
||||||
|
|
||||||
pads = g_list_next (pads);
|
/* if already pushed, skip */
|
||||||
|
if (g_list_find (pushed_pads, eventpad)) {
|
||||||
|
gst_object_unref (item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) {
|
if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) {
|
||||||
/* for each pad we send to, we should ref the event; it's up
|
/* for each pad we send to, we should ref the event; it's up
|
||||||
* to downstream to unref again when handled. */
|
* to downstream to unref again when handled. */
|
||||||
GST_LOG_OBJECT (pad, "Reffing and sending event %p (%s) to %s:%s",
|
GST_LOG_OBJECT (pad, "Reffing and sending event %p (%s) to %s:%s",
|
||||||
event, GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (eventpad));
|
event, GST_EVENT_TYPE_NAME (event),
|
||||||
gst_event_ref (event);
|
GST_DEBUG_PAD_NAME (eventpad));
|
||||||
result |= gst_pad_push_event (eventpad, event);
|
gst_event_ref (event);
|
||||||
} else {
|
result |= gst_pad_push_event (eventpad, event);
|
||||||
/* we only send the event on one pad, multi-sinkpad elements
|
} else {
|
||||||
* should implement a handler */
|
/* we only send the event on one pad, multi-sinkpad elements
|
||||||
GST_LOG_OBJECT (pad, "sending event %p (%s) to one sink pad %s:%s",
|
* should implement a handler */
|
||||||
event, GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (eventpad));
|
GST_LOG_OBJECT (pad, "sending event %p (%s) to one sink pad %s:%s",
|
||||||
result = gst_pad_push_event (eventpad, event);
|
event, GST_EVENT_TYPE_NAME (event),
|
||||||
goto done;
|
GST_DEBUG_PAD_NAME (eventpad));
|
||||||
|
result = gst_pad_push_event (eventpad, event);
|
||||||
|
done = TRUE;
|
||||||
|
event = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pushed_pads = g_list_prepend (pushed_pads, eventpad);
|
||||||
|
|
||||||
|
gst_object_unref (item);
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_RESYNC:
|
||||||
|
/* FIXME, if we want to reset the result value we need to remember which
|
||||||
|
* pads pushed with which result */
|
||||||
|
gst_iterator_resync (iter);
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_ERROR:
|
||||||
|
GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads");
|
||||||
|
done = TRUE;
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_DONE:
|
||||||
|
done = TRUE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* we handled the incoming event so we unref once */
|
gst_iterator_free (iter);
|
||||||
GST_LOG_OBJECT (pad, "handled event %p, unreffing", event);
|
|
||||||
gst_event_unref (event);
|
|
||||||
|
|
||||||
done:
|
no_iter:
|
||||||
g_list_free (orig);
|
|
||||||
|
/* If this is a sinkpad and we don't have pads to send the event to, we
|
||||||
|
* return TRUE. This is so that when using the default handler on a sink
|
||||||
|
* element, we don't fail to push it. */
|
||||||
|
if (!pushed_pads)
|
||||||
|
result = (GST_PAD_DIRECTION (pad) == GST_PAD_SINK);
|
||||||
|
|
||||||
|
g_list_free (pushed_pads);
|
||||||
|
|
||||||
|
/* we handled the incoming event so we unref once */
|
||||||
|
if (event) {
|
||||||
|
GST_LOG_OBJECT (pad, "handled event %p, unreffing", event);
|
||||||
|
gst_event_unref (event);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -3257,32 +3296,54 @@ gst_pad_dispatcher (GstPad * pad, GstPadDispatcherFunction dispatch,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
gboolean res = FALSE;
|
gboolean res = FALSE;
|
||||||
GList *int_pads, *orig;
|
GstIterator *iter = NULL;
|
||||||
|
gboolean done = FALSE;
|
||||||
|
gpointer item;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||||
g_return_val_if_fail (dispatch != NULL, FALSE);
|
g_return_val_if_fail (dispatch != NULL, FALSE);
|
||||||
|
|
||||||
orig = int_pads = gst_pad_get_internal_links (pad);
|
iter = gst_pad_iterate_internal_links (pad);
|
||||||
|
|
||||||
while (int_pads) {
|
if (!iter)
|
||||||
GstPad *int_pad = GST_PAD_CAST (int_pads->data);
|
goto no_iter;
|
||||||
GstPad *int_peer = gst_pad_get_peer (int_pad);
|
|
||||||
|
|
||||||
if (int_peer) {
|
while (!done) {
|
||||||
GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s",
|
switch (gst_iterator_next (iter, &item)) {
|
||||||
GST_DEBUG_PAD_NAME (int_peer));
|
case GST_ITERATOR_OK:
|
||||||
res = dispatch (int_peer, data);
|
{
|
||||||
gst_object_unref (int_peer);
|
GstPad *int_pad = GST_PAD_CAST (item);
|
||||||
if (res)
|
GstPad *int_peer = gst_pad_get_peer (int_pad);
|
||||||
|
|
||||||
|
if (int_peer) {
|
||||||
|
GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s",
|
||||||
|
GST_DEBUG_PAD_NAME (int_peer));
|
||||||
|
done = res = dispatch (int_peer, data);
|
||||||
|
gst_object_unref (int_peer);
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (int_pad, "no peer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gst_object_unref (item);
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_RESYNC:
|
||||||
|
gst_iterator_resync (iter);
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_ERROR:
|
||||||
|
done = TRUE;
|
||||||
|
GST_ERROR_OBJECT (pad, "Could not iterate internally linked pads");
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_DONE:
|
||||||
|
done = TRUE;
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
GST_DEBUG_OBJECT (int_pad, "no peer");
|
|
||||||
}
|
}
|
||||||
int_pads = g_list_next (int_pads);
|
|
||||||
}
|
}
|
||||||
g_list_free (orig);
|
gst_iterator_free (iter);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (pad, "done, result %d", res);
|
GST_DEBUG_OBJECT (pad, "done, result %d", res);
|
||||||
|
|
||||||
|
no_iter:
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue