I'm having a hard time finding good examples on how to use these functions.
static void * kQueue1Key = "key1";
static void * kQueue2Key = "key2";
dispatch_queue_t queue1 = dispatch_queue_create("com.company.queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue2 = dispatch_queue_create("com.company.queue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_set_specific(queue1, kQueue1Key, (void *)kQueue1Key, NULL);
dispatch_queue_set_specific(queue2, kQueue2Key, (void *)kQueue2Key, NULL);
dispatch_sync(queue1, ^{
if(dispatch_get_specific(kQueue1Key))
{
NSLog(@"I'm expecting this line to run (A)");
dispatch_sync(queue2, ^{
NSLog(@"I'm expecting this line to run (B)");
if(dispatch_get_specific(kQueue2Key))
{
if(dispatch_get_specific(kQueue1Key))
{
NSLog(@"I'm expecting this line to run (C)");
}
else
{
[NSException raise:NSInternalInconsistencyException format:@"Should not end up here (C)"];
}
}
else
{
[NSException raise:NSInternalInconsistencyException format:@"Should not end up here (B)"];
}
});
}
else
{
[NSException raise:NSInternalInconsistencyException format:@"Should not end up here (A)"];
}
});
Result
I'm expecting this line to run (A)
I'm expecting this line to run (B)
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Should not end up here (C)'
Is it expected behavior? If I were to dispatch_sync to queue1 since I'm not on the queue I would deadlock. What am I missing?
dispatch_sync? Cause down this road lies eventual sadness (TLDR version: It can't work give the possibility of non-default queue targeting, and even if you assume your queues aren't cleverly targeted, the ancillary crap involved steals much (maybe all) of the performance benefit over standard recursive locking.) See also: stackoverflow.com/questions/19494167/…dispatch_get_specificwas the "new answer" to avoid mutex locks. If it's not, then what else does it offer?dispatch_queue_set/get_specificjust provide arbitrary, associative storage hanging off a queue.dispatch_get_specificallows you to read that storage without having a reference to the current queue. There is some added functionality in that if you have Qb that targets Qa and you set_specific on Qa, and then get_specific from a block executing on Qb, it will walk the targeting chain and return you the value from Qa.dispatch_queue_set/get_specificis that it's the recommended mechanism that one can use to replace uses of the now-deprecateddispatch_get_current_queuefunction.