Reputation: 6862
I'm using the open source software TMCache. It saves expensive data to cache asynchronously. There is also a synchronous method.
It uses dispatch_semaphore_wait()
to wait until the operation is over.
- (id)objectForKey:(NSString *)key
{
if (!key)
return nil;
__block id objectForKey = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self objectForKey:key block:^(TMCache *cache, NSString *key, id object) {
objectForKey = object;
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
return objectForKey;
}
This works fine on my machine. On a colleague's machine it does not.
The program stops working at dispatch_semaphore_wait()
. It's absolutely not reproducible for me.
The method above is called in tableView:viewForTableColumn:row:
,
so it's executed in the main queue.
Any idea why this is happening? Must I use the method in another queue?
Upvotes: 0
Views: 3212
Reputation: 1001
Most likely you are running out of threads. The dispatch_semaphore_signal(semaphore) , which should release the dispatch_semaphore_wait() needs to be executed in a new thread (see objectForKey:block: for details). If OS fails to dispatch that new thread, you stuck, as nobody will send you the dispatch_semaphore_signal.
How often and when it happens depends on computer/device speed, how fast you scroll the table etc. That's why you can't reproduce this issue on your computer.
The quick solution here is to keep number of threads low, by employing the same dispatch semaphore approach with timeout set to DISPATCH_TIME_NOW, as you may not block the main queue.
I would prefer changing the way TMCache.m works, though. I believe that dispatch semaphores approach is not justified in this case - gaining the code brevity (wrapping async method into a synchronous counterpart) at the expense of reliability does not seem right to me. I used to wrap synchronous methods with async ones, but not vice versa.
Here is the fix
https://github.com/rushproject/TMCache
Note that only synchronous objectForKey methods were patched.
Upvotes: 6