I found a data race in my Swift app by using the Thread Sanitizer, and so I made my first attempt to fix race conditions by converting the offending class
to an actor
. The crash that the race was causing seems to have gone away, but Thread Sanitizer is still saying there's a data race in the code, which I thought should be impossible in the actor
.
I can't post the entire actor
here, but here is the code where the race is occurring:
actor SampleActor {
private var things = Set<Int>()
func addThing(_ newThing: Int, seconds: Double) {
things.insert(newThing)
Task {
try await Task.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
self.things.remove(newThing)
}
}
}
// Code to cause the race
let sample = SampleActor()
for n in 0 ..< 1000 {
Task {
await sample.addThing(n, seconds: Double.random(in: 0...1.0))
}
}
I'm probably going about this the wrong way, but I need to add an object to the SampleActor
's set of objects, and have it be automatically removed after some amount of time.
Is there a better way to do this? And what am I missing about the use of actor
to avoid the data race in this case? Shouldn't SampleActor.things
be immune to races here because it's a property of an actor
?
CodePudding user response:
Remove the Task {
part in the actor
Add async
to the function
func addThing(_ newThing: Int, seconds: Double) async {