BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Swift 5.5 Brings Async/Await and Actor Support

Swift 5.5 Brings Async/Await and Actor Support

This item in japanese

At WWDC21, Apple has introduced Swift 5.5, available in beta. Among its new features, one of the most anticipated is better concurrency support using aysnc/await and actors.

Asynchronous functions aim to make concurrent Swift code easier to write and understand, says Apple. Traditionally, Swift used closures and completion handlers to handle asynchronous operations. As it is known, this approach quickly leads to "callback hell" when your code has many asynchronous operations, or control flow gets complicated.

Swift asynchronous functions bring instead coroutines to the language.

Functions can opt into being async, allowing the programmer to compose complex logic involving asynchronous operations using the normal control-flow mechanisms. The compiler is responsible for translating an asynchronous function into an appropriate set of closures and state machines.

The following code snippet shows how you can declare and call async functions as if they were synchronous:

func loadWebResource(_ path: String) async throws -> Resource
func decodeImage(_ r1: Resource, _ r2: Resource) async throws -> Image
func dewarpAndCleanupImage(_ i : Image) async throws -> Image

func processImageData() async throws -> Image {
  let dataResource  = try await loadWebResource("dataprofile.txt")
  let imageResource = try await loadWebResource("imagedata.dat")
  let imageTmp      = try await decodeImage(dataResource, imageResource)
  let imageResult   = try await dewarpAndCleanupImage(imageTmp)
  return imageResult
}

While asynchronous functions appear to greatly simplify concurrency management, they do not rule out the possibility of deadlocks or state corruption. In particular, programmers should be aware of suspension points that async functions introduce. At a suspension point, a function relinquish its thread. This happens, for example, when you call an asynchronous function associated with a different execution context. To avoid the risk of deadlocks or data corruption, async functions should avoid calling functions that may block their thread.

For example, acquiring a mutex can only block until some currently-running thread gives up the mutex; this is sometimes acceptable but must be used carefully to avoid introducing deadlocks or artificial scalability problems. In contrast, waiting on a condition variable can block until some arbitrary other work gets scheduled that signals the variable; this pattern goes strongly against recommendation.

An interesting evolution of this feature enables calling asynchronous Objective-C APIs, which use completion handlers, using an await expression.

Actors, on the other hand, are an abstraction built on top of async and await to safely access mutable state. In short, actors encapsulate some state and provide a set of methods to access it safely.

Unlike classes, actors allow only one task to access their mutable state at a time, which makes it safe for code in multiple tasks to interact with the same instance of an actor.

This is an examples of a Swift actor:

actor TemperatureLogger {
    let label: String
    var measurements: [Int]
    private(set) var max: Int

    init(label: String, measurement: Int) {
        self.label = label
        self.measurements = [measurement]
        self.max = measurement
    }
}

An actor's methods can be used indifferently synchronously or asynchronously from within the actor, but the compiler will force you to use an async operation to read the actor's state from outside the actor.

If you are interested in learning how Swift concurrency works behind the scenes, understanding how Swift tasks differ from Grand Central Dispatch, and how to write concurrent Swift code with performance in mind, do not miss Apple WWDC session Swift concurrency: Behind the scenes.

Swift 5.5 is currently available as part of Xcode 13 beta, which can be downloaded from Apple developer website.

Rate this Article

Adoption
Style

BT