“Thread” vs. “Queue” vs. “Actor’s executor”

I had this conversation with ChatGPT and I don't trust the bot as a source of truth on this.

My question: ...the word 'queue' in swift-concurrency ... is not the same as the word 'queue' used in the context of GCD ?

ChatGPT's Answer
When discussing actor isolation, three concepts come into play:

  1. Thread —An operating system thread is a low-level thing that can run code.The Swift concurrency runtime can hop between threads freely.
  2. Actor’s queue/executor —Every actor has its own serial executor, which is basically a queue of tasks waiting to run in that actor’s isolation.
  • The actor’s executor serialises all the tasks that touch the actor’s state.
  • This is sometimes informally called the actor’s “queue” or “mailbox.”
  1. Scheduler —The scheduler is the thing that maps pending tasks (actor-isolated or not) onto available threads.It doesn’t care what actor a task belongs to — it just looks for work to do and finds a thread to run it.

:counterclockwise_arrows_button: How they fit together:

  • When you call an actor method, the call is posted onto that actor’s executor queue.
  • The scheduler later picks up that actor’s executor work and assigns it to an available OS thread.
  • On that thread, the actor’s executor processes one task at a time.

My question: So the word 'queue' in this context is just an informal way of saying 'executor' ? And is not the same as the word 'queue' used in the context of GCD ?

ChatGPT's Answer
Exactly — you’ve got it. :white_check_mark: Let me make this crystal clear.


:bullseye:

queue

in actor context

When we say the actor has a “queue”, we mean its executor:

  • A logical serial list of tasks that need to run one-by-one to maintain actor isolation.
  • This is not necessarily a DispatchQueue or a GCD queue — it’s an implementation detail of the actor’s executor.
  • Apple’s concurrency runtime decides how to implement this under the hood.

:bullseye:

queue

in GCD context

When we talk about a GCD queue (DispatchQueue.main, DispatchQueue.global, etc.), we mean:

  • A real Dispatch Queue provided by Grand Central Dispatch .
  • You can submit blocks to these queues with DispatchQueue.async { ... }.
  • They manage their own pools of threads.

It wasn't all that nice to have to try to parse what was what (your input / your qwuestion / the ai response)...

But yeah: "queue" just means queue. Actors have a list of jobs basically.

A dispatch queue can be a swift concurrency SerialExecutor.

An actor has an executor; the executor may be a dispatch queue or not. Logically, executors have "a queue" of the pending jobs.

Watch this talk for details Swift concurrency: Behind the scenes - WWDC21 - Videos - Apple Developer

2 Likes

From SE-0306:

So, it is conceptually a “queue” but not always a strict FIFO one. The default serial executor considers not only order, but priorities, too.

1 Like

I don't think I've ever seen anyone use the word queue to refer to a Swift Concurrency specific thing. Are you sure your premise here isn't just either a) someone getting confused, or b) someone referring to libdispatch and you mistakenly thinking they're referring to SC?

1 Like

Actually, SE-0306 uses the term:

But later it clarifies:

So, you’re right that we wouldn’t tend to use the term “queue” in the context of Swift concurrency, explicitly to avoid this sort of confusion. (I confess that I don’t see many people adopting this “mailbox” terminology, either.) In this case, I suspect that ChatGPT went down the “queue” road as the OP included this term in the prompt.

1 Like

Evolution proposals use the term "enqueue" a lot. That implies use of queue.

 $ grep  -r -i enqueue * | cut -d: -f1 | sort | uniq
0304-structured-concurrency.md
0314-async-stream.md
0323-async-main-semantics.md
0329-clock-instant-duration.md
0371-isolated-synchronous-deinit.md
0392-custom-actor-executors.md
0406-async-stream-backpressure.md
0417-task-executor-preference.md
0420-inheritance-of-actor-isolation.md
0424-custom-isolation-checking-for-serialexecutor.md
0431-isolated-any-functions.md
0449-nonisolated-for-global-actor-cutoff.md
0469-task-names.md
0472-task-start-synchronously-on-caller-context.md
0475-observed.md

While I searched for this, I find the following text in SE-0306, which almost answers OP's question.

Implementation note: At an implementation level, the messages are partial tasks (described by the [Structured Concurrency][sc] proposal) for the asynchronous call, and each actor instance contains its own serial executor (also in the [Structured Concurrency][sc] proposal). The default serial executor is responsible for running the partial tasks one-at-a-time. This is conceptually similar to a serial DispatchQueue, but with an important difference: tasks awaiting an actor are not guaranteed to be run in the same order they originally awaited that actor. Swift's runtime system aims to avoid priority inversions whenever possible, using techniques like priority escalation. Thus, the runtime system considers a task's priority when selecting the next task to run on the actor from its queue. This is in contrast with a serial DispatchQueue, which are strictly first-in-first-out. In addition, Swift's actor runtime uses a lighter-weight queue implementation than Dispatch to take full advantage of Swift's async functions.

1 Like

The "enqueue" means specifically: Executor/enqueue(_:) | Apple Developer Documentation and the fact of enqueueing a job to an executor.

3 Likes

Think queue is a common term overall, not necessarily related to computer science, so it's natural to see it from time to time, e.g. message queue seen quite often in different actor docs.

2 Likes