apple/swift
Concurrency
Active contributors: ktoso, kavon, FranzBusch, rauhul
Purpose
stdlib/public/Concurrency/ implements the Swift Concurrency model: structured concurrency (async/await, async let, TaskGroup), unstructured concurrency (Task { ... }, detached tasks), actors (reference types with isolated mutable state), executors (the schedulers that run tasks), and Sendable (the protocol marking values safe to share across concurrency domains).
The module is the largest single feature added to the language since open-sourcing.
Directory layout
stdlib/public/Concurrency/ (mixed C++ and Swift)
├── Actor.swift / Actor.cpp # actor runtime
├── Task.swift / TaskGroup.swift / Task+TaskGroup.cpp
├── AsyncLet.swift / AsyncLet.cpp
├── AsyncSequence.swift, AsyncIteratorProtocol.swift
├── AsyncStream.swift / AsyncThrowingStream.swift
├── AsyncFlatMapSequence.swift, AsyncMapSequence.swift, ... (combinators)
├── CheckedContinuation.swift
├── Clock.swift, ContinuousClock.swift, SuspendingClock.swift
├── DispatchExecutor.swift / DispatchGlobalExecutor.cpp # libdispatch backed
├── CooperativeExecutor.swift / CooperativeGlobalExecutor.cpp # Linux cooperative
├── CFExecutor.swift / CFExecutor.cpp # Darwin CF backing
├── Executor.swift, ExecutorAssertions.swift
├── ExecutorBridge.{cpp,h,swift}
├── ExecutorImpl.cpp, ExecutorChecks.cpp
├── Errors.swift / Error.cpp / Error.h
├── Mutex.swift # actor support
├── PartialAsyncTask.swift
├── PriorityQueue.swift, PriorityQueue.cpp
├── TaskAlloc.cpp, TaskCancellation.swift, TaskLocal.swift, TaskSleep.swift
├── ThreadingError.cpp, ThreadSanitizer.cpp
└── ... many moreThere are roughly 70 source files split between Swift (the user-visible API and overlay glue) and C++ (the runtime and FFI bottom).
Key abstractions
| Type | File | Description |
|---|---|---|
Task<Success, Failure> |
stdlib/public/Concurrency/Task.swift |
A unit of asynchronous work. |
actor (language keyword) |
stdlib/public/Concurrency/Actor.swift + Actor.cpp |
Reference type with mailbox-style isolation. |
Executor |
stdlib/public/Concurrency/Executor.swift |
Protocol; runs a job. Subprotocols: SerialExecutor, TaskExecutor. |
DefaultActor |
stdlib/public/Concurrency/Actor.cpp |
C++ helper that lays out actor mailbox state in the heap. |
AsyncSequence |
stdlib/public/Concurrency/AsyncSequence.swift |
Async equivalent of Sequence. |
CheckedContinuation |
stdlib/public/Concurrency/CheckedContinuation.swift |
Bridge from callback APIs. |
Clock |
stdlib/public/Concurrency/Clock.swift |
Abstraction over ContinuousClock / SuspendingClock. |
TaskGroup<ChildTaskResult> |
stdlib/public/Concurrency/TaskGroup.swift |
Structured group of child tasks. |
How it works
Tasks and continuations
A Task is a heap-allocated record with a state machine. Each suspension point (an await) is compiled into an LLVM coroutine continuation -- the function suspends, the runtime captures its state, and a later wake-up resumes from the saved continuation. The runtime helpers swift_task_create, swift_task_switch, swift_continuation_resume are in Task+TaskGroup.cpp, TaskGroup.cpp, Continuation.cpp. IRGen lowers await to these calls; see IRGen.
Executors
graph TD
Task -->|"runs on"| Executor
Executor --> Serial[SerialExecutor]
Executor --> Global[GlobalExecutor]
Serial --> ActorExec["actor's executor (built-in)"]
Serial --> CustomExec[Custom serial executor]
Global --> Cooperative[CooperativeGlobalExecutor]
Global --> Dispatch[DispatchGlobalExecutor]- Cooperative global executor (
CooperativeGlobalExecutor.cpp) is the default on platforms without libdispatch. It is a small fixed-size thread pool with a work-stealing deque per thread. - Dispatch global executor (
DispatchGlobalExecutor.cpp) bridges to libdispatch on Apple platforms. - Per-actor executor -- by default, an actor uses the global concurrent executor; declaring a custom
unownedExecutorproperty makes the actor use a user-providedSerialExecutor.
Actors
An actor is a class whose mailbox is enforced. Calls from outside the actor are scheduled (a hop) onto its executor. The runtime adds an ActiveExecutor-tracking field and a lock-free mailbox in the class header (DefaultActor in Actor.cpp). Sema enforces the language rules (you cannot synchronously read an actor's state from outside it; mutating an actor inside an inout parameter is illegal; etc.).
Sendable
Sendable is a marker protocol that is checked statically (lib/Sema/TypeCheckConcurrency.cpp) but has no runtime witness. Conforming a type means promising it can be passed across actors. Many stdlib value types conform conditionally (Array<Sendable> is Sendable).
Distributed actors
Distributed actors (stdlib/public/Distributed/) build on top of regular actors. A distributed actor is associated with an ActorSystem; calls to a remote actor are encoded by the system and shipped over the wire. See Distributed actors.
Task locals
@TaskLocal gives you scoped, dynamically-bound values (analogous to ThreadLocal but per-task and inherited by child tasks). Implementation in TaskLocal.swift plus runtime support in Task+TaskGroup.cpp.
Integration points
- The compiler -- Sema enforces actor isolation rules. SILGen lowers
awaitand actor hops. IRGen emits coroutine intrinsics and runtime calls. - The runtime -- the C++ side (
stdlib/public/runtime/plusstdlib/public/Concurrency/*.cpp) provides task allocation, executor management, and continuation resumption. - Threading layer --
stdlib/public/Threading/provides cross-platform thread / mutex / once primitives. - Distributed actors depend on the regular actor mechanism plus a user-defined
DistributedActorSystem.
Entry points for modification
- Adding an executor: implement
SerialExecutor(orTaskExecutor) in user code. For the runtime side, seeExecutor.swiftand the existingCooperative*andDispatch*examples. - Tuning task scheduling:
CooperativeGlobalExecutor.cppandTask+TaskGroup.cpp. - Adding a concurrency diagnostic:
lib/Sema/TypeCheckConcurrency.cpp. Tests undertest/Concurrency/. - Reproducing data-race issues:
SWIFT_DEBUG_RUNTIME_TRACK_ACTORS=1and ThreadSanitizer.
Related pages
- Standard library -- the surrounding library context.
- Distributed actors -- the layer above.
- Sema -- where isolation rules are enforced.
- Runtime -- the underlying allocation and metadata machinery.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.