diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2012-07-16 15:25:46 +0200 |
---|---|---|
committer | Wim Taymans <wim.taymans@collabora.co.uk> | 2012-07-16 15:25:46 +0200 |
commit | cce71223d7b2f8227301f0724a18fc647f0cfd06 (patch) | |
tree | 43c79b93484bfc6cf8d4e500142a246e24d0982b | |
parent | 981387682584860c09930f277b072aafec1428a0 (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.c | 35 |
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); |