Недавно мне потребовалась функция, которую я мог бы использовать, чтобы гарантировать синхронное выполнение данного блока в конкретной очереди последовательной отправки. Возможно, что эта общая функция может быть вызвана из уже запущенной в этой очереди, поэтому мне нужно было проверить этот случай, чтобы предотвратить тупик от синхронной отправки в одну очередь.
Для этого я использовал следующий код:
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()
для выполнения подобных сравнений, и я вижу эту формулировку в заголовках:
Рекомендуется только для отладки и ведения журнала:
Код не должен делать никаких предположений о возвращенной очереди, если он не является одной из глобальных очередей или очереди, которые сам код создано. Код не должен предполагать, что синхронное выполнение на очередь находится в безопасности от тупиковой ситуации, если эта очередь не та, которая была возвращена dispatch_get_current_queue().
Кроме того, в iOS 6.0 (но еще не для Mountain Lion) заголовки GCD теперь отмечают эту функцию как устаревшую.
Похоже, я не должен использовать эту функцию таким образом, но я не уверен, что я должен использовать на своем месте. Для функции, подобной приведенной выше, ориентированной на основную очередь, я мог бы использовать [NSThread isMainThread]
, но как я могу проверить, запущен ли я в одной из моих пользовательских последовательных очередей, чтобы предотвратить блокировку?