11
11
//===----------------------------------------------------------------------===//
12
12
13
13
import Swift
14
- import _Concurrency
15
14
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://
[email protected] :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