I was in a situation where I was calling a method that was calling a method that was calling a method that:
While this is a fine async architecture, it would be useful to construct a convenience “synchronous” wrapper so that you can call a function to do the network request that dispatches all this nonsense and just spins and waits for the result and returns the result to the caller. In other words, it reduces to the problem of building dispatch_sync out of dispatch_async. However, this is a lot more complicated than it sounds. The naive implementation:
The problem is, how do we do that “spin” step?
The solution is buried deep in the manpage for dispatch_async (of all places!). It reads:
Conceptually, dispatch_sync() is a convenient wrapper around dispatch_async() with the addition of a
semaphore to wait for completion of the block, and a wrapper around the block to signal its completion.
Aha, dispatch semaphores! It turns out that dispatch_semaphore_wait will spin in such a way as to allow dispatch events while waiting for the signal. The final code block:
-(void) beginSynchronousRequestWithPrefix:(NSString*) uprefix { void (^myBlock)(NSObject*) = [self.block retain]; dispatch_semaphore_t holdOn = dispatch_semaphore_create(0); self.block = ^(NSObject * obj) { myBlock(obj); dispatch_semaphore_signal(holdOn); }; dispatch_async(self.block...) dispatch_semaphore_wait(holdOn, DISPATCH_TIME_FOREVER); [myBlock release]; }
Comments
Comments are closed.