参照
提案概要
- GlobalActorに隔離されたクラスのdeinitに対して isolated を付与することで、deinit内部の処理をActor隔離する
なぜ必要か
- deinitをActor隔離できないことから、不要なワークアラウンドが必要な場合があり、利便性を損ねているため
どのように使うか
- 以下例のように、明示的に isolatedを付与する
class NonSendableAhmed {
var state: Int = 0
}
@MainActor
class Maria {
let friend: NonSendableAhmed
init() {
self.friend = NonSendableAhmed()
}
init(sharingFriendOf otherMaria: Maria) {
// While the friend is non-Sendable, this initializer and
// and the otherMaria are isolated to the MainActor. That is,
// they share the same executor. So, it's OK for the non-Sendable value
// to cross between otherMaria and self.
self.friend = otherMaria.friend
}
isolated deinit {
// Used to be a potential data race. Now, deinit is also
// isolated on the MainActor, so this code is perfectly
// correct.
friend.state += 1
}
}
func example() async {
let m1 = await Maria()
let m2 = await Maria(sharingFriendOf: m1)
doSomething(m1, m2)
} いつ使うか
- deinit内部で、外部にNon-Sendableな値をスレッドセーフな状態を保って操作したい場合
技術メモ