I'm currently building a graph like framework where each node has a dispatch queue. To avoid possible context switching I'd like to set the target of a descendant node to the furthest direct ancestor node with similar dispatch queue context. The graph itself is tree-alike and avoids strong reference cycles by design. However I cannot proceed with that optimization because the setTarget(queue:)
method always crashes for custom queues, even in the following simple example:
import Dispatch
DispatchQueue.main.setTarget(queue: DispatchQueue.main) // Okay
DispatchQueue.global().setTarget(queue: DispatchQueue.global()) // Okay
DispatchQueue.global(qos: .utility).setTarget(queue: DispatchQueue.global(qos: .background)) // Okay
let a = DispatchQueue(label: "a", attributes: .concurrent)
a.async {}
let b = DispatchQueue(label: "b", target: a) // Okay
b.async {}
let c = DispatchQueue(label: "c")
c.setTarget(queue: a) // Crashes
// or
c.setTarget(queue: c) // Also crashes (but it worked above with the main queue)
/*
error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
* frame #0: 0x0000000108b72730 libdispatch.dylib`_dispatch_lane_set_target_queue + 404
frame #1: 0x00007f8660304800
frame #2: 0x000000011e731742 $__lldb_expr20`main at Untitled Page 2.xcplaygroundpage:8
frame #3: 0x000000010594f600 Test`linkResources + 304
frame #4: 0x00000001071c5a3c CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
frame #5: 0x00000001071c51f0 CoreFoundation`__CFRunLoopDoBlocks + 336
frame #6: 0x00000001071bfa64 CoreFoundation`__CFRunLoopRun + 1284
frame #7: 0x00000001071bf221 CoreFoundation`CFRunLoopRunSpecific + 625
frame #8: 0x000000010f07f1dd GraphicsServices`GSEventRunModal + 62
frame #9: 0x000000010aeb6115 UIKitCore`UIApplicationMain + 140
frame #10: 0x000000010594f6cd Test`main + 205
frame #11: 0x0000000108bdc551 libdyld.dylib`start + 1
frame #12: 0x0000000108bdc551 libdyld.dylib`start + 1
*/
Is this a bug or intended behavior? Can someone please explain if it should be possible to set the target at runtime and also potentially re-set or remove the target queue entirely?