1111//===----------------------------------------------------------------------===//
1212
1313import Swift
14- import _Concurrency
1514
16- /// Common protocol to which all distributed actors conform implicitly.
17- ///
18- /// It is not possible to conform to this protocol manually explicitly.
19- /// Only a 'distributed actor' declaration or protocol with 'DistributedActor'
20- /// requirement may conform to this protocol.
21- ///
22- /// The 'DistributedActor' protocol provides the core functionality of any
23- /// distributed actor, which involves transforming actor
24- /// which involves enqueuing new partial tasks to be executed at some
25- /// point.
26- @available ( SwiftStdlib 5 . 5 , * )
27- public protocol DistributedActor : Actor , Codable {
28-
29- /// Creates new (local) distributed actor instance, bound to the passed transport.
30- ///
31- /// Upon initialization, the `actorAddress` field is populated by the transport,
32- /// with an address assigned to this actor.
33- ///
34- /// - Parameter transport: the transport this distributed actor instance will
35- /// associated with.
36- init ( transport: ActorTransport )
37-
38- /// Resolves the passed in `address` against the `transport`,
39- /// returning either a local or remote actor reference.
40- ///
41- /// The transport will be asked to `resolve` the address and return either
42- /// a local instance or determine that a proxy instance should be created
43- /// for this address. A proxy actor will forward all invocations through
44- /// the transport, allowing it to take over the remote messaging with the
45- /// remote actor instance.
46- ///
47- /// - Parameter address: the address to resolve, and produce an instance or proxy for.
48- /// - Parameter transport: transport which should be used to resolve the `address`.
49- init ( resolve address: ActorAddress , using transport: ActorTransport ) throws
50-
51- /// The `ActorTransport` associated with this actor.
52- /// It is immutable and equal to the transport passed in the local/resolve
53- /// initializer.
54- ///
55- /// Conformance to this requirement is synthesized automatically for any
56- /// `distributed actor` declaration.
57- nonisolated var actorTransport : ActorTransport { get }
58-
59- /// Logical address which this distributed actor represents.
60- ///
61- /// An address is always uniquely pointing at a specific actor instance.
62- ///
63- /// Conformance to this requirement is synthesized automatically for any
64- /// `distributed actor` declaration.
65- nonisolated var actorAddress : ActorAddress { get }
66- }
67-
68- // ==== Codable conformance ----------------------------------------------------
69-
70- extension CodingUserInfoKey {
71- @available ( SwiftStdlib 5 . 5 , * )
72- static let actorTransportKey = CodingUserInfoKey ( rawValue: " $dist_act_trans " ) !
73- }
74-
75- @available ( SwiftStdlib 5 . 5 , * )
76- extension DistributedActor {
77- nonisolated public init ( from decoder: Decoder ) throws {
78- // guard let transport = decoder.userInfo[.actorTransportKey] as? ActorTransport else {
79- // throw DistributedActorCodingError(message:
80- // "ActorTransport not available under the decoder.userInfo")
81- // }
82- //
83- // var container = try decoder.singleValueContainer()
84- // let address = try container.decode(ActorAddress.self)
85- // self = try Self(resolve: address, using: transport) // FIXME: This is going to be solved by the init() work!!!!
86- fatalError ( " \( #function) is not implemented yet for distributed actors' " )
87- }
88-
89- nonisolated public func encode( to encoder: Encoder ) throws {
90- var container = encoder. singleValueContainer ( )
91- try container. encode ( self . actorAddress)
92- }
93- }
94- /******************************************************************************/
95- /***************************** Actor Transport ********************************/
96- /******************************************************************************/
97-
98- @available ( SwiftStdlib 5 . 5 , * )
99- public protocol ActorTransport : Sendable {
100- /// Resolve a local or remote actor address to a real actor instance, or throw if unable to.
101- /// The returned value is either a local actor or proxy to a remote actor.
102- func resolve< Act> ( address: ActorAddress , as actorType: Act . Type )
103- throws -> ActorResolved < Act > where Act: DistributedActor
104-
105- /// Create an `ActorAddress` for the passed actor type.
106- ///
107- /// This function is invoked by an distributed actor during its initialization,
108- /// and the returned address value is stored along with it for the time of its
109- /// lifetime.
110- ///
111- /// The address MUST uniquely identify the actor, and allow resolving it.
112- /// E.g. if an actor is created under address `addr1` then immediately invoking
113- /// `transport.resolve(address: addr1, as: Greeter.self)` MUST return a reference
114- /// to the same actor.
115- func assignAddress< Act> (
116- _ actorType: Act . Type
117- ) -> ActorAddress
118- where Act: DistributedActor
119-
120- func actorReady< Act> (
121- _ actor : Act
122- ) where Act: DistributedActor
123-
124- /// Called during actor deinit/destroy.
125- func resignAddress(
126- _ address: ActorAddress
127- )
128-
129- }
130-
131- @available ( SwiftStdlib 5 . 5 , * )
132- public enum ActorResolved < Act: DistributedActor > {
133- case resolved( Act )
134- case makeProxy
135- }
136-
137- /******************************************************************************/
138- /***************************** Actor Address **********************************/
139- /******************************************************************************/
140-
141- /// Uniquely identifies a distributed actor, and enables sending messages even to remote actors.
142- ///
143- /// ## Identity
144- /// The address is the source of truth with regards to referring to a _specific_ actor in the system.
145- /// This is in contrast to an `ActorPath` which can be thought of as paths in a filesystem, however without any uniqueness
146- /// or identity guarantees about the files those paths point to.
147- ///
148- /// ## Lifecycle
149- /// Note, that an ActorAddress is a pure value, and as such does not "participate" in an actors lifecycle;
150- /// Thus, it may represent an address of an actor that has already terminated, so attempts to locate (resolve)
151- /// an `ActorRef` for this address may result with a reference to dead letters (meaning, that the actor this address
152- /// had pointed to does not exist, and most likely is dead / terminated).
153- ///
154- /// ## Serialization
155- ///
156- /// An address can be serialized using `Codable` or other serialization mechanisms.
157- /// When shared over the network or with other processes it must include the origin's
158- /// system address (e.g. the network address of the host, or process identifier).
159- ///
160- /// When using `Codable` serialization this is done automatically, by looking up
161- /// the address of the `ActorTransport` the actor is associated with if was a local
162- /// instance, or simply carrying the full address if it already was a remote reference.
163- ///
164- /// ## Format
165- /// The address consists of the following parts:
166- ///
167- /// ```
168- /// | node | path | incarnation |
169- /// ( protocol | name? | host | port ) ( [segments] name )? ( uint32 )
170- /// ```
171- ///
172- /// For example: `sact://human-readable-name@127.0.0.1:7337/user/wallet/id-121242`.
173- /// Note that the `ActorIncarnation` is not printed by default in the String representation of a path, yet may be inspected on demand.
174- @available ( SwiftStdlib 5 . 5 , * )
175- public struct ActorAddress : Codable , Sendable , Equatable , Hashable {
176- /// Uniquely specifies the actor transport and the protocol used by it.
177- ///
178- /// E.g. "xpc", "specific-clustering-protocol" etc.
179- public var `protocol` : String
180-
181- public var host : String ?
182- public var port : Int ?
183- public var nodeID : UInt64 ?
184- public var path : String ?
185-
186- /// Unique Identifier of this actor.
187- public var uid : UInt64 // TODO: should we remove this
188-
189- // FIXME: remove this or implement for real; this is just a hack implementation for now
190- public init ( parse: String ) {
191- self . protocol = " sact "
192- self . host = " xxx "
193- self . port = 7337
194- self . nodeID = 11
195- self . path = " example "
196- self . uid = 123123
197- }
198- }
199-
200- // TODO: naive impl, bring in a real one
201- @available ( SwiftStdlib 5 . 5 , * )
202- extension ActorAddress : CustomStringConvertible {
203- public var description : String {
204- var result = `protocol`
205- result += " :// "
206- if let host = host {
207- result += host
208- }
209- if let port = port {
210- result += " : \( port) "
211- }
212- // TODO: decide if we'd want to print the nodeID too here.
213- if let path = path {
214- result += " / \( path) "
215- }
216- if uid > 0 {
217- result += " # \( uid) "
218- }
219- return result
220- }
221- }
222-
223- /******************************************************************************/
224- /******************************** Misc ****************************************/
225- /******************************************************************************/
226-
227- /// Error protocol to which errors thrown by any `ActorTransport` should conform.
228- @available ( SwiftStdlib 5 . 5 , * )
229- public protocol ActorTransportError : Error { }
230-
231- @available ( SwiftStdlib 5 . 5 , * )
232- public struct DistributedActorCodingError : ActorTransportError {
233- public let message : String
234-
235- public init ( message: String ) {
236- self . message = message
237- }
238-
239- public static func missingTransportUserInfo< Act> ( _ actorType: Act . Type ) -> Self
240- where Act: DistributedActor {
241- . init( message: " Missing ActorTransport userInfo while decoding " )
242- }
243- }
244-
245- /******************************************************************************/
246- /************************* Runtime Functions **********************************/
247- /******************************************************************************/
248-
249- // ==== isRemote / isLocal -----------------------------------------------------
250-
251- @_silgen_name ( " swift_distributed_actor_is_remote " )
252- func __isRemoteActor( _ actor : AnyObject ) -> Bool
253-
254- func __isLocalActor( _ actor : AnyObject ) -> Bool {
255- return !__isRemoteActor( actor )
256- }
257-
258- // ==== Proxy Actor lifecycle --------------------------------------------------
259-
260- /// Called to initialize the distributed-remote actor 'proxy' instance in an actor.
261- /// The implementation will call this within the actor's initializer.
262- @_silgen_name ( " swift_distributedActor_remote_initialize " )
263- func _distributedActorRemoteInitialize( _ actor : AnyObject )
264-
265- /// Called to destroy the default actor instance in an actor.
266- /// The implementation will call this within the actor's deinit.
267- ///
268- /// This will call `actorTransport.resignAddress(self.actorAddress)`.
269- @_silgen_name( " swift_distributedActor_destroy" )
270- func _distributedActorDestroy( _ actor : AnyObject )
15+ /// Report a call to a _remote function on a distributed (remote) actor,
16+ /// that was not dynamically replaced by some specific ActorTransport library.
17+ @_transparent
18+ public func _missingDistributedActorTransport(
19+ className: StaticString , functionName: StaticString ,
20+ file: StaticString , line: UInt , column: UInt
21+ ) -> Never {
22+ // This function is marked @_transparent so that it is inlined into the caller
23+ // (the remote function stub), and, depending on the build configuration,
24+ // redundant parameter values (#file etc.) are eliminated, and don't leak
25+ // information about the user's source.
26+ fatalError (
27+ """
28+ Invoked remote placeholder function ' \( functionName) ' on remote \
29+ distributed actor of type ' \( className) '. Configure an appropriate \
30+ 'ActorTransport' for this actor to resolve this error (e.g. by depending \
31+ on some specific transport library).
32+ """ , file: file, line: line)
33+ }
0 commit comments