target parameter in DispatchQueue
Asked Answered
C

4

19

In Swift 3, the creation of a DispatchQueue instance:

DispatchQueue(label: String,
              qos: DispatchQoS,
              attributes: DispatchQueue.Attributes,
              autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency, 
              target: DispatchQueue?)

I see the sample codes from StackOverFlow, it can be nil, .global() or .main, what's the meaning of this target parameter?

I guess .main means the queue will run on main thread, but what for .nil or .global() ?

Covenantor answered 16/11, 2016 at 14:25 Comment(0)
T
14

There's no documentation for Swift so I dropped back to the old documentation for GCD. The closest that I've found is for the function dispatch_set_target_queue:

An object's target queue is responsible for processing the object. The target queue determines the queue on which the object's finalizer is invoked. In addition, modifying the target queue of some objects changes their behavior:

Dispatch queues:

A dispatch queue's priority is inherited from its target queue. Use the dispatch_get_global_queue function to obtain a suitable target queue of the desired priority.

If you submit a block to a serial queue, and the serial queue’s target queue is a different serial queue, that block is not invoked concurrently with blocks submitted to the target queue or to any other queue with that same target queue.

So looks like the target queue does 2 things:

  1. Provide the priority for your new queue
  2. Executes the finalizer (deinit) of all objects in your queue

Reading between the lines, there are some sychronization between your queue and the target queue. I don't have Xcode at the moment so I can't test.

Thereby answered 16/11, 2016 at 15:8 Comment(1)
1. Provide the priorty for your new queue. -> then what does the qos attribute does.Matos
C
12

TLDR: specifying a target queue will provide minimum QoS for your queue and will redirect all blocks to target queue while preserving the semantics of your queue.

For example, consider queue A to be concurrent and queue B to be serial which targets to A:

// serial A -> targets concurrent B

// concurrent queue A
let a = DispatchQueue(label: "A", attributes: .concurrent)

// serial queue B targeting concurrent queue A
let b = DispatchQueue(label: "B", target: a)

// next two blocks will be executed concurrently on A
a.async {
    print("1")
}
a.async {
    print("2")
}

// next two blocks will be executed serially on A
b.async {
    print("3")
}
b.async {
    print("4")
}

https://developer.apple.com/documentation/dispatch/dispatchobject/1452989-settarget

Redirects all blocks from the current dispatch queue to the specified target queue. Use target queues to redirect work from several different queues onto a single queue. You might do this to minimize the total number of threads your app uses, while still preserving the execution semantics you need. The system doesn't allocate threads to the dispatch queue if it has a target queue, unless that target queue is a global concurrent queue.

The target queue defines where blocks run, but it doesn't change the semantics of the current queue. Blocks submitted to a serial queue still execute serially, even if the underlying target queue is concurrent. In addition, you can't create concurrency where none exists. If a queue and its target queue are both serial, submitting blocks to both queues doesn't cause those blocks to run concurrently. The blocks still run serially in the order the target queue receives them.

A dispatch queue inherits the minimum quality-of-service level from its target queue.

Cheatham answered 9/10, 2020 at 19:37 Comment(0)
A
7

The target is explained by apple as:

"A dispatch queue's priority is inherited from its target queue. Use the dispatch_get_global_queue function to obtain a suitable target queue of the desired priority. If you submit a block to a serial queue, and the serial queue’s target queue is a different serial queue, that block is not invoked concurrently with blocks submitted to the target queue or to any other queue with that same target queue."

https://developer.apple.com/reference/dispatch/1452989-dispatch_set_target_queue

1. .main will run on the main thread. The main thread is used primarily for UI work so you should be cautious when using this thread for work that is not UI related because it could make the UI hang or appear unresponsive. This queue has the highest priority.

2. .global is primarily used for other work that is not UI related. and schedules blocks when threads become available. the global queue has three priorities Low, Default & High. This queue has the second highest priority with 3 different types.

3. nil is the lowest priority and will be lower than any global queue. it has no priority, it just needs to get done.

Summary

.main as target for UI work

.global as target for other work that needs to be done as soon as possible

nil as target for work that just needs to get done at some point (your not bothered when)

Aerogram answered 16/11, 2016 at 15:8 Comment(2)
It's still confusing. What is the "finalizer" that the object gonna invoke? And what's the relationship with Qos?Fireworm
Each queue has its own priority as I explained in my answer. Qos means "Quality of Service" and allows you categorise individual pieces of work in that queue. By describing the work using Qos you can ensure it is energy efficient and also set a sub priority within the queue. So lets say you have two pieces of UI work that execute on the main thread. You can state that work1 is higher priority that work2 by specifying a Qos.Aerogram
P
0

the target is for setting up the target queue hierarchy. It is not for QoS. It is for controlling # of threads and of the target queue hierarchy.

QoS and the characteristic of the queue you're going to create will remain the same. But by doing this, the performance will differ. For more information, refer to WWDC videos.

Plumcot answered 4/9, 2020 at 8:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.