Do escaping closure that are passed to actor method inherit actor isolation? Or they are non isolated?
For instance:
actor MyActor {
func method(_ closure: @escaping () async -> Void) {
await closure()
}
}
With what isolation will closure be created? In my simple test, seems that closure inherit it's context isolation on allocation
actor MyActor {
func method(_ closure: @escaping () async -> Void) async {
print("in actor method: ", Thread.current)
await closure()
print("in actor method: ", Thread.current)
}
}
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let actor = MyActor()
Task {
print("in task closure: ", Thread.current)
await actor.method {
print("in actor closure: ", Thread.current)
try? await Task.sleep(nanoseconds: 1_000_000_000)
print("in actor closure: ", Thread.current)
}
print("in task closure: ", Thread.current)
}
return true
}
Outputs:
in task closure: <_NSMainThread: 0x283604380>{number = 1, name = main}
in actor method: <NSThread: 0x283654400>{number = 5, name = (null)}
in actor closure: <_NSMainThread: 0x283604380>{number = 1, name = main}
in actor closure: <_NSMainThread: 0x283604380>{number = 1, name = main}
in actor method: <NSThread: 0x283654400>{number = 5, name = (null)}
in task closure: <_NSMainThread: 0x283604380>{number = 1, name = main}
I know that it's it proper proof of hypothesis, therefore I'm asking: Is there are any proposals or statements, which describe what isolation async closure do get?
CodePudding user response:
Yes, the closure will use the same actor context from which it was formed (the main actor in this example):
As SE-0306 says
A closure that is not
@Sendable
cannot escape the concurrency domain in which it was formed. Therefore, such a closure will be actor-isolated if it is formed within an actor-isolated context.