我如何validation我在给定的GCD队列上运行而不使用dispatch_get_current_queue()?
最近,我需要一个函数来保证特定串行调度队列上给定块的同步执行。 有可能这个共享函数可以从已经在那个队列上运行的东西中调用,所以我需要检查这种情况,以防止从同步调度到同一队列的死锁。
我使用如下代码来做到这一点:
void runSynchronouslyOnVideoProcessingQueue(void (^block)(void)) { dispatch_queue_t videoProcessingQueue = [GPUImageOpenGLESContext sharedOpenGLESQueue]; if (dispatch_get_current_queue() == videoProcessingQueue) { block(); } else { dispatch_sync(videoProcessingQueue, block); } }
这个函数依赖于使用dispatch_get_current_queue()
来确定这个函数正在运行的队列的身份,并将其与目标队列进行比较。 如果有一个匹配,它知道只是在没有派发到该队列的情况下内联运行该块,因为该函数已经在其上运行。
我曾经听说过是否使用dispatch_get_current_queue()
来进行比较是正确的,我在头文件中看到了这个字眼:
build议仅用于debugging和logging目的:
代码不能对返回的队列做任何假设,除非它是全局队列或代码本身创build的队列之一。 如果该队列不是由dispatch_get_current_queue()返回的队列,则代码不能假定队列上的同步执行是安全的。
此外,在iOS 6.0(但尚未山狮),GCD标头现在标记为不推荐使用此function。
这听起来像我不应该以这种方式使用这个函数,但我不知道我应该用什么来代替它。 对于像上面那样针对主队列的函数,我可以使用[NSThread isMainThread]
,但是如何检查我是否在我的自定义串行队列中运行,以便可以防止死锁?
使用dispatch_queue_set_specific()
分配你想要的标识符。 然后你可以使用dispatch_get_specific()
来检查你的标识符。
请记住, dispatch_get_specific()
是很好的,因为它将从当前队列开始,然后如果当前没有设置密钥,则会遍历目标队列。 这通常不重要,但在某些情况下可能会有用。
这是一个非常简单的解决scheme。 这不像性能使用dispatch_queue_set_specific
和dispatch_get_specific
– 我没有这个指标。
#import <libkern/OSAtomic.h> BOOL dispatch_is_on_queue(dispatch_queue_t queue) { int key; static int32_t incrementer; CFNumberRef value = CFBridgingRetain(@(OSAtomicIncrement32(&incrementer))); dispatch_queue_set_specific(queue, &key, value, nil); BOOL result = dispatch_get_specific(&key) == value; dispatch_queue_set_specific(queue, &key, nil, nil); CFRelease(value); return result; }