1

What happens if you dispatch_async a block of code on a queue that's currently blocked by it's own dispatch_sync operation? Do they lock or will the blocked queue continue after the dispatch_sync operation returns?

I have an object I created that manages access to a backing store (SQLite, in this case). It uses one concurrent GCD queue and any other objects that want to access the information from the store will pass a request to the manager along with a block that will be executed asynchronously. The essence of what happens is this (not actual code):

- (void) executeRequest:(StoreRequest *)request withCompletionBlock:(void(^)(NSInteger result)block{
    dispatch_queue_t currentContext = dispatch_get_current_queue();
    dispatch_async(_storeQueue, ^{
        NSInteger result = [_store executeRequest:request];
        if (block){
            dispatch_async(currentContext, ^{
                block(result);
            }
        }
    });
}

The real code is a bit more complex (I actually queue up and store requests/blocks/contexts to execute at the end of a run loop). I also use dispatch_barrier_async for write requests to prevent concurrent read/writing. This all works fine, but in certain situations I also need to perform a synchronous request on the store. Now this request doesn't need to be performed before any queued up operations, but I do need the requesting queue blocked until the operation is performed. This can be easily done:

- (NSInteger) executeRequest:(StoreRequest *)request{
    __block NSInteger result = 0;
    dispatch_sync(_storeQueue, ^{
        result = [_store executeRequest:request];
    });
    return result;
}

My question is this: What happens if a pending asynchronous operation placed before the synchronous operation dispatches a block of code asynchronously on the queue that is currently blocked by the synchronous dispatch. In other words, the above operation will dispatch its request at the end of the _store queue and wait. But it's quite possible (even likely) that the operations in front of it include asynchronous dispatches back to the waiting queue (for other operations). Will this lock the threads? Since the queued blocks are dispatched asynchronously the _store queue will never be blocked and therefore will finish, theoretically allowing the queue it's blocking to continue...but I'm not sure what happens with the blocks that were asynchronously dispatched or if dispatching anything to a block thread locks it up. I would assume that the blocked queue will continue, finish it's request and then the process the pending blocks, but I want to make sure.

Actually, now that I've written this all up, I'm pretty sure it'll work just fine, but I'm going to post this question anyway to make sure I'm not missing anything.

Aaron Hayman
  • 8,492
  • 2
  • 36
  • 63

2 Answers2

1

dispatch_async never blocks. It's that simple.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • Yeah, I wasn't worried about the `_store` queue since all it's dispatches were async. I was worried about the queue it was dispatching to since it that queue was blocked during the dispatch to it. Mostly, I just got things confused in my head and started thinking of queues as threads. I forget sometimes that queues aren't threads, so of course the dispatched block would just wait until the blocked queue returned and continue as normal. It's the whole point of GCD....perhaps more coffee would help. :) – Aaron Hayman Mar 21 '13 at 15:25
1

The dispatch_async itself never blocks. It appends the block to the end of the queue and returns immediately.

Will the block get executed? It depends. In a sequential queue, if one block is blocked, no other block will execute until that block gets unblocked and finishes. On a background queue, the queue can use multiple threads, so even if some blocks are blocked, it will just start other blocks. I haven't tried if there is a limit to the number of blocked blocks, but there's a good chance that all unblocked blocks will eventually execute and finish, and you are left with the blocked ones.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • GCD has a 64 thread limit. See http://stackoverflow.com/questions/15150308/workaround-on-the-threads-limit-in-grand-central-dispatch – Airsource Ltd Jul 10 '14 at 10:00