I'm watching this WWDC video about Protect mutable state with Swift actors
and in one example they show how an actor method can be called concurrently
Imagine we have two different concurrent tasks trying to fetch the same image at the same time. The first sees that there is no cache entry, proceeds to start downloading the image from the server, and then gets suspended because the download will take a while. While the first task is downloading the image, a new image might be deployed to the server under the same URL. Now, a second concurrent task tries to fetch the image under that URL. It also sees no cache entry because the first download has not finished yet, then starts a second d ownload of the image. It also gets suspended while its download completes. After a while, one of the downloads -- let's assume it's the first -- will complete and its task will resume execution on the actor. It populates the cache and returns the resulting image of a cat. Now the second task has its download complete, so it wakes up. It overwrites the same entry in the cache with the image of the sad cat that it got. So even though the cache was already populated with an image, we now get a different image for the same URL.
Isn't the whole idea of actor is that it ensures that only one caller can directly interact with the actor at any given time?
Here is my example. Here you can see that "BEGIN increment" is always followed by "END increment" and that subsequent call to increment
must await
actor Counter {
var count = 1
func increment() {
print("BEGIN increment")
let url = URL(string: "https://google.com")!
let data = try! Data(contentsOf: url)
let string = String(data: data, encoding: .utf8) ?? ""
print("END increment")
count += 1
}
}
struct ContentView: View {
@State var counter = Counter()
var body: some View {
Button {
Task.detached {
await counter.increment()
}
} label: {
Text("Click")
}
}
}