@@ -15,6 +15,28 @@ import _Concurrency
15
15
import Distributed
16
16
import Dispatch
17
17
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
+
18
40
@_silgen_name ( " swift_task_isCurrentExecutor " )
19
41
private func isCurrentExecutor( _ executor: Builtin . Executor ) -> Bool
20
42
@@ -27,7 +49,7 @@ func isCurrent(_ a: AnyActor) -> Bool {
27
49
return isCurrentExecutor ( getExecutor ( a) )
28
50
}
29
51
30
- func isMainThread ( ) -> Bool {
52
+ func isMainExecutor ( ) -> Bool {
31
53
isCurrentExecutor ( Builtin . buildMainActorExecutorRef ( ) )
32
54
}
33
55
@@ -53,7 +75,7 @@ distributed actor DA_userDefined_nonisolated {
53
75
}
54
76
55
77
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 ( ) ) " )
57
79
}
58
80
}
59
81
@@ -63,7 +85,7 @@ distributed actor DA_userDefined_isolated {
63
85
}
64
86
65
87
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 ( ) ) " )
67
89
}
68
90
}
69
91
@@ -78,7 +100,7 @@ distributed actor DA_state_nonisolated {
78
100
}
79
101
80
102
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 ( ) ) " )
82
104
return
83
105
}
84
106
}
@@ -94,7 +116,28 @@ distributed actor DA_state_isolated {
94
116
}
95
117
96
118
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 ( ) ) " )
98
141
return
99
142
}
100
143
}
@@ -123,7 +166,7 @@ final class FakeActorSystem: @unchecked Sendable, DistributedActorSystem {
123
166
}
124
167
125
168
deinit {
126
- print ( " Deinit ActorSystem: mainThread= \( isMainThread ( ) ) " )
169
+ print ( " Deinit ActorSystem: mainExecutor= \( isMainExecutor ( ) ) mainThread=\( isMainThread ( ) ) " )
127
170
group. leave ( )
128
171
}
129
172
@@ -248,7 +291,7 @@ func test() {
248
291
// CHECK: assign type:DA, address:[[ADDRESS:.*]]
249
292
// CHECK: ready actor:main.DA, address:ActorAddress(address: "[[ADDR1:addr-[0-9]]]")
250
293
// CHECK: resign address:ActorAddress(address: "[[ADDR1]]")
251
- // CHECK-NEXT: Deinit ActorSystem: mainThread=true
294
+ // CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
252
295
253
296
group. enter ( )
254
297
_ = { ( ) -> DA_userDefined in
@@ -258,7 +301,7 @@ func test() {
258
301
// CHECK: assign type:DA_userDefined, address:[[ADDRESS:.*]]
259
302
// CHECK: ready actor:main.DA_userDefined, address:ActorAddress(address: "[[ADDR2:addr-[0-9]]]")
260
303
// CHECK: resign address:ActorAddress(address: "[[ADDR2]]")
261
- // CHECK-NEXT: Deinit ActorSystem: mainThread=true
304
+ // CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
262
305
263
306
// resign must happen as the _last thing_ after user-deinit completed
264
307
group. enter ( )
@@ -268,9 +311,9 @@ func test() {
268
311
group. wait ( )
269
312
// CHECK: assign type:DA_userDefined_nonisolated, address:[[ADDRESS:.*]]
270
313
// 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
272
315
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR3]]")
273
- // CHECK-NEXT: Deinit ActorSystem: mainThread=true
316
+ // CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
274
317
275
318
// resign must happen as the _last thing_ after user-deinit completed
276
319
group. enter ( )
@@ -280,9 +323,9 @@ func test() {
280
323
group. wait ( )
281
324
// CHECK: assign type:DA_userDefined_isolated, address:[[ADDRESS:.*]]
282
325
// 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
284
327
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR4]]")
285
- // CHECK-NEXT: Deinit ActorSystem: mainThread =false
328
+ // CHECK-NEXT: Deinit ActorSystem: mainExecutor =false mainThread=true
286
329
287
330
// resign must happen as the _last thing_ after user-deinit completed
288
331
group. enter ( )
@@ -292,9 +335,9 @@ func test() {
292
335
group. wait ( )
293
336
// CHECK: assign type:DA_state_nonisolated, address:[[ADDRESS:.*]]
294
337
// 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
296
339
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR5]]")
297
- // CHECK-NEXT: Deinit ActorSystem: mainThread=true
340
+ // CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
298
341
299
342
// resign must happen as the _last thing_ after user-deinit completed
300
343
group. enter ( )
@@ -304,9 +347,21 @@ func test() {
304
347
group. wait ( )
305
348
// CHECK: assign type:DA_state_isolated, address:[[ADDRESS:.*]]
306
349
// 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
308
363
// CHECK-NEXT: resign address:ActorAddress(address: "[[ADDR6]]")
309
- // CHECK-NEXT: Deinit ActorSystem: mainThread=false
364
+ // CHECK-NEXT: Deinit ActorSystem: mainExecutor=false mainThread=false
310
365
311
366
// a remote actor should not resign it's address, it was never "assigned" it
312
367
group. enter ( )
@@ -318,7 +373,7 @@ func test() {
318
373
// CHECK-NEXT: resolve type:DA_userDefined_nonisolated, address:ActorAddress(address: "remote-1")
319
374
// MUST NOT run deinit body for a remote distributed actor
320
375
// CHECK-NOT: Deinitializing ActorAddress(address: "remote-1")
321
- // CHECK-NEXT: Deinit ActorSystem: mainThread=true
376
+ // CHECK-NEXT: Deinit ActorSystem: mainExecutor=true mainThread=true
322
377
323
378
// a remote actor should not resign it's address, it was never "assigned" it
324
379
group. enter ( )
@@ -330,14 +385,27 @@ func test() {
330
385
// CHECK-NEXT: resolve type:DA_userDefined_isolated, address:ActorAddress(address: "remote-2")
331
386
// MUST NOT run deinit body for a remote distributed actor
332
387
// 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
334
401
335
402
print ( " DONE " )
336
403
// CHECK-NEXT: DONE
337
404
}
338
405
339
406
@main struct Main {
340
407
static func main( ) async {
408
+ mainThread = getCurrentThreadID ( )
341
409
test ( )
342
410
}
343
411
}
0 commit comments