How do the run loop of the main thread and the main queue are related?

Do run loops use an operation queue under the hood?

When I dispatch to the mian queue, I know it will run on the mian thread, which means it will be handled b the main thread's run loop. But is the other way around correct?

More specific question, is it possible somehow that the following code will return true?

OperationQueue.current != OperationQueue.main && Thread.isMainThread

I tried to do for example to dispatch to the main thread using a timer.

myQueue.sync {
  let timer = Timer(timeInterval: 1, repeats: false) { _ in
    let curr = OperationQueue.current
    let main = OperationQueue.main
    print("\(String(describing: curr)) \(main)")
  }
  RunLoop.main.add(timer, forMode: .common)
}

And got the same pointer. But maybe some other way of dispatching to the main run loop will give different results, possibly that is why OperationQueue.current can return nil.

Accepted Reply

Do run loops use an operation queue under the hood?

No.

How do the run loop of the main thread and the main queue are related?

Foundation’s run loop code has special logic so that the main thread’s run loop drains any blocks that were dispatched to the main queue.

As to your other questions, it’s hard to answer because you haven’t explained the motivation for what you’re doing. There are some serious traps here. Consider this one:

import Foundation

let queue = DispatchQueue(label: "not-main")

func main() {
    queue.async {
        DispatchQueue.main.sync {
            // This doesn’t trap:
            dispatchPrecondition(condition: .onQueue(.main))
            // But this prints false:
            print(Thread.isMainThread)
        }
    }
    dispatchMain()
}

main()

That’s because, when you dispatch sync to a queue, Dispatch avoids the thread switch by having your current thread actually do the work.

The whole concept of current queue is not well formed when it comes to Dispatch. That’s why dispatch_get_current_queue is deprecated and not available in Swift. You run into similar problems with OperationQueue but it predates Dispatch and thus OperationQueue.current is still a thing.

If you can explain more about your high-level goal, I’ll see if I can suggest something that works for that.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • Thanks! It's more of a questing for understanding how it works rather than solving a specific problem. "Foundation’s run loop code has special logic so that the main thread’s run loop drains any blocks that were dispatched to the main queue." Do you know where I can read more about this?

Add a Comment

Replies

Do run loops use an operation queue under the hood?

No.

How do the run loop of the main thread and the main queue are related?

Foundation’s run loop code has special logic so that the main thread’s run loop drains any blocks that were dispatched to the main queue.

As to your other questions, it’s hard to answer because you haven’t explained the motivation for what you’re doing. There are some serious traps here. Consider this one:

import Foundation

let queue = DispatchQueue(label: "not-main")

func main() {
    queue.async {
        DispatchQueue.main.sync {
            // This doesn’t trap:
            dispatchPrecondition(condition: .onQueue(.main))
            // But this prints false:
            print(Thread.isMainThread)
        }
    }
    dispatchMain()
}

main()

That’s because, when you dispatch sync to a queue, Dispatch avoids the thread switch by having your current thread actually do the work.

The whole concept of current queue is not well formed when it comes to Dispatch. That’s why dispatch_get_current_queue is deprecated and not available in Swift. You run into similar problems with OperationQueue but it predates Dispatch and thus OperationQueue.current is still a thing.

If you can explain more about your high-level goal, I’ll see if I can suggest something that works for that.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • Thanks! It's more of a questing for understanding how it works rather than solving a specific problem. "Foundation’s run loop code has special logic so that the main thread’s run loop drains any blocks that were dispatched to the main queue." Do you know where I can read more about this?

Add a Comment