21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

dispatch_syncをデッドロックしないよう安全に呼ぶ

Last updated at Posted at 2015-02-17

dispatch_syncは同一キュー内で呼び出すとデッドロックに陥ります。

今までメインスレッドを安全に同期的に呼び出す際は以下のように行っていました。

func safe_dispatch_sync_main(block: dispatch_block_t) {
    if NSThread.isMainThread() {
        block()
    } else {
        dispatch_sync(dispatch_get_main_queue(), block)
    }
}

今回、dispatch_queue_createで作成したキューを同期的に実行する方法がないか探した結果をメモします。

結論

dispatch_queue_get_labelを利用するとqueueのラベル名が取得できます。
ラベル名が異なればdispatch_syncを呼び出し、同じであればブロックを直接実行します。

func safe_dispatch_sync(queue: dispatch_queue_t, block: dispatch_block_t) {
    
    let queue_label = dispatch_queue_get_label(queue)
    let current_label = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)
    if queue_label != current_label {
        dispatch_sync(queue, block)
    } else {
        block()
    }
}

補足

同じキューかどうかかの判断をラベル名で行っているため、同じラベル名で複数作成されると別キューで実行される可能性があります。
※ただdispatch_syncには原理的に入らないのでデッドロックになる最悪のパターンは回避できると思います。
※ラベル名をUUIDやランダムで作成するとより厳密に判別できると思います。

21
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?