Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get current dispatch queue?

People also ask

How do I find the current dispatch queue?

To get the dispatch queue object you can use [NSOperationQueue currentQueue]. underlyingQueue , which returns your currrent queue as a dispatch_queue_t . - works for main queue!

What is a dispatch queue?

Dispatch queues are FIFO queues to which your application can submit tasks in the form of block objects. Dispatch queues execute tasks either serially or concurrently. Work submitted to dispatch queues executes on a pool of threads managed by the system.

How many types of dispatch queues are there?

Four such queues exist, each with different priorities: high, default, low and background. The background priority queue has the lowest priority and is throttled in any I/O activity to minimize negative system impact. Custom queues: Queues you create that can be serial or concurrent.

What is Dispatch_get_global_queue?

Returns a system-defined global concurrent queue with the specified quality-of-service class.


If you are working with an NSOperationQueue, it can provide the current dispatch queue for you.

NSOperationQueue has the class function [NSOperationQueue currentQueue], which returns the current queue as a NSOperationQueue object. To get the dispatch queue object you can use [NSOperationQueue currentQueue].underlyingQueue, which returns your currrent queue as a dispatch_queue_t.

Swift 3:

if let currentDispatch = OperationQueue.current?.underlyingQueue {
    print(currentDispatch)
}

- works for main queue!


With the deprecation of dispatch_get_current_queue() there is effectively no way to know what queue you're executing on. If you peruse the GCD sources, you'll eventually see that this is because there may be multiple answers to the question "what queue am I executing on?" (Because queues eventually target one of the global queues, etc.)

If you want to guarantee that a future block is run on a specific queue, then the only way is to make your API accept a queue as a parameter along with the completion block. This lets the caller decide where the completion gets executed.

If simply knowing whether the caller is on the main thread or not is enough, you can use +[NSThread isMainThread] to find out. In the common case, all blocks executing on the main GCD queue will be executing on the main thread. (One exception to this rule is if your application uses dispatch_main() in lieu of a main run loop, you will have to use dispatch_get_specific and friends to detect with certainty that you are executing on the main queue -- this is a comparatively rare circumstance.) More commonly, note that not all code that executes on the main thread executes on the main queue via GCD; GCD is subordinate to the main thread runloop. For your specific case it sounds like that might be enough.


You do have the option of "dispatch_get_current_queue()", however the iOS 6.1 SDK defines this API with these disclaimers:

"Recommended for debugging and logging purposes only:"

and

"This function is deprecated and will be removed in a future release.".

Here's another related question with some alternatives you can consider if you want code that's future-proof.


With the deprecation of dispatch_get_current_queue() you cannot directly get a pointer to the queue you are running on, however you do can get the current queue's label by calling dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) and that does give you some flexibility.

You can always check if you are on that specific queue just by comparing their labels, so in your case if you don't want to force it on main queue, when you entered the method you can just utilize the following flag:

let isOnMainQueue = (dispatch_queue_get_label(dispatch_get_main_queue()) == dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL))

If you are running on the global queue, you will respectfully get the queue's label associated with it's QOS type, which can be one of the following:

com.apple.root.user-interactive-qos //qos_class_t(rawValue: 33)
com.apple.root.user-initiated-qos   //qos_class_t(rawValue: 25)
com.apple.root.default-qos          //qos_class_t(rawValue: 21)  
com.apple.root.utility-qos          //qos_class_t(rawValue: 17)
com.apple.root.background-qos       //qos_class_t(rawValue: 9) 

And then you can use dispatch_get_global_queue(qos_class_self(), 0) which will give you back that same global queue you are running on.

But I believe Apple particularly discourages us from bounding the logic to the queue we got called on, so better utilising this for exclusively debugging purposes.


Based on Oleg Barinov answer

Details

  • Swift 5.1, Xcode 11.3.1

Solution

import Foundation

// MARK: private functionality

extension DispatchQueue {

    private struct QueueReference { weak var queue: DispatchQueue? }

    private static let key: DispatchSpecificKey<QueueReference> = {
        let key = DispatchSpecificKey<QueueReference>()
        setupSystemQueuesDetection(key: key)
        return key
    }()

    private static func _registerDetection(of queues: [DispatchQueue], key: DispatchSpecificKey<QueueReference>) {
        queues.forEach { $0.setSpecific(key: key, value: QueueReference(queue: $0)) }
    }

    private static func setupSystemQueuesDetection(key: DispatchSpecificKey<QueueReference>) {
        let queues: [DispatchQueue] = [
                                        .main,
                                        .global(qos: .background),
                                        .global(qos: .default),
                                        .global(qos: .unspecified),
                                        .global(qos: .userInitiated),
                                        .global(qos: .userInteractive),
                                        .global(qos: .utility)
                                    ]
        _registerDetection(of: queues, key: key)
    }
}

// MARK: public functionality

extension DispatchQueue {
    static func registerDetection(of queue: DispatchQueue) {
        _registerDetection(of: [queue], key: key)
    }

    static var currentQueueLabel: String? { current?.label }
    static var current: DispatchQueue? { getSpecific(key: key)?.queue }
}

Usage

Detect system queue

DispatchQueue.currentQueueLabel
DispatchQueue.current
DispatchQueue.global(qos: .default) == DispatchQueue.current
DispatchQueue.main === DispatchQueue.current

Detect custom queue

let queue = DispatchQueue(label: "queue-sample")
DispatchQueue.registerDetection(of: queue)
if DispatchQueue.current == queue { ... }

Sample

Do not forget to paste the solution code here.

func subTest(queue: DispatchQueue) {
    queue.async {
        print("--------------------------------------------------------")
        print("queue label: \(DispatchQueue.currentQueueLabel ?? "nil")")
        print("print DispatchQueue.current: \(String(describing: DispatchQueue.current))")
        print("print queue == DispatchQueue.current: \(queue == DispatchQueue.current)")
        print("print queue === DispatchQueue.current: \(queue === DispatchQueue.current)")
        print("DispatchQueue.main == DispatchQueue.current: \(DispatchQueue.main == DispatchQueue.current)\n")
    }
}

func test() {
    subTest(queue: DispatchQueue.main)
    sleep(1)
    subTest(queue: DispatchQueue.global(qos: .default))
    sleep(1)
    subTest(queue: DispatchQueue.global(qos: .utility))
    sleep(1)

    let queue = DispatchQueue(label: "queue-sample")
    DispatchQueue.registerDetection(of: queue)
    subTest(queue: queue)
    sleep(1)
}

test()
DispatchQueue.global(qos: .default).async {
    test()
}

Result

--------------------------------------------------------
queue label: com.apple.root.default-qos
print DispatchQueue.current: Optional(<OS_dispatch_queue_global: com.apple.root.default-qos[0x7fff89eb47c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = [0x0], width = 0xfff, state = 0x0060000000000000, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false

--------------------------------------------------------
queue label: com.apple.root.utility-qos
print DispatchQueue.current: Optional(<OS_dispatch_queue_global: com.apple.root.utility-qos[0x7fff89eb46c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = [0x0], width = 0xfff, state = 0x0060000000000000, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false

--------------------------------------------------------
queue label: queue-sample
print DispatchQueue.current: Optional(<OS_dispatch_queue_serial: queue-sample[0x600000275780] = { xref = 7, ref = 3, sref = 2, target = com.apple.root.default-qos.overcommit[0x7fff89eb4840], width = 0x1, state = 0x0060002500000b01, enqueued, max qos 5, draining on 0xb03, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false

--------------------------------------------------------
queue label: com.apple.main-thread
print DispatchQueue.current: Optional(<OS_dispatch_queue_main: com.apple.main-thread[0x7fff89eb43c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x7fff89eb4840], width = 0x1, state = 0x001ffe9000000300, dirty, in-flight = 0, thread = 0x303 }>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: true

--------------------------------------------------------
queue label: com.apple.main-thread
print DispatchQueue.current: Optional(<OS_dispatch_queue_main: com.apple.main-thread[0x7fff89eb43c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x7fff89eb4840], width = 0x1, state = 0x001ffe9000000300, dirty, in-flight = 0, thread = 0x303 }>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: true

--------------------------------------------------------
queue label: com.apple.root.default-qos
print DispatchQueue.current: Optional(<OS_dispatch_queue_global: com.apple.root.default-qos[0x7fff89eb47c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = [0x0], width = 0xfff, state = 0x0060000000000000, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false

--------------------------------------------------------
queue label: com.apple.root.utility-qos
print DispatchQueue.current: Optional(<OS_dispatch_queue_global: com.apple.root.utility-qos[0x7fff89eb46c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = [0x0], width = 0xfff, state = 0x0060000000000000, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false

--------------------------------------------------------
queue label: queue-sample
print DispatchQueue.current: Optional(<OS_dispatch_queue_serial: queue-sample[0x60000027a280] = { xref = 7, ref = 3, sref = 2, target = com.apple.root.default-qos.overcommit[0x7fff89eb4840], width = 0x1, state = 0x0060002500000b01, enqueued, max qos 5, draining on 0xb03, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false