Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ### Language Version
- Swift 6.2 with strict concurrency, `@MainActor` isolation by default, and the following enabled features:
- - **NonisolatedNonsendingByDefault** (SE-0461): Nonisolated async functions execute on the calling actor's executor by default, not the global concurrent pool.
- - **Named tasks** (SE-0469): `Task("Get Users") { ... }` — use descriptive names for debuggability.
- - **Caller isolation inheritance** (SE-0420): `func poll(isolation: isolated (any Actor)? = #isolation) async -> [Item]` — async functions can explicitly inherit the caller's isolation.
- ### Concurrency Patterns
- **Scheduling hierarchy** (cheapest to most expensive, confirmed by reading the Swift runtime source — see `~/Developer/Research/swift-concurrency-scheduling.md`):
- 1. **`MainActor.assumeIsolated { }`** — near-zero cost. Synchronous assertion + direct call. Use for callbacks known to be on main (e.g., NotificationCenter with `queue: .main`, AppKit delegates).
- 2. **`await MainActor.run { }`** — no allocation, reuses existing task. Use when already in async context.
- 3. **`DispatchQueue.main.async { }`** — ~64B block allocation + direct GCD dispatch. Use for fire-and-forget from background or `@Sendable` contexts (e.g., `onTermination` handlers).
- 4. **`Task.immediate { @MainActor in }`** (SE-0472) — full Task allocation (~300-500B) but **no dispatch hop** if already on the right executor. Falls back to normal enqueue otherwise. Use when Task semantics are needed (cancellation, task-locals, priority) with predictable execution ordering.
- 5. **`Task { @MainActor in }`** — full Task allocation + always enqueues via dispatch_async. Only use when you specifically need deferred execution with Task semantics.
- **Rules:**
- - **Never use `Task { @MainActor in }` for synchronous code** — anti-pattern that introduces unnecessary thread hops and ~5x more overhead than `DispatchQueue.main.async` for the same fundamental `dispatch_async_f` call.
- - **Use `.detached` to actually run off MainActor** — given implicit MainActor isolation, a plain `Task { }` inherits the actor context.
- - **Task.immediate preserves execution order** — unlike regular Task which always enqueues, `Task.immediate` runs synchronously when isolation is compatible, guaranteeing that mutations are visible immediately after the call returns.
- **Isolated deinit** (SE-0471): Actor-isolated types can declare `isolated deinit` to safely access isolated state during deinitialization without resorting to unstructured concurrency.
- ```swift
- @MainActor
- final class ResourceOwner {
- let connection: NonSendableConnection
- isolated deinit {
- connection.close() // safe — runs on MainActor
- }
- }
- ```
Advertisement