summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2012-07-16 15:25:46 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2012-07-16 15:25:46 +0200
commitcce71223d7b2f8227301f0724a18fc647f0cfd06 (patch)
tree43c79b93484bfc6cf8d4e500142a246e24d0982b
parent981387682584860c09930f277b072aafec1428a0 (diff)
pad: don't call pad block callbacks multiple times
Ensure that when multiple threads try to block a pad, only one of the threads calls the callback. We do this by checking if the callback was already called. The previous version unconditionally called the callback and then checked if it was already called... Also only call the unblock callback once from the first thread that unblocks. Fixes https://bugzilla.gnome.org/show_bug.cgi?id=679950
-rw-r--r--gst/gstpad.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/gst/gstpad.c b/gst/gstpad.c
index c04c974bc..f2547c56f 100644
--- a/gst/gstpad.c
+++ b/gst/gstpad.c
@@ -4059,7 +4059,7 @@ handle_pad_block (GstPad * pad)
gst_object_ref (pad);
while (GST_PAD_IS_BLOCKED (pad)) {
- do {
+ while (!pad->abidata.ABI.block_callback_called) {
/* we either have a callback installed to notify the block or
* some other thread is doing a GCond wait. */
callback = pad->block_callback;
@@ -4076,13 +4076,15 @@ handle_pad_block (GstPad * pad)
/* we released the lock, recheck flushing */
if (GST_PAD_IS_FLUSHING (pad))
goto flushing;
+ /* .. and blocking state */
+ if (!GST_PAD_IS_BLOCKED (pad))
+ break;
} else {
/* no callback, signal the thread that is doing a GCond wait
* if any. */
GST_PAD_BLOCK_BROADCAST (pad);
}
- } while (pad->abidata.ABI.block_callback_called == FALSE
- && GST_PAD_IS_BLOCKED (pad));
+ }
/* OBJECT_LOCK could have been released when we did the callback, which
* then could have made the pad unblock so we need to check the blocking
@@ -4107,18 +4109,21 @@ handle_pad_block (GstPad * pad)
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got unblocked");
- /* when we get here, the pad is unblocked again and we perform
- * the needed unblock code. */
- callback = pad->block_callback;
- if (callback) {
- /* we need to call the callback */
- user_data = pad->block_data;
- GST_OBJECT_UNLOCK (pad);
- callback (pad, FALSE, user_data);
- GST_OBJECT_LOCK (pad);
- } else {
- /* we need to signal the thread waiting on the GCond */
- GST_PAD_BLOCK_BROADCAST (pad);
+ if (!pad->abidata.ABI.block_callback_called) {
+ /* when we get here, the pad is unblocked again and we perform
+ * the needed unblock code. */
+ callback = pad->block_callback;
+ pad->abidata.ABI.block_callback_called = TRUE;
+ if (callback) {
+ /* we need to call the callback */
+ user_data = pad->block_data;
+ GST_OBJECT_UNLOCK (pad);
+ callback (pad, FALSE, user_data);
+ GST_OBJECT_LOCK (pad);
+ } else {
+ /* we need to signal the thread waiting on the GCond */
+ GST_PAD_BLOCK_BROADCAST (pad);
+ }
}
gst_object_unref (pad);