loading . . . A Swift Concurrency Glossary It would be nice if there was a single place to go to look up all the terms, keywords, and annotations related to Swift concurrency. So here it is. If you notice something I’ve missed, pleased o let me know. Oh and of course, I included some commentary.
Also, by **no means** do you need to understand everything here to use Swift Concurrency successfully.
## `actor`
* Type: Keyword
* Usage: Defines a new reference type that protects mutable state
* Introduced: SE-0306 Actors
Actors are the thing that define a unit of isolation. They are easy to **make** , but require a fair bit of understanding and practice to use successfully.
(I have now written a whole post about how and when to use an actor.)
## `Actor`
* Type: Protocol
* Usage: A protocol which all actor types conform to
* Introduced: SE-0306 Actors
This is kinda like `AnyObject`, but only for actor types. You’ll rarely need this, aside from making isolated parameters.
## `async`
* Type: keyword
* Usage: Applied to a function signature so it can be used with `await`
* Introduced: SE-0296 Async/await
This keyword marks an “effect” on a function, allowing it to use `await` internally and also be itself awaited.
## `AsyncSequence`
* Type: Protocol
* Usage: A series of value that are produced over time
* Introduced: SE-0298 Async/Await: Sequences
This is a protocol that describes a sequence who’s values may only be available at some point in the future.
## `async let`
* Type: Flow Control
* Usage: Convenient shortcut to wrap work in a new Task
* Introduced: SE-03017 `async let` bindings
This one gives you a way to begin some work asynchronously without needing to await immediately. Does come with some subtly, but is particularly useful for managing slow, syncrhonous work.
## `await`
* Type: keyword
* Usage: Marks a suspension point that allows an async function to execute
* Introduced: SE-0296 Async/await
The other half of `async`. You use this to introduce a potential suspension point in the currently executing task. At these points, the actor executing code can change.
## `@concurrent`
* Type: annotation
* Usage: Causes an async function to run on the global executor
* Introduced: SE-0461 Run nonisolated async functions on the caller’s actor by default
As of Swift 6.2, you can opt into nonisolated async functions inheriting the calling isolation. This is incredibly useful, but you now cannot use that to run functions in the background. This attribute gives you a settings-independent way to ensure a function never runs on an actor.
## Continuations
* Type: Type
* Usage: Makes it possible to wrap up callback-based code so it can be used with `await`
* Introduced: SE-0300 Continuations for interfacing async tasks with synchronous code
Asynchronous execution is not new. But, it was very commonly done using callbacks and closures. This is a whole suite of APIs that allows you to express these concepts in terms of async functions.
## Default Isolation
* Type: Concept
* Usage: Control the implicit default isolation
* Introduced: SE-0466 Control default actor isolation inference
All declarations have a well-defined static isolation, which means a default is required. This was always `nonisolated`, up to Swift 6.2, where we gained the ability to change this to `MainActor`. This capability has introduced a formal language dialect: you cannot understand the semantics of Swift code without knowing the value of this setting.
## `Executor`
* Type: Protocol
* Usage: An API for expressing how actors execute code
* Introduced: SE-0304 Structured concurrency
There is a pretty large set of APIs for controlling and interacting with the underlying mechanisms an actor uses to run code. This is rarely required for day-to-day Swift development, but is there for advanced uses and performance considerations.
## `for-await`
* Type: Flow Control
* Usage: Get the values from an `AsyncSequence`
* Introduced: SE-0298 Async/Await: Sequences
This gives you a way to retrieve the values in an `AsyncSequence` via a control structure that very closely resembles a traditional for loop.
## `@globalActor`
* Type: annotation
* Usage: Marks an actor type as global, allowing it to be used as a global actor annotation
* Introduced: SE-0316 Global actors
This is how you make an actor type “global”. A global actor’s type name can be referenced in annotation form, and can be used to apply static isolation.
## Global Executor
* Type: concept
* Usage: The executor that runs concurrent code
* Introduced: SE-0338 Clarify the Execution of Non-Actor-Isolated Async Functions
Actors run code they isolate on their executor. But, there’s also an executor available that can run code not isolated to any actor. Unlike actor executors, this one is **not** serial and can run more than one thing simultaneously. You get code on this with `async let`, `TaskGroup`, and `@concurrent`.
## `isolated`
* Type: keyword
* Usage: Defines static isolation via a parameter of a function
* Introduced: SE-0313 Improved control over actor isolation
There are four ways to define isolation statically, with this being the most powerful and complex. This is an essential tool **if** you need to integrate concurrency into non-`Sendable` types.
(There’s work going on to simplify this area! I’ve also written something about how to use it with non-Sendable types.)
## `@isolated(any)`
* Type: annotation
* Usage: Makes it possible to inspect a function’s static isolation at runtime
* Introduced: SE-0431 `@isolated(any)` Function Types
There are rare cases where you may want to inspect the static isolation was of a function that has been passed around as a variable. This annotations makes that possible. If you are thinking about this, you probably want to combine it with `@_inheritActorContext`.
(I’ve written the introducion of this attribute specifically, along with a biggest post that looks at it more closely.)
## isolation
* Type: concept
* Usage: The form of thread-safety that an actor type provides
* Introduced: SE-0306 Actors
Isolation is this abstraction over ways to make things thread-safe. Actors are the things that implement that safety, perhaps via a serial queue.
(I’ve got two things on this. One about how you use isolation and another to help think about it.)
## `#isolation`
* Type: expression macro
* Usage: Returns the static isolation as `(any Actor)?`
* Introduced: SE-0420 Inheritance of actor isolation
If you are using an isolated parameter, you **may** want to use this as well. I also have found it handy for printing out what the compiler thinks the isolation is at a specific point.
(I’ve written about this one as well.)
## `@_inheritActorContext`
* Type: parameter annotation
* Usage: Applies isolation inheritance to a closure parameter
* Introduced: ?
You can use this one to match the sematics of `Task`, so a closure can maintain the same isolation as where it was formed. Usually goes together with `@isolated(any)`.
(There is a proposal floating around that will formalize this one, though I do have complex feelings about it.)
## `@MainActor`
* Type: annotation
* Usage: The global actor annotation for the `MainActor` type
* Introduced: SE-0316 Global actors
I bet you’ve come across this one before. It is just how you reference the shared `MainActor` instance.
## `nonisolated`
* Type: keyword
* Usage: Explicitly turn off actor isolation for a declaration
* Introduced: SE-0313 Improved control over actor isolation
Actors provide isolation, but sometimes you want to disable that. This is a handy way to hop off an actor to run some code in the background.
## `nonisolated(nonsending)`
* Type: annotation
* Usage: Causes an async function to inherit the caller’s isolation
* Introduced: SE-0461 Run nonisolated async functions on the caller’s actor by default
This is a very powerful technique for avoiding the need for Sendable types. The attribute gives you a settings-independent to make a function that inherits the caller’s isolation. Similar to the problem addressed with `@concurrent`, but from the other direction.
## `nonisolated(unsafe)`
* Type: annotation
* Usage: Opts a declaration out of Sendable checking
* Introduced: SE-0306 Actors
This gives you a very targetted way to opt a declaration out of the compiler’s isolation checks. It is a much less-error-prone tool than `@unchecked Sendable` or a preconcurrency import.
## `@preconcurrency`
* Type: attribute
* Usage: Multiple, all around how code built for Swift 6 interacts with code that has not
* Introduced: SE-0337 Incremental migration to concurrency checking, SE-0423: Dynamic actor isolation enforcement from non-strict-concurrency contexts
If you are consuming APIs written before Swift 6, or making APIs that need to remain compatible with Swift 5 mode, you pretty much need this one.
(I’ve gone into some depth about how this works.)
## Region-Based Isolation
* Type: concept
* Usage: Allows the compiler to relax `Sendable` checking in specific circumstances
* Introduced: SE-0414 Region-based Isolation
This is a code-flow analysis system that allows the compiler to prove that even if a type is not `Sendable`, a specific usage pattern may still always be safe. It can really only work within the scope of a single function body, but the `sending` keyword does allow it to be even more powerful.
(My summary of this is here.)
## `Sendable`
* Type: Protocol
* Usage: A marker protocol that indicates a type can be safely used from any isolation, including none at all
* Introduced: SE-0302 Sendable and `@Sendable` closures
This provides a way to encode the thread-safety of a type into the type system. And it has no members so how complex could it possibly be?
(I haven’t even written about this directly, but I did cover the general idea here.)
## `SendableMetatype`
* Type: Protocol
* Usage: A marker protocol that indicates a metatype can be safely used from any isolation
* Introduced: SE-0470 Global-actor isolated conformances
Prior to Swift 6.2, all types were `Sendable` and this concept wasn’t required. But, isolated conformances brought with it some extra complexity here that required the new protocol.
## `@Sendable`
* Type: Attribute
* Usage: Functions cannot conform to protocols, so an attribute is required to express the same concept
* Introduced: SE-0302 Sendable and `@Sendable` closures
This is exactly the same thing as `Sendable`, but for function types.
## `sending`
* Type: Keyword
* Usage: Express the concurrent usage of parameters and return values into the type system
* Introduced: SE-0430 `sending` parameter and result values
Sometimes `Sendable`/`@Sendable` is too difficult or just unnecessarily restrictive. The `sending` keyword is a way relax some constraints by encoding a strict promise about the behavior of values into your function signatures.
(And, yes, I did in fact write about it!)
## `Task`
* Type: Type
* Usage: Creates a new top-level context to run async code
* Introduced: SE-0304 Structured concurrency
You gotta start somewhere, and for async functions it’s usually via a `Task`. But this type somes with a lot of features, to support things like cancellation and accessing results.
## `TaskGroup`
* Type: Type
* Usage: An API to work with an arbitrary number of child tasks
* Introduced: SE-0304 Structured concurrency
A `TaskGroup` gives you a way to manage and control multiple child `Task` instances. Useful for tackling a variety of problems, including just doing a bunch of stuff simultaneously.
## `TaskLocal`
* Type: Type
* Usage: A mechanism for making values available across the current task
* Introduced: SE-0311 Task Local Values
This is kind of like the analog of thread-local values, but for tasks. They are quite an advanced tool, but there are lots of clever/tricky things you can pull off with them.
## `@unchecked`
* Type: Annotation
* Usage: Disables compiler checks for a `Sendable` conformance
* Introduced: SE-0302 Sendable and `@Sendable` closures
Sometimes, you’ve already got thread-safety implemented, but it is done via a mechanism don’t support Swift’s compiler-based checking. Declaring a type `@unchecked Sendable` let’s you express that situation.
* * *
Did you know that I do consulting for concurrency and Swift 6 migrations? If you think I could help, get in touch. https://www.massicotte.org/concurrency-glossary