Actors in Swift Concurrency

Hey all,

New to learning swift concurrency here. Watching the WWDC video (Protect mutable state with Swift actors - WWDC21 - Videos - Apple Developer) on actors and the presenter discusses the code below:

actor ImageDownloader { private var cache: [URL: Image] = [:]

func image(from url: URL) async throws -> Image? {
    if let cached = cache[url] {
        return cached

    let image = try await downloadImage(from: url)

    // Potential bug: `cache` may have changed.
    cache[url] = image
    return image

I thought actors isolate the content and now allow other tasks to access it until it is done, but the presenter is saying since this is not the case here ?

Is it because there is an await keyword, which serves as a point of possible suspension and during a suspension, other tasks can access it even though it is inside an actor .. ?

Yes, a suspension point divides the calling function into "before" and "after" halves. If the actor was "locked" in between the two halves, then if the awaited function called back into the actor, it would hang forever (a deadlock).

1 Like

I see. So that is why we can still access the actors function with two or more tasks if we await one of them

To put it in other words, actors isolate the state so that it is safe to access it from multiple threads. Yet they won’t prevent introducing race conditions, it has nice explanation in Actor proposal — swift-evolution/proposals/ at main · apple/swift-evolution · GitHub

The options are either to (1) avoid suspension points in the actor code, or (2) avoid relying on state around them, or (3) introduce your own mechanisms to control execution of the critical parts, e.g. using continuations.

Avoiding suspension points seems to be the best way at first, but it eliminates benefits of concurrency, which in many cases, including this example from WWDC, makes implementation slow — instead of fetching 10 images at the same time, they will be now fetched one by one. There were a lot of discussions on the forum on this topic with examples of implementations, and many other details — you can look for them searching for "actor" and "reentrancy" keywords.