try await withThrowingTaskGroup(of: QuakeLocation.self) { group in
let count = Counter() // Create a counter object.
var locations: [QuakeLocation] = []
for quake in quakes {
group.addTask {
let location = try await provider.location(for: quake.url)
// Increment the counter after fetch completes.
count.increment()
}
}
while let location = try await group.next() {
locations.append(location)
}
// This will sometimes fail.
assert(counter.count == locations.count)
}
class Counter {
var count: Int = 0
func increment() {
count = count + 1
}
}
This example calls increment()
from multiple tasks. If the tasks are timed just so, two tasks might both read the same value, add 1
to that value, and then write the same updated value to the count
property. In effect, one of the requests wouldn’t be counted. This is a data race.