Skip to content

Commit 292f3e1

Browse files
Updated unit tests
1 parent f7aed4b commit 292f3e1

File tree

2 files changed

+120
-23
lines changed

2 files changed

+120
-23
lines changed

test/Concurrency/voucher_propagation.swift

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ actor Counter {
7676
func get() -> Int { n }
7777
}
7878

79-
actor ActorWithIsolatedDeinit {
79+
actor ActorWithSelfIsolatedDeinit {
8080
let expectedVoucher: voucher_t?
8181
let group: DispatchGroup
8282

@@ -102,6 +102,25 @@ actor ActorWithIsolatedDeinit {
102102
}
103103
}
104104

105+
actor ActorWithDeinitIsolatedOnAnother {
106+
let expectedVoucher: voucher_t?
107+
let group: DispatchGroup
108+
109+
init(expectedVoucher: voucher_t?, group: DispatchGroup) {
110+
self.expectedVoucher = expectedVoucher
111+
self.group = group
112+
}
113+
114+
@AnotherActor
115+
deinit {
116+
expectTrue(isCurrentExecutor(AnotherActor.shared.unownedExecutor))
117+
let currentVoucher = voucher_copy()
118+
expectEqual(expectedVoucher, currentVoucher)
119+
os_release(currentVoucher)
120+
group.leave()
121+
}
122+
}
123+
105124
class ClassWithIsolatedDeinit {
106125
let expectedVoucher: voucher_t?
107126
let group: DispatchGroup
@@ -413,11 +432,21 @@ if #available(SwiftStdlib 5.1, *) {
413432
withVouchers { v1, v2, v3 in
414433
let group = DispatchGroup()
415434
group.enter()
435+
group.enter()
436+
group.enter()
416437
Task {
417438
await AnotherActor.shared.performTesting {
418439
adopt(voucher: v1)
419440
_ = ClassWithIsolatedDeinit(expectedVoucher: v1, group: group)
420441
}
442+
await AnotherActor.shared.performTesting {
443+
adopt(voucher: v2)
444+
_ = ActorWithSelfIsolatedDeinit(expectedVoucher: v2, group: group)
445+
}
446+
await AnotherActor.shared.performTesting {
447+
adopt(voucher: v3)
448+
_ = ActorWithDeinitIsolatedOnAnother(expectedVoucher: v3, group: group)
449+
}
421450
}
422451
group.wait()
423452
}
@@ -430,12 +459,12 @@ if #available(SwiftStdlib 5.1, *) {
430459
group.enter()
431460
Task {
432461
do {
433-
adopt(voucher: v2)
434-
_ = ActorWithIsolatedDeinit(expectedVoucher: v2, group: group)
462+
adopt(voucher: v1)
463+
_ = ActorWithDeinitIsolatedOnAnother(expectedVoucher: v1, group: group)
435464
}
436465
do {
437-
adopt(voucher: v3)
438-
_ = ClassWithIsolatedDeinit(expectedVoucher: v3, group: group)
466+
adopt(voucher: v2)
467+
_ = ClassWithIsolatedDeinit(expectedVoucher: v2, group: group)
439468
}
440469
}
441470
group.wait()

test/Distributed/Runtime/distributed_actor_deinit.swift

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,28 @@ import Distributed
1414
@preconcurrency import Dispatch
1515
import StdlibUnittest
1616

17+
#if canImport(Darwin)
18+
import Darwin
19+
typealias ThreadID = pthread_t
20+
func getCurrentThreadID() -> ThreadID { pthread_self() }
21+
func equalThreadIDs(_ a: ThreadID, _ b: ThreadID) -> Bool { pthread_equal(a, b) != 0 }
22+
#elseif canImport(Glibc)
23+
import Glibc
24+
typealias ThreadID = pthread_t
25+
func getCurrentThreadID() -> ThreadID { pthread_self() }
26+
func equalThreadIDs(_ a: ThreadID, _ b: ThreadID) -> Bool { pthread_equal(a, b) != 0 }
27+
#elseif os(Windows)
28+
import WinSDK
29+
typealias ThreadID = UInt32
30+
func getCurrentThreadID() -> ThreadID { GetCurrentThreadId() }
31+
func equalThreadIDs(_ a: ThreadID, _ b: ThreadID) -> Bool { a == b }
32+
#endif
33+
34+
var mainThread: ThreadID?
35+
func isMainThread() -> Bool {
36+
return equalThreadIDs(getCurrentThreadID(), mainThread!)
37+
}
38+
1739
// Look up a symbol using dlsym and cast the result to an arbitrary type.
1840
func lookup<T>(_ name: String) -> T {
1941
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
@@ -33,7 +55,7 @@ func isCurrent(_ a: AnyActor) -> Bool {
3355
return isCurrentExecutor(getExecutor(a))
3456
}
3557

36-
func isMainThread() -> Bool {
58+
func isMainExecutor() -> Bool {
3759
isCurrentExecutor(getMainExecutor())
3860
}
3961

@@ -59,7 +81,7 @@ distributed actor DA_userDefined_nonisolated {
5981
}
6082

6183
nonisolated deinit {
62-
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
84+
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self)) mainThread:\(isMainThread())")
6385
}
6486
}
6587

@@ -69,7 +91,7 @@ distributed actor DA_userDefined_isolated {
6991
}
7092

7193
deinit {
72-
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
94+
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self)) mainThread:\(isMainThread())")
7395
}
7496
}
7597

@@ -84,7 +106,7 @@ distributed actor DA_state_nonisolated {
84106
}
85107

86108
nonisolated deinit {
87-
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
109+
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self)) mainThread:\(isMainThread())")
88110
return
89111
}
90112
}
@@ -100,7 +122,28 @@ distributed actor DA_state_isolated {
100122
}
101123

102124
deinit {
103-
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
125+
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self)) mainThread:\(isMainThread())")
126+
return
127+
}
128+
}
129+
130+
@globalActor actor AnotherActor: GlobalActor {
131+
static let shared = AnotherActor()
132+
}
133+
134+
distributed actor DA_state_isolated_on_another {
135+
var name: String
136+
var age: Int
137+
138+
init(name: String, age: Int, system: FakeActorSystem) {
139+
self.name = name
140+
self.age = age
141+
self.actorSystem = system
142+
}
143+
144+
@AnotherActor
145+
deinit {
146+
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated-self:\(isCurrent(self)) isolated-other:\(isCurrent(AnotherActor.shared)) mainThread:\(isMainThread())")
104147
return
105148
}
106149
}
@@ -129,7 +172,7 @@ final class FakeActorSystem: @unchecked Sendable, DistributedActorSystem {
129172
}
130173

131174
deinit {
132-
print("Deinit ActorSystem: mainThread=\(isMainThread())")
175+
print("Deinit ActorSystem: mainExecutor=\(isMainExecutor()) mainThread=\(isMainThread())")
133176
group.leave()
134177
}
135178

@@ -254,7 +297,7 @@ func test() {
254297
// CHECK: assign type:DA, address:[[ADDRESS:.*]]
255298
// CHECK: ready actor:main.DA, address:ActorAddress(address: "[[ADDR1:addr-[0-9]]]")
256299
// CHECK: resign address:ActorAddress(address: "[[ADDR1]]")
257-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
300+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
258301

259302
group.enter()
260303
_ = { () -> DA_userDefined in
@@ -264,7 +307,7 @@ func test() {
264307
// CHECK: assign type:DA_userDefined, address:[[ADDRESS:.*]]
265308
// CHECK: ready actor:main.DA_userDefined, address:ActorAddress(address: "[[ADDR2:addr-[0-9]]]")
266309
// CHECK: resign address:ActorAddress(address: "[[ADDR2]]")
267-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
310+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
268311

269312
// resign must happen as the _last thing_ after user-deinit completed
270313
group.enter()
@@ -274,9 +317,9 @@ func test() {
274317
group.wait()
275318
// CHECK: assign type:DA_userDefined_nonisolated, address:[[ADDRESS:.*]]
276319
// CHECK: ready actor:main.DA_userDefined_nonisolated, address:ActorAddress(address: "[[ADDR3:addr-[0-9]]]")
277-
// CHECK: Deinitializing ActorAddress(address: "[[ADDR3]]") remote:false isolated:false
320+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR3]]") remote:false isolated:false mainThread:true
278321
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR3]]")
279-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
322+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
280323

281324
// resign must happen as the _last thing_ after user-deinit completed
282325
group.enter()
@@ -286,9 +329,9 @@ func test() {
286329
group.wait()
287330
// CHECK: assign type:DA_userDefined_isolated, address:[[ADDRESS:.*]]
288331
// CHECK: ready actor:main.DA_userDefined_isolated, address:ActorAddress(address: "[[ADDR4:addr-[0-9]]]")
289-
// CHECK: Deinitializing ActorAddress(address: "[[ADDR4]]") remote:false isolated:true
332+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR4]]") remote:false isolated:true mainThread:true
290333
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR4]]")
291-
// CHECK-NEXT: Deinit ActorSystem: mainThread=false
334+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=false mainThread=true
292335

293336
// resign must happen as the _last thing_ after user-deinit completed
294337
group.enter()
@@ -298,9 +341,9 @@ func test() {
298341
group.wait()
299342
// CHECK: assign type:DA_state_nonisolated, address:[[ADDRESS:.*]]
300343
// CHECK: ready actor:main.DA_state_nonisolated, address:ActorAddress(address: "[[ADDR5:addr-[0-9]]]")
301-
// CHECK: Deinitializing ActorAddress(address: "[[ADDR5]]") name=Foo age=37 remote:false isolated:false
344+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR5]]") name=Foo age=37 remote:false isolated:false mainThread:true
302345
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR5]]")
303-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
346+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
304347

305348
// resign must happen as the _last thing_ after user-deinit completed
306349
group.enter()
@@ -310,9 +353,21 @@ func test() {
310353
group.wait()
311354
// CHECK: assign type:DA_state_isolated, address:[[ADDRESS:.*]]
312355
// CHECK: ready actor:main.DA_state_isolated, address:ActorAddress(address: "[[ADDR6:addr-[0-9]]]")
313-
// CHECK: Deinitializing ActorAddress(address: "[[ADDR6]]") name=Bar age=42 remote:false isolated:true
356+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR6]]") name=Bar age=42 remote:false isolated:true mainThread:true
357+
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR6]]")
358+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=false mainThread=true
359+
360+
// resign must happen as the _last thing_ after user-deinit completed
361+
group.enter()
362+
_ = { () -> DA_state_isolated_on_another in
363+
DA_state_isolated_on_another(name: "Baz", age:57, system: DefaultDistributedActorSystem(group: group))
364+
}()
365+
group.wait()
366+
// CHECK: assign type:DA_state_isolated_on_another, address:[[ADDRESS:.*]]
367+
// CHECK: ready actor:main.DA_state_isolated_on_another, address:ActorAddress(address: "[[ADDR6:addr-[0-9]]]")
368+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR6]]") name=Baz age=57 remote:false isolated-self:false isolated-other:true mainThread:false
314369
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR6]]")
315-
// CHECK-NEXT: Deinit ActorSystem: mainThread=false
370+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=false mainThread=false
316371

317372
// a remote actor should not resign it's address, it was never "assigned" it
318373
group.enter()
@@ -324,7 +379,7 @@ func test() {
324379
// CHECK-NEXT: resolve type:DA_userDefined_nonisolated, address:ActorAddress(address: "remote-1")
325380
// MUST NOT run deinit body for a remote distributed actor
326381
// CHECK-NOT: Deinitializing ActorAddress(address: "remote-1")
327-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
382+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
328383

329384
// a remote actor should not resign it's address, it was never "assigned" it
330385
group.enter()
@@ -336,14 +391,27 @@ func test() {
336391
// CHECK-NEXT: resolve type:DA_userDefined_isolated, address:ActorAddress(address: "remote-2")
337392
// MUST NOT run deinit body for a remote distributed actor
338393
// CHECK-NOT: Deinitializing ActorAddress(address: "remote-2")
339-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
394+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
395+
396+
// a remote actor should not resign it's address, it was never "assigned" it
397+
group.enter()
398+
_ = { () -> DA_state_isolated_on_another in
399+
let address = ActorAddress(parse: "remote-3")
400+
return try! DA_state_isolated_on_another.resolve(id: address, using: DefaultDistributedActorSystem(group: group))
401+
}()
402+
group.wait()
403+
// CHECK-NEXT: resolve type:DA_state_isolated_on_another, address:ActorAddress(address: "remote-3")
404+
// MUST NOT run deinit body for a remote distributed actor
405+
// CHECK-NOT: Deinitializing ActorAddress(address: "remote-3")
406+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
340407

341408
print("DONE")
342409
// CHECK-NEXT: DONE
343410
}
344411

345412
@main struct Main {
346413
static func main() async {
414+
mainThread = getCurrentThreadID()
347415
test()
348416
}
349417
}

0 commit comments

Comments
 (0)