Chapter 8 - Why doesn't Download task run twice?

Thank you for making a very practical book.

I have a questions about the image cache mechanism introduced in Chapter 8.
The following is it.

[Question] Why doesn’t Download task run twice?
When the image cache does not exist, you are storing the Task in the cache as inProgress state. At the same time, you are copying the Task to download the image to the cache as an associated Value

let download: Task<UIImage, Error> = Task.detached {
      guard let url = URL(string: "http://localhost:8080".appending(serverPath)) else {
        throw "Could not create the download URL"
      print("Download: \(url.absoluteString)")
      let data = try await url).0
      return try resize(data, to: CGSize(width: 200, height: 200))

cache[serverPath] = .inProgress(download)

And after that you await that Task.

do {
      let result = try await download.value
      add(result, forKey: serverPath)
      return result
} catch {

When someone calls A at the same time, the following process will be executed because the cache exists.

if let cached = cache[serverPath] {
      switch cached {
      case .inProgress(let task):
        return try await task.value

Since Task is a value type, I assumed that each await would request an image.
Why doesn’t Download task run twice?

Hi and thank you - that is a very interesting question!

Task is a struct, but none of the code above mutates it which grants creating a new copy of the task. I.e. once the task is created initially, the rest of the code only accesses it which keeps a single copy of the task in memory.

If for example, you assign the task as an associated value, it will still be the same copy as long as you don’t mutate the struct.

Ultimately, you can argue that, value 's value changes and so the struct should be mutated. However, if you look at the source code you’ll see the task properties are dynamic ones, for example:

I hope that answers your question