I like this @epam-gor-gyolchanyan's idea, and having actor-isolated deinit async
is probably a better solution than trying to capture all actor properties into a new task manually for clean up as @Douglas_Gregor mentioned, which is obviously getting difficult when actor has tons of internal properties:
I also think deinit async
is slightly better than having synchronous actor-isolated deinit
(without async) since non-isolated deinit
is preferred whenever possible, and it looks symmetric to how actor-initializer works (synchronous non-isolated init
and isolated init async
).
cf.
I don't know much about compiler-internal whether deinit async
(or synchronous actor-isolated deinit
for my 2nd favor) can be technically possible, but since accessing actor-isolated methods is difficult inside deinit
, if Swift keeps providing non-isolated synchronous deinit
only, I really wish there is at least some magicalSelf
keyword to help Swift developers not do heavy lifting.
actor Foo {
// Endless actor-isolated internal properties that can each call `cleanUp()`.
var state1, state2, state3, ...
// Clean up code used in many places, including `deinit`.
func cleanUpAll() {
state1.cleanUp()
state2.cleanUp()
...
}
// Assume `deinit` is still non-isolated as is:
deinit {
// self.cleanUpAll() // ERROR: can't use actor-isolated method
// BAD: Copy-pasting same code here is cumbersome.
Task.detached { [state1, state2, ...] in
state1.cleanUp()
state2.cleanUp()
...
}
// GOOD: Single line of code, and works like magic!
magicalSelf.cleanUpAll()
}
}