1111//===----------------------------------------------------------------------===//
1212
1313import Swift
14+ import _Concurrency
1415
1516#if canImport(Darwin)
1617import Darwin
@@ -26,25 +27,33 @@ import WinSDK
2627/// for learning about `distributed actor` isolation, as well as early
2728/// prototyping stages of development where a real system is not necessary yet.
2829@available ( SwiftStdlib 5 . 7 , * )
29- public final class LocalTestingDistributedActorSystem : DistributedActorSystem , @unchecked Sendable {
30+ public struct LocalTestingDistributedActorSystem : DistributedActorSystem , @unchecked Sendable {
3031 public typealias ActorID = LocalTestingActorAddress
3132 public typealias ResultHandler = LocalTestingInvocationResultHandler
3233 public typealias InvocationEncoder = LocalTestingInvocationEncoder
3334 public typealias InvocationDecoder = LocalTestingInvocationDecoder
34- public typealias SerializationRequirement = Codable
35+ public typealias SerializationRequirement = any Codable
36+
3537
36- private var activeActors : [ ActorID : any DistributedActor ] = [ : ]
37- private let activeActorsLock = _Lock ( )
38+ @ usableFromInline
39+ final class _Storage {
3840
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 ( )
4243
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+ }
4453
4554 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 {
4857 throw LocalTestingDistributedActorSystemError ( message: " Unable to locate id ' \( id) ' locally " )
4958 }
5059 guard let actor = anyActor as? Act else {
@@ -54,28 +63,25 @@ public final class LocalTestingDistributedActorSystem: DistributedActorSystem, @
5463 }
5564
5665 public func assignID< Act> ( _ actorType: Act . Type ) -> ActorID
57- where Act: DistributedActor {
66+ where Act: DistributedActor , Act . ID == ActorID {
5867 let id = self . idProvider. next ( )
59- self . assignedIDsLock. withLock {
60- self . assignedIDs. insert ( id)
68+ storage . assignedIDsLock. withLock {
69+ self . storage . assignedIDs. insert ( id)
6170 }
6271 return id
6372 }
6473
6574 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 {
6977 fatalError ( " Attempted to mark an unknown actor ' \( actor . id) ' ready " )
7078 }
71- self . activeActorsLock. withLock {
72- self . activeActors [ actor . id] = actor
73- }
79+ self . storage. activeActors [ actor . id] = actor
7480 }
7581
7682 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)
7985 }
8086 }
8187
@@ -93,7 +99,7 @@ public final class LocalTestingDistributedActorSystem: DistributedActorSystem, @
9399 where Act: DistributedActor ,
94100 Act. ID == ActorID ,
95101 Err: Error ,
96- Res: SerializationRequirement {
102+ Res: Codable {
97103 fatalError ( " Attempted to make remote call to \( target) on actor \( actor ) using a local-only actor system " )
98104 }
99105
@@ -109,38 +115,40 @@ public final class LocalTestingDistributedActorSystem: DistributedActorSystem, @
109115 fatalError ( " Attempted to make remote call to \( target) on actor \( actor ) using a local-only actor system " )
110116 }
111117
112- private struct ActorIDProvider {
118+ @usableFromInline
119+ final class ActorIDProvider {
113120 private var counter : Int = 0
114121 private let counterLock = _Lock ( )
115122
123+ @usableFromInline
116124 init ( ) { }
117125
118- mutating func next( ) -> LocalTestingActorAddress {
126+ func next( ) -> LocalTestingActorAddress {
119127 let id : Int = self . counterLock. withLock {
120128 self . counter += 1
121129 return self . counter
122130 }
123- return LocalTestingActorAddress ( parse : " \( id ) " )
131+ return LocalTestingActorAddress ( id )
124132 }
125133 }
126134}
127135
128136@available ( SwiftStdlib 5 . 7 , * )
129137public struct LocalTestingActorAddress : Hashable , Sendable , Codable {
130- public let address : String
138+ public let uuid : String
131139
132- public init ( parse address : String ) {
133- self . address = address
140+ public init ( _ uuid : Int ) {
141+ self . uuid = " \( uuid ) "
134142 }
135143
136144 public init ( from decoder: Decoder ) throws {
137145 let container = try decoder. singleValueContainer ( )
138- self . address = try container. decode ( String . self)
146+ self . uuid = try container. decode ( String . self)
139147 }
140148
141149 public func encode( to encoder: Encoder ) throws {
142150 var container = encoder. singleValueContainer ( )
143- try container. encode ( self . address )
151+ try container. encode ( self . uuid )
144152 }
145153}
146154
@@ -220,7 +228,7 @@ public struct LocalTestingDistributedActorSystemError: DistributedActorSystemErr
220228// === lock ----------------------------------------------------------------
221229
222230@available ( SwiftStdlib 5 . 7 , * )
223- fileprivate class _Lock {
231+ internal class _Lock {
224232 #if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
225233 private let underlying : UnsafeMutablePointer < os_unfair_lock >
226234 #elseif os(Windows)
@@ -233,10 +241,27 @@ fileprivate class _Lock {
233241 private let underlying : UnsafeMutablePointer < pthread_mutex_t >
234242 #endif
235243
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+
236261 deinit {
237262 #if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
238263 // `os_unfair_lock`s do not need to be explicitly destroyed
239- #elseif os(Windows)
264+ #elseif os(Windows)
240265 // `SRWLOCK`s do not need to be explicitly destroyed
241266 #elseif os(WASI)
242267 // WASI environment has only a single thread
@@ -252,22 +277,6 @@ fileprivate class _Lock {
252277 #endif
253278 }
254279
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-
271280 @discardableResult
272281 func withLock< T> ( _ body: ( ) -> T ) -> T {
273282 #if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
0 commit comments