dispatch_suspend() does not affect child queues
Hi libdispatch team, I have a question regarding the indented behavior and use of dispatch multiple queues: If a queue A has its target set to queue B and queue B is suspended with dispatch_suspend(B), why are blocks from queue A still executed? I was expecting dispatch_suspend(X) to silence the entire subsystem of queues directly or indirectly targeting queue X, but it does not. Instead, only the queue X I pass in is suspended, all other queues seem unaffected. I attached an Xcode project (tested on OS X 10.8.0) to demonstrate the issue. I am using two serial queues "low" and "high" to implement the front enqueue pattern to execute emergency work: The "low" queue targets the "high" queue. Blocks are usually enqueued on "low", emergency work is enqueued on "high" so it can bypass all the work queued in "low". This works fine when line 27 is commented out. However, as soon as I give a different subsystem of my code (imagine this being a third party library) access to the "low" queue, this subsystem can create a hidden private queue that feeds into "low". The emergency block will now experience undue delay, because suspending the "low" queue does not suspend the private queue. I would like to understand the rationale for this behavior of libdispatch. Michael
Michael, On Aug 5, 2012, at 10:06, Michael Roitzsch <mroi@os.inf.tu-dresden.de> wrote:
Hi libdispatch team,
I have a question regarding the indented behavior and use of dispatch multiple queues: If a queue A has its target set to queue B and queue B is suspended with dispatch_suspend(B), why are blocks from queue A still executed?
they are not, but unless dispatch_suspend(B) is executed from B itself, suspension is asynchronous and non-preemptive, i.e. suspension only takes effect when queue state is checked before the next item on B is executed (but does not affect the current item on B). Importantly, because of the way target queues work, this means that many items on queue A can execute after the call to dispatch_suspend(B) before B actually becomes suspended (queue A as a whole is a single workitem on queue B so queue A may stay the "current item" on queue B for many items on A). If you need to know exactly when queue suspension takes effect you need to execute dispatch_suspend on the queue itself. HTH Daniel
I was expecting dispatch_suspend(X) to silence the entire subsystem of queues directly or indirectly targeting queue X, but it does not. Instead, only the queue X I pass in is suspended, all other queues seem unaffected.
I attached an Xcode project (tested on OS X 10.8.0) to demonstrate the issue. I am using two serial queues "low" and "high" to implement the front enqueue pattern to execute emergency work: The "low" queue targets the "high" queue. Blocks are usually enqueued on "low", emergency work is enqueued on "high" so it can bypass all the work queued in "low".
This works fine when line 27 is commented out. However, as soon as I give a different subsystem of my code (imagine this being a third party library) access to the "low" queue, this subsystem can create a hidden private queue that feeds into "low". The emergency block will now experience undue delay, because suspending the "low" queue does not suspend the private queue.
I would like to understand the rationale for this behavior of libdispatch.
Michael
<GCD-Test.zip>_______________________________________________ libdispatch-dev mailing list libdispatch-dev@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo/libdispatch-dev
Hi Daniel,
If a queue A has its target set to queue B and queue B is suspended with dispatch_suspend(B), why are blocks from queue A still executed?
they are not, but unless dispatch_suspend(B) is executed from B itself, suspension is asynchronous and non-preemptive, i.e. suspension only takes effect when queue state is checked before the next item on B is executed (but does not affect the current item on B).
I knew that it was non-preemptive, but I was not aware it was also asynchronous. But the manpage describes it that way, so I should have known.
(queue A as a whole is a single workitem on queue B so queue A may stay the "current item" on queue B for many items on A)
That was the missing bit to complete my mental picture. Thanks a lot for your explanation. Michael
participants (2)
-
Daniel A. Steffen
-
Michael Roitzsch