I want to call a completion handler synchronously inside a critical section (using @synchronized block). I am trying to wait for completion handler using semaphore, but the semaphore signal is never called.
Here is what I am doing:
NSNumber *lock = 0;
@synchronized(lock) {
// critical section code begins
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self someMethodWithCompletionHandler:^(BOOL result) {
// execute completion handler
dispatch_semaphore_signal(sema);
}];
// wait for completion block to finish
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
// critical section code ends
}
I believe, due to @synchronized block the completion handler is called on the same thread as the caller which results in a deadlock. Is that right? If yes, how else can this be achieved?
Thanks!
I would avoid
@synchronized
and use a serial dispatch queue to serialize the work in the critical section. You can still use a semaphore to block the serial dispatch queue until the asynchronous operation is complete.The serial dispatch queue guarantees that only one block of code can enter the critical section at a time and there is no risk of blocking the main queue.
You will need to create the serial queue during your class initialisation