Skip to content

Commit b4a1aab

Browse files
Updated Distributed/Runtime/distributed_actor_deinit.swift to check for isolation
1 parent 9005e9b commit b4a1aab

File tree

1 file changed

+136
-27
lines changed

1 file changed

+136
-27
lines changed

test/Distributed/Runtime/distributed_actor_deinit.swift

Lines changed: 136 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking -parse-as-library) | %FileCheck %s
1+
// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking -parse-stdlib -parse-as-library) | %FileCheck %s
22

33
// REQUIRES: executable_test
44
// REQUIRES: concurrency
@@ -10,7 +10,26 @@
1010
// FIXME(distributed): Distributed actors currently have some issues on windows, isRemote always returns false. rdar://82593574
1111
// UNSUPPORTED: OS=windows-msvc
1212

13+
import Swift
14+
import _Concurrency
1315
import Distributed
16+
import Dispatch
17+
18+
@_silgen_name("swift_task_isCurrentExecutor")
19+
private func isCurrentExecutor(_ executor: Builtin.Executor) -> Bool
20+
21+
func getExecutor(_ a: AnyActor) -> Builtin.Executor {
22+
let pack = (a, UnsafeRawPointer?.none)
23+
return unsafeBitCast(pack, to: Builtin.Executor.self)
24+
}
25+
26+
func isCurrent(_ a: AnyActor) -> Bool {
27+
return isCurrentExecutor(getExecutor(a))
28+
}
29+
30+
func isMainThread() -> Bool {
31+
isCurrentExecutor(Builtin.buildMainActorExecutorRef())
32+
}
1433

1534
actor A {}
1635

@@ -28,26 +47,54 @@ distributed actor DA_userDefined {
2847
nonisolated deinit {}
2948
}
3049

31-
distributed actor DA_userDefined2 {
50+
distributed actor DA_userDefined_nonisolated {
3251
init(system: FakeActorSystem) {
3352
self.actorSystem = system
3453
}
3554

3655
nonisolated deinit {
37-
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self))")
56+
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
3857
}
3958
}
4059

41-
distributed actor DA_state {
42-
var name = "Hello"
43-
var age = 42
44-
60+
distributed actor DA_userDefined_isolated {
4561
init(system: FakeActorSystem) {
4662
self.actorSystem = system
4763
}
4864

65+
deinit {
66+
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
67+
}
68+
}
69+
70+
distributed actor DA_state_nonisolated {
71+
var name: String
72+
var age: Int
73+
74+
init(name: String, age: Int, system: FakeActorSystem) {
75+
self.name = name
76+
self.age = age
77+
self.actorSystem = system
78+
}
79+
4980
nonisolated deinit {
50-
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self))")
81+
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
82+
return
83+
}
84+
}
85+
86+
distributed actor DA_state_isolated {
87+
var name: String
88+
var age: Int
89+
90+
init(name: String, age: Int, system: FakeActorSystem) {
91+
self.name = name
92+
self.age = age
93+
self.actorSystem = system
94+
}
95+
96+
deinit {
97+
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
5198
return
5299
}
53100
}
@@ -69,6 +116,16 @@ final class FakeActorSystem: @unchecked Sendable, DistributedActorSystem {
69116
typealias ResultHandler = FakeResultHandler
70117

71118
var n = 0
119+
let group: DispatchGroup
120+
121+
init(group: DispatchGroup) {
122+
self.group = group
123+
}
124+
125+
deinit {
126+
print("Deinit ActorSystem: mainThread=\(isMainThread())")
127+
group.leave()
128+
}
72129

73130
func resolve<Act>(id: ActorID, as actorType: Act.Type) throws -> Act?
74131
where Act: DistributedActor,
@@ -174,7 +231,7 @@ typealias DefaultDistributedActorSystem = FakeActorSystem
174231
// ==== Execute ----------------------------------------------------------------
175232

176233
func test() {
177-
let system = DefaultDistributedActorSystem()
234+
let group = DispatchGroup()
178235

179236
// no lifecycle things make sense for a normal actor, double check we didn't emit them
180237
print("before A")
@@ -183,46 +240,98 @@ func test() {
183240
// CHECK: before A
184241
// CHECK: after A
185242

243+
group.enter()
186244
_ = { () -> DA in
187-
DA(system: system)
245+
DA(system: DefaultDistributedActorSystem(group: group))
188246
}()
247+
group.wait()
189248
// CHECK: assign type:DA, address:[[ADDRESS:.*]]
190249
// CHECK: ready actor:main.DA, address:ActorAddress(address: "[[ADDR1:addr-[0-9]]]")
191250
// CHECK: resign address:ActorAddress(address: "[[ADDR1]]")
251+
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
192252

253+
group.enter()
193254
_ = { () -> DA_userDefined in
194-
DA_userDefined(system: system)
255+
DA_userDefined(system: DefaultDistributedActorSystem(group: group))
195256
}()
257+
group.wait()
196258
// CHECK: assign type:DA_userDefined, address:[[ADDRESS:.*]]
197259
// CHECK: ready actor:main.DA_userDefined, address:ActorAddress(address: "[[ADDR2:addr-[0-9]]]")
198260
// CHECK: resign address:ActorAddress(address: "[[ADDR2]]")
261+
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
199262

200263
// resign must happen as the _last thing_ after user-deinit completed
201-
_ = { () -> DA_userDefined2 in
202-
DA_userDefined2(system: system)
264+
group.enter()
265+
_ = { () -> DA_userDefined_nonisolated in
266+
DA_userDefined_nonisolated(system: DefaultDistributedActorSystem(group: group))
203267
}()
204-
// CHECK: assign type:DA_userDefined2, address:[[ADDRESS:.*]]
205-
// CHECK: ready actor:main.DA_userDefined2, address:ActorAddress(address: "[[ADDR3:addr-[0-9]]]")
206-
// CHECK: Deinitializing ActorAddress(address: "[[ADDR3]]") remote:false
268+
group.wait()
269+
// CHECK: assign type:DA_userDefined_nonisolated, address:[[ADDRESS:.*]]
270+
// CHECK: ready actor:main.DA_userDefined_nonisolated, address:ActorAddress(address: "[[ADDR3:addr-[0-9]]]")
271+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR3]]") remote:false isolated:false
207272
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR3]]")
208-
273+
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
274+
209275
// resign must happen as the _last thing_ after user-deinit completed
210-
_ = { () -> DA_state in
211-
DA_state(system: system)
276+
group.enter()
277+
_ = { () -> DA_userDefined_isolated in
278+
DA_userDefined_isolated(system: DefaultDistributedActorSystem(group: group))
212279
}()
213-
// CHECK: assign type:DA_state, address:[[ADDRESS:.*]]
214-
// CHECK: ready actor:main.DA_state, address:ActorAddress(address: "[[ADDR4:addr-[0-9]]]")
215-
// CHECK: Deinitializing ActorAddress(address: "[[ADDR4]]") remote:false
280+
group.wait()
281+
// CHECK: assign type:DA_userDefined_isolated, address:[[ADDRESS:.*]]
282+
// CHECK: ready actor:main.DA_userDefined_isolated, address:ActorAddress(address: "[[ADDR4:addr-[0-9]]]")
283+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR4]]") remote:false isolated:true
216284
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR4]]")
285+
// CHECK-NEXT: Deinit ActorSystem: mainThread=false
217286

287+
// resign must happen as the _last thing_ after user-deinit completed
288+
group.enter()
289+
_ = { () -> DA_state_nonisolated in
290+
DA_state_nonisolated(name: "Foo", age:37, system: DefaultDistributedActorSystem(group: group))
291+
}()
292+
group.wait()
293+
// CHECK: assign type:DA_state_nonisolated, address:[[ADDRESS:.*]]
294+
// CHECK: ready actor:main.DA_state_nonisolated, address:ActorAddress(address: "[[ADDR5:addr-[0-9]]]")
295+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR5]]") name=Foo age=37 remote:false isolated:false
296+
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR5]]")
297+
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
298+
299+
// resign must happen as the _last thing_ after user-deinit completed
300+
group.enter()
301+
_ = { () -> DA_state_isolated in
302+
DA_state_isolated(name: "Bar", age:42, system: DefaultDistributedActorSystem(group: group))
303+
}()
304+
group.wait()
305+
// CHECK: assign type:DA_state_isolated, address:[[ADDRESS:.*]]
306+
// CHECK: ready actor:main.DA_state_isolated, address:ActorAddress(address: "[[ADDR6:addr-[0-9]]]")
307+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR6]]") name=Bar age=42 remote:false isolated:true
308+
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR6]]")
309+
// CHECK-NEXT: Deinit ActorSystem: mainThread=false
310+
311+
// a remote actor should not resign it's address, it was never "assigned" it
312+
group.enter()
313+
_ = { () -> DA_userDefined_nonisolated in
314+
let address = ActorAddress(parse: "remote-1")
315+
return try! DA_userDefined_nonisolated.resolve(id: address, using: DefaultDistributedActorSystem(group: group))
316+
}()
317+
group.wait()
318+
// CHECK-NEXT: resolve type:DA_userDefined_nonisolated, address:ActorAddress(address: "remote-1")
319+
// MUST NOT run deinit body for a remote distributed actor
320+
// CHECK-NOT: Deinitializing ActorAddress(address: "remote-1")
321+
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
322+
218323
// a remote actor should not resign it's address, it was never "assigned" it
219-
let address = ActorAddress(parse: "remote-1")
220-
_ = { () -> DA_userDefined2 in
221-
try! DA_userDefined2.resolve(id: address, using: system)
324+
group.enter()
325+
_ = { () -> DA_userDefined_isolated in
326+
let address = ActorAddress(parse: "remote-2")
327+
return try! DA_userDefined_isolated.resolve(id: address, using: DefaultDistributedActorSystem(group: group))
222328
}()
223-
// CHECK-NEXT: resolve type:DA_userDefined2, address:ActorAddress(address: "[[ADDR5:remote-1]]")
329+
group.wait()
330+
// CHECK-NEXT: resolve type:DA_userDefined_isolated, address:ActorAddress(address: "remote-2")
224331
// MUST NOT run deinit body for a remote distributed actor
225-
// CHECK-NOT: Deinitializing ActorAddress(address: "remote-1") remote:true
332+
// CHECK-NOT: Deinitializing ActorAddress(address: "remote-2")
333+
// TODO: Fix this. Remote proxies should not have isolated deinit.
334+
// CHECK-NEXT: Deinit ActorSystem: mainThread=false
226335

227336
print("DONE")
228337
// CHECK-NEXT: DONE

0 commit comments

Comments
 (0)