11
11
//===----------------------------------------------------------------------===//
12
12
13
13
import Swift
14
+ import _Concurrency
14
15
15
16
#if canImport(Darwin)
16
17
import Darwin
@@ -26,25 +27,33 @@ import WinSDK
26
27
/// for learning about `distributed actor` isolation, as well as early
27
28
/// prototyping stages of development where a real system is not necessary yet.
28
29
@available ( SwiftStdlib 5 . 7 , * )
29
- public final class LocalTestingDistributedActorSystem : DistributedActorSystem , @unchecked Sendable {
30
+ public struct LocalTestingDistributedActorSystem : DistributedActorSystem , @unchecked Sendable {
30
31
public typealias ActorID = LocalTestingActorAddress
31
32
public typealias ResultHandler = LocalTestingInvocationResultHandler
32
33
public typealias InvocationEncoder = LocalTestingInvocationEncoder
33
34
public typealias InvocationDecoder = LocalTestingInvocationDecoder
34
- public typealias SerializationRequirement = Codable
35
+ public typealias SerializationRequirement = any Codable
36
+
35
37
36
- private var activeActors : [ ActorID : any DistributedActor ] = [ : ]
37
- private let activeActorsLock = _Lock ( )
38
+ @ usableFromInline
39
+ final class _Storage {
38
40
39
- private var idProvider : ActorIDProvider = ActorIDProvider ( )
40
- private var assignedIDs : Set < ActorID > = [ ]
41
- private let assignedIDsLock = _Lock ( )
41
+ var activeActors : [ ActorID : any DistributedActor ] = [ : ]
42
+ let activeActorsLock = _Lock ( )
42
43
43
- public init ( ) { }
44
+ var assignedIDs : Set < ActorID > = [ ]
45
+ let assignedIDsLock = _Lock ( )
46
+ }
47
+ let storage : _Storage
48
+ var idProvider : ActorIDProvider = ActorIDProvider ( )
49
+
50
+ public init ( ) {
51
+ storage = . init( )
52
+ }
44
53
45
54
public func resolve< Act> ( id: ActorID , as actorType: Act . Type )
46
- throws -> Act ? where Act: DistributedActor {
47
- guard let anyActor = self . activeActorsLock. withLock ( { self . activeActors [ id] } ) else {
55
+ throws -> Act ? where Act: DistributedActor , Act . ID == ActorID {
56
+ guard let anyActor = storage . activeActorsLock. withLock ( { self . storage . activeActors [ id] } ) else {
48
57
throw LocalTestingDistributedActorSystemError ( message: " Unable to locate id ' \( id) ' locally " )
49
58
}
50
59
guard let actor = anyActor as? Act else {
@@ -54,28 +63,25 @@ public final class LocalTestingDistributedActorSystem: DistributedActorSystem, @
54
63
}
55
64
56
65
public func assignID< Act> ( _ actorType: Act . Type ) -> ActorID
57
- where Act: DistributedActor {
66
+ where Act: DistributedActor , Act . ID == ActorID {
58
67
let id = self . idProvider. next ( )
59
- self . assignedIDsLock. withLock {
60
- self . assignedIDs. insert ( id)
68
+ storage . assignedIDsLock. withLock {
69
+ self . storage . assignedIDs. insert ( id)
61
70
}
62
71
return id
63
72
}
64
73
65
74
public func actorReady< Act> ( _ actor : Act )
66
- where Act: DistributedActor ,
67
- Act. ID == ActorID {
68
- guard self . assignedIDsLock. withLock ( { self . assignedIDs. contains ( actor . id) } ) else {
75
+ where Act: DistributedActor , Act. ID == ActorID {
76
+ guard storage. assignedIDsLock. withLock ( { self . storage. assignedIDs. contains ( actor . id) } ) else {
69
77
fatalError ( " Attempted to mark an unknown actor ' \( actor . id) ' ready " )
70
78
}
71
- self . activeActorsLock. withLock {
72
- self . activeActors [ actor . id] = actor
73
- }
79
+ self . storage. activeActors [ actor . id] = actor
74
80
}
75
81
76
82
public func resignID( _ id: ActorID ) {
77
- self . activeActorsLock. withLock {
78
- self . activeActors. removeValue ( forKey: id)
83
+ storage . activeActorsLock. withLock {
84
+ self . storage . activeActors. removeValue ( forKey: id)
79
85
}
80
86
}
81
87
@@ -93,7 +99,7 @@ public final class LocalTestingDistributedActorSystem: DistributedActorSystem, @
93
99
where Act: DistributedActor ,
94
100
Act. ID == ActorID ,
95
101
Err: Error ,
96
- Res: SerializationRequirement {
102
+ Res: Codable {
97
103
fatalError ( " Attempted to make remote call to \( target) on actor \( actor ) using a local-only actor system " )
98
104
}
99
105
@@ -109,38 +115,40 @@ public final class LocalTestingDistributedActorSystem: DistributedActorSystem, @
109
115
fatalError ( " Attempted to make remote call to \( target) on actor \( actor ) using a local-only actor system " )
110
116
}
111
117
112
- private struct ActorIDProvider {
118
+ @usableFromInline
119
+ final class ActorIDProvider {
113
120
private var counter : Int = 0
114
121
private let counterLock = _Lock ( )
115
122
123
+ @usableFromInline
116
124
init ( ) { }
117
125
118
- mutating func next( ) -> LocalTestingActorAddress {
126
+ func next( ) -> LocalTestingActorAddress {
119
127
let id : Int = self . counterLock. withLock {
120
128
self . counter += 1
121
129
return self . counter
122
130
}
123
- return LocalTestingActorAddress ( parse : " \( id ) " )
131
+ return LocalTestingActorAddress ( id )
124
132
}
125
133
}
126
134
}
127
135
128
136
@available ( SwiftStdlib 5 . 7 , * )
129
137
public struct LocalTestingActorAddress : Hashable , Sendable , Codable {
130
- public let address : String
138
+ public let uuid : String
131
139
132
- public init ( parse address : String ) {
133
- self . address = address
140
+ public init ( _ uuid : Int ) {
141
+ self . uuid = " \( uuid ) "
134
142
}
135
143
136
144
public init ( from decoder: Decoder ) throws {
137
145
let container = try decoder. singleValueContainer ( )
138
- self . address = try container. decode ( String . self)
146
+ self . uuid = try container. decode ( String . self)
139
147
}
140
148
141
149
public func encode( to encoder: Encoder ) throws {
142
150
var container = encoder. singleValueContainer ( )
143
- try container. encode ( self . address )
151
+ try container. encode ( self . uuid )
144
152
}
145
153
}
146
154
@@ -220,7 +228,7 @@ public struct LocalTestingDistributedActorSystemError: DistributedActorSystemErr
220
228
// === lock ----------------------------------------------------------------
221
229
222
230
@available ( SwiftStdlib 5 . 7 , * )
223
- fileprivate class _Lock {
231
+ internal class _Lock {
224
232
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
225
233
private let underlying : UnsafeMutablePointer < os_unfair_lock >
226
234
#elseif os(Windows)
@@ -233,10 +241,27 @@ fileprivate class _Lock {
233
241
private let underlying : UnsafeMutablePointer < pthread_mutex_t >
234
242
#endif
235
243
244
+ init ( ) {
245
+ #if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
246
+ self . underlying = UnsafeMutablePointer . allocate ( capacity: 1 )
247
+ self . underlying. initialize ( to: os_unfair_lock ( ) )
248
+ #elseif os(Windows)
249
+ self . underlying = UnsafeMutablePointer . allocate ( capacity: 1 )
250
+ InitializeSRWLock ( self . underlying)
251
+ #elseif os(WASI)
252
+ // WASI environment has only a single thread
253
+ #else
254
+ self . underlying = UnsafeMutablePointer . allocate ( capacity: 1 )
255
+ guard pthread_mutex_init ( self . underlying, nil ) == 0 else {
256
+ fatalError ( " pthread_mutex_init failed " )
257
+ }
258
+ #endif
259
+ }
260
+
236
261
deinit {
237
262
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
238
263
// `os_unfair_lock`s do not need to be explicitly destroyed
239
- #elseif os(Windows)
264
+ #elseif os(Windows)
240
265
// `SRWLOCK`s do not need to be explicitly destroyed
241
266
#elseif os(WASI)
242
267
// WASI environment has only a single thread
@@ -252,22 +277,6 @@ fileprivate class _Lock {
252
277
#endif
253
278
}
254
279
255
- init ( ) {
256
- #if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
257
- self . underlying = UnsafeMutablePointer . allocate ( capacity: 1 )
258
- #elseif os(Windows)
259
- self . underlying = UnsafeMutablePointer . allocate ( capacity: 1 )
260
- InitializeSRWLock ( self . underlying)
261
- #elseif os(WASI)
262
- // WASI environment has only a single thread
263
- #else
264
- self . underlying = UnsafeMutablePointer . allocate ( capacity: 1 )
265
- guard pthread_mutex_init ( self . underlying, nil ) == 0 else {
266
- fatalError ( " pthread_mutex_init failed " )
267
- }
268
- #endif
269
- }
270
-
271
280
@discardableResult
272
281
func withLock< T> ( _ body: ( ) -> T ) -> T {
273
282
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
0 commit comments