Skip to content

Commit 7505cd2

Browse files
Updated unit tests
1 parent 35f0334 commit 7505cd2

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
@@ -75,7 +75,7 @@ actor Counter {
7575
func get() -> Int { n }
7676
}
7777

78-
actor ActorWithIsolatedDeinit {
78+
actor ActorWithSelfIsolatedDeinit {
7979
let expectedVoucher: voucher_t?
8080
let group: DispatchGroup
8181

@@ -101,6 +101,25 @@ actor ActorWithIsolatedDeinit {
101101
}
102102
}
103103

104+
actor ActorWithDeinitIsolatedOnAnother {
105+
let expectedVoucher: voucher_t?
106+
let group: DispatchGroup
107+
108+
init(expectedVoucher: voucher_t?, group: DispatchGroup) {
109+
self.expectedVoucher = expectedVoucher
110+
self.group = group
111+
}
112+
113+
@AnotherActor
114+
deinit {
115+
expectTrue(isCurrentExecutor(AnotherActor.shared.unownedExecutor))
116+
let currentVoucher = voucher_copy()
117+
expectEqual(expectedVoucher, currentVoucher)
118+
os_release(currentVoucher)
119+
group.leave()
120+
}
121+
}
122+
104123
class ClassWithIsolatedDeinit {
105124
let expectedVoucher: voucher_t?
106125
let group: DispatchGroup
@@ -412,11 +431,21 @@ if #available(SwiftStdlib 5.1, *) {
412431
withVouchers { v1, v2, v3 in
413432
let group = DispatchGroup()
414433
group.enter()
434+
group.enter()
435+
group.enter()
415436
Task {
416437
await AnotherActor.shared.performTesting {
417438
adopt(voucher: v1)
418439
_ = ClassWithIsolatedDeinit(expectedVoucher: v1, group: group)
419440
}
441+
await AnotherActor.shared.performTesting {
442+
adopt(voucher: v2)
443+
_ = ActorWithSelfIsolatedDeinit(expectedVoucher: v2, group: group)
444+
}
445+
await AnotherActor.shared.performTesting {
446+
adopt(voucher: v3)
447+
_ = ActorWithDeinitIsolatedOnAnother(expectedVoucher: v3, group: group)
448+
}
420449
}
421450
group.wait()
422451
}
@@ -429,12 +458,12 @@ if #available(SwiftStdlib 5.1, *) {
429458
group.enter()
430459
Task {
431460
do {
432-
adopt(voucher: v2)
433-
_ = ActorWithIsolatedDeinit(expectedVoucher: v2, group: group)
461+
adopt(voucher: v1)
462+
_ = ActorWithDeinitIsolatedOnAnother(expectedVoucher: v1, group: group)
434463
}
435464
do {
436-
adopt(voucher: v3)
437-
_ = ClassWithIsolatedDeinit(expectedVoucher: v3, group: group)
465+
adopt(voucher: v2)
466+
_ = ClassWithIsolatedDeinit(expectedVoucher: v2, group: group)
438467
}
439468
}
440469
group.wait()

test/Distributed/Runtime/distributed_actor_deinit.swift

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,28 @@ import _Concurrency
1515
import Distributed
1616
import Dispatch
1717

18+
#if canImport(Darwin)
19+
import Darwin
20+
typealias ThreadID = pthread_t
21+
func getCurrentThreadID() -> ThreadID { pthread_self() }
22+
func equalThreadIDs(_ a: ThreadID, _ b: ThreadID) -> Bool { pthread_equal(a, b) != 0 }
23+
#elseif canImport(Glibc)
24+
import Glibc
25+
typealias ThreadID = pthread_t
26+
func getCurrentThreadID() -> ThreadID { pthread_self() }
27+
func equalThreadIDs(_ a: ThreadID, _ b: ThreadID) -> Bool { pthread_equal(a, b) != 0 }
28+
#elseif os(Windows)
29+
import WinSDK
30+
typealias ThreadID = UInt32
31+
func getCurrentThreadID() -> ThreadID { GetCurrentThreadId() }
32+
func equalThreadIDs(_ a: ThreadID, _ b: ThreadID) -> Bool { a == b }
33+
#endif
34+
35+
var mainThread: ThreadID?
36+
func isMainThread() -> Bool {
37+
return equalThreadIDs(getCurrentThreadID(), mainThread!)
38+
}
39+
1840
@_silgen_name("swift_task_isCurrentExecutor")
1941
private func isCurrentExecutor(_ executor: Builtin.Executor) -> Bool
2042

@@ -27,7 +49,7 @@ func isCurrent(_ a: AnyActor) -> Bool {
2749
return isCurrentExecutor(getExecutor(a))
2850
}
2951

30-
func isMainThread() -> Bool {
52+
func isMainExecutor() -> Bool {
3153
isCurrentExecutor(Builtin.buildMainActorExecutorRef())
3254
}
3355

@@ -53,7 +75,7 @@ distributed actor DA_userDefined_nonisolated {
5375
}
5476

5577
nonisolated deinit {
56-
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
78+
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self)) mainThread:\(isMainThread())")
5779
}
5880
}
5981

@@ -63,7 +85,7 @@ distributed actor DA_userDefined_isolated {
6385
}
6486

6587
deinit {
66-
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
88+
print("Deinitializing \(self.id) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self)) mainThread:\(isMainThread())")
6789
}
6890
}
6991

@@ -78,7 +100,7 @@ distributed actor DA_state_nonisolated {
78100
}
79101

80102
nonisolated deinit {
81-
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
103+
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self)) mainThread:\(isMainThread())")
82104
return
83105
}
84106
}
@@ -94,7 +116,28 @@ distributed actor DA_state_isolated {
94116
}
95117

96118
deinit {
97-
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self))")
119+
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated:\(isCurrent(self)) mainThread:\(isMainThread())")
120+
return
121+
}
122+
}
123+
124+
@globalActor actor AnotherActor: GlobalActor {
125+
static let shared = AnotherActor()
126+
}
127+
128+
distributed actor DA_state_isolated_on_another {
129+
var name: String
130+
var age: Int
131+
132+
init(name: String, age: Int, system: FakeActorSystem) {
133+
self.name = name
134+
self.age = age
135+
self.actorSystem = system
136+
}
137+
138+
@AnotherActor
139+
deinit {
140+
print("Deinitializing \(self.id) name=\(name) age=\(age) remote:\(__isRemoteActor(self)) isolated-self:\(isCurrent(self)) isolated-other:\(isCurrent(AnotherActor.shared)) mainThread:\(isMainThread())")
98141
return
99142
}
100143
}
@@ -123,7 +166,7 @@ final class FakeActorSystem: @unchecked Sendable, DistributedActorSystem {
123166
}
124167

125168
deinit {
126-
print("Deinit ActorSystem: mainThread=\(isMainThread())")
169+
print("Deinit ActorSystem: mainExecutor=\(isMainExecutor()) mainThread=\(isMainThread())")
127170
group.leave()
128171
}
129172

@@ -248,7 +291,7 @@ func test() {
248291
// CHECK: assign type:DA, address:[[ADDRESS:.*]]
249292
// CHECK: ready actor:main.DA, address:ActorAddress(address: "[[ADDR1:addr-[0-9]]]")
250293
// CHECK: resign address:ActorAddress(address: "[[ADDR1]]")
251-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
294+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
252295

253296
group.enter()
254297
_ = { () -> DA_userDefined in
@@ -258,7 +301,7 @@ func test() {
258301
// CHECK: assign type:DA_userDefined, address:[[ADDRESS:.*]]
259302
// CHECK: ready actor:main.DA_userDefined, address:ActorAddress(address: "[[ADDR2:addr-[0-9]]]")
260303
// CHECK: resign address:ActorAddress(address: "[[ADDR2]]")
261-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
304+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
262305

263306
// resign must happen as the _last thing_ after user-deinit completed
264307
group.enter()
@@ -268,9 +311,9 @@ func test() {
268311
group.wait()
269312
// CHECK: assign type:DA_userDefined_nonisolated, address:[[ADDRESS:.*]]
270313
// CHECK: ready actor:main.DA_userDefined_nonisolated, address:ActorAddress(address: "[[ADDR3:addr-[0-9]]]")
271-
// CHECK: Deinitializing ActorAddress(address: "[[ADDR3]]") remote:false isolated:false
314+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR3]]") remote:false isolated:false mainThread:true
272315
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR3]]")
273-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
316+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
274317

275318
// resign must happen as the _last thing_ after user-deinit completed
276319
group.enter()
@@ -280,9 +323,9 @@ func test() {
280323
group.wait()
281324
// CHECK: assign type:DA_userDefined_isolated, address:[[ADDRESS:.*]]
282325
// CHECK: ready actor:main.DA_userDefined_isolated, address:ActorAddress(address: "[[ADDR4:addr-[0-9]]]")
283-
// CHECK: Deinitializing ActorAddress(address: "[[ADDR4]]") remote:false isolated:true
326+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR4]]") remote:false isolated:true mainThread:true
284327
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR4]]")
285-
// CHECK-NEXT: Deinit ActorSystem: mainThread=false
328+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=false mainThread=true
286329

287330
// resign must happen as the _last thing_ after user-deinit completed
288331
group.enter()
@@ -292,9 +335,9 @@ func test() {
292335
group.wait()
293336
// CHECK: assign type:DA_state_nonisolated, address:[[ADDRESS:.*]]
294337
// 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
338+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR5]]") name=Foo age=37 remote:false isolated:false mainThread:true
296339
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR5]]")
297-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
340+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
298341

299342
// resign must happen as the _last thing_ after user-deinit completed
300343
group.enter()
@@ -304,9 +347,21 @@ func test() {
304347
group.wait()
305348
// CHECK: assign type:DA_state_isolated, address:[[ADDRESS:.*]]
306349
// 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
350+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR6]]") name=Bar age=42 remote:false isolated:true mainThread:true
351+
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR6]]")
352+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=false mainThread=true
353+
354+
// resign must happen as the _last thing_ after user-deinit completed
355+
group.enter()
356+
_ = { () -> DA_state_isolated_on_another in
357+
DA_state_isolated_on_another(name: "Baz", age:57, system: DefaultDistributedActorSystem(group: group))
358+
}()
359+
group.wait()
360+
// CHECK: assign type:DA_state_isolated_on_another, address:[[ADDRESS:.*]]
361+
// CHECK: ready actor:main.DA_state_isolated_on_another, address:ActorAddress(address: "[[ADDR6:addr-[0-9]]]")
362+
// CHECK: Deinitializing ActorAddress(address: "[[ADDR6]]") name=Baz age=57 remote:false isolated-self:false isolated-other:true mainThread:false
308363
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR6]]")
309-
// CHECK-NEXT: Deinit ActorSystem: mainThread=false
364+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=false mainThread=false
310365

311366
// a remote actor should not resign it's address, it was never "assigned" it
312367
group.enter()
@@ -318,7 +373,7 @@ func test() {
318373
// CHECK-NEXT: resolve type:DA_userDefined_nonisolated, address:ActorAddress(address: "remote-1")
319374
// MUST NOT run deinit body for a remote distributed actor
320375
// CHECK-NOT: Deinitializing ActorAddress(address: "remote-1")
321-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
376+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
322377

323378
// a remote actor should not resign it's address, it was never "assigned" it
324379
group.enter()
@@ -330,14 +385,27 @@ func test() {
330385
// CHECK-NEXT: resolve type:DA_userDefined_isolated, address:ActorAddress(address: "remote-2")
331386
// MUST NOT run deinit body for a remote distributed actor
332387
// CHECK-NOT: Deinitializing ActorAddress(address: "remote-2")
333-
// CHECK-NEXT: Deinit ActorSystem: mainThread=true
388+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
389+
390+
// a remote actor should not resign it's address, it was never "assigned" it
391+
group.enter()
392+
_ = { () -> DA_state_isolated_on_another in
393+
let address = ActorAddress(parse: "remote-3")
394+
return try! DA_state_isolated_on_another.resolve(id: address, using: DefaultDistributedActorSystem(group: group))
395+
}()
396+
group.wait()
397+
// CHECK-NEXT: resolve type:DA_state_isolated_on_another, address:ActorAddress(address: "remote-3")
398+
// MUST NOT run deinit body for a remote distributed actor
399+
// CHECK-NOT: Deinitializing ActorAddress(address: "remote-3")
400+
// CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
334401

335402
print("DONE")
336403
// CHECK-NEXT: DONE
337404
}
338405

339406
@main struct Main {
340407
static func main() async {
408+
mainThread = getCurrentThreadID()
341409
test()
342410
}
343411
}

0 commit comments

Comments
 (0)