@@ -16,11 +16,14 @@ import _Concurrency
16
16
public protocol DistributedActorSystem : Sendable {
17
17
/// The identity used by actors that communicate via this transport
18
18
associatedtype ActorID : Sendable & Hashable & Codable // TODO: make Codable conditional here
19
- /// The specific type of the argument builder to be used for remote calls.
20
- associatedtype Invocation : DistributedTargetInvocation
19
+
20
+ associatedtype InvocationEncoder : DistributedTargetInvocationEncoder
21
+ associatedtype InvocationDecoder : DistributedTargetInvocationDecoder
21
22
22
23
/// The serialization requirement that will be applied to all distributed targets used with this system.
23
- typealias SerializationRequirement = Invocation . SerializationRequirement
24
+ associatedtype SerializationRequirement
25
+ where SerializationRequirement == InvocationEncoder . SerializationRequirement ,
26
+ SerializationRequirement == InvocationDecoder . SerializationRequirement
24
27
25
28
// ==== ---------------------------------------------------------------------
26
29
// - MARK: Resolving actors by identity
@@ -104,12 +107,12 @@ public protocol DistributedActorSystem: Sendable {
104
107
/// arguments, generic substitutions, and specific error and return types
105
108
/// that are associated with this specific invocation.
106
109
@inlinable
107
- func makeInvocation ( ) throws -> Invocation
110
+ func makeInvocationEncoder ( ) throws -> InvocationEncoder
108
111
109
112
/// Invoked by the Swift runtime when making a remote call.
110
113
///
111
114
/// The `arguments` are the arguments container that was previously created
112
- /// by `makeInvocation ` and has been populated with all arguments.
115
+ /// by `makeInvocationEncoder ` and has been populated with all arguments.
113
116
///
114
117
/// This method should perform the actual remote function call, and await for its response.
115
118
///
@@ -119,7 +122,7 @@ public protocol DistributedActorSystem: Sendable {
119
122
// func remoteCall<Act, Err, Res>(
120
123
// on actor: Act,
121
124
// target: RemoteCallTarget,
122
- // invocation: inout Invocation ,
125
+ // invocation: inout InvocationDecoder ,
123
126
// throwing: Err.Type,
124
127
// returning: Res.Type
125
128
// ) async throws -> Res
@@ -149,7 +152,7 @@ extension DistributedActorSystem {
149
152
public func executeDistributedTarget< Act, ResultHandler> (
150
153
on actor : Act ,
151
154
mangledTargetName: String ,
152
- invocation : inout Invocation ,
155
+ invocationDecoder : inout InvocationDecoder ,
153
156
handler: ResultHandler
154
157
) async throws where Act: DistributedActor ,
155
158
Act. ID == ActorID ,
@@ -245,41 +248,43 @@ extension DistributedActorSystem {
245
248
do {
246
249
// Decode the invocation and pack arguments into the h-buffer
247
250
// TODO(distributed): decode the generics info
248
- var argumentDecoder = invocation. makeArgumentDecoder ( )
249
- var paramIdx = 0
250
- for unsafeRawArgPointer in hargs {
251
- guard paramIdx < paramCount else {
252
- throw ExecuteDistributedTargetError (
253
- message: " Unexpected attempt to decode more parameters than expected: \( paramIdx + 1 ) " )
251
+ // TODO(distributed): move this into the IRGen synthesized funcs, so we don't need hargs at all and can specialize the decodeNextArgument calls
252
+ do {
253
+ var paramIdx = 0
254
+ for unsafeRawArgPointer in hargs {
255
+ guard paramIdx < paramCount else {
256
+ throw ExecuteDistributedTargetError (
257
+ message: " Unexpected attempt to decode more parameters than expected: \( paramIdx + 1 ) " )
258
+ }
259
+ let paramType = paramTypes [ paramIdx]
260
+ paramIdx += 1
261
+
262
+ // FIXME(distributed): func doDecode<Arg: SerializationRequirement>(_: Arg.Type) throws {
263
+ // FIXME: but how would we call this...?
264
+ // FIXME: > type 'Arg' constrained to non-protocol, non-class type 'Self.Invocation.SerializationRequirement'
265
+ func doDecodeArgument< Arg> ( _: Arg . Type ) throws {
266
+ let unsafeArgPointer = unsafeRawArgPointer
267
+ . bindMemory ( to: Arg . self, capacity: 1 )
268
+ try invocationDecoder. decodeNextArgument ( Arg . self, into: unsafeArgPointer)
269
+ }
270
+ try _openExistential ( paramType, do: doDecodeArgument)
254
271
}
255
- let paramType = paramTypes [ paramIdx]
256
- paramIdx += 1
257
-
258
- // FIXME(distributed): func doDecode<Arg: SerializationRequirement>(_: Arg.Type) throws {
259
- // FIXME: but how would we call this...?
260
- // FIXME: > type 'Arg' constrained to non-protocol, non-class type 'Self.Invocation.SerializationRequirement'
261
- func doDecodeArgument< Arg> ( _: Arg . Type ) throws {
262
- let unsafeArgPointer = unsafeRawArgPointer
263
- . bindMemory ( to: Arg . self, capacity: 1 )
264
- try argumentDecoder. decodeNext ( Arg . self, into: unsafeArgPointer)
265
- }
266
- try _openExistential ( paramType, do: doDecodeArgument)
267
272
}
268
273
269
- let returnType = try invocation . decodeReturnType ( ) ?? returnTypeFromTypeInfo
274
+ let returnType = try invocationDecoder . decodeReturnType ( ) ?? returnTypeFromTypeInfo
270
275
// let errorType = try invocation.decodeErrorType() // TODO: decide how to use?
276
+
271
277
// Execute the target!
272
278
try await _executeDistributedTarget (
273
279
on: actor ,
274
280
mangledTargetName, UInt ( mangledTargetName. count) ,
275
- argumentBuffer: hargs. buffer. _rawValue,
281
+ argumentBuffer: hargs. buffer. _rawValue, // TODO(distributed): pass the invocationDecoder instead, so we can decode inside IRGen directly into the argument explosion
276
282
resultBuffer: resultBuffer. _rawValue
277
283
)
278
284
279
285
func onReturn< R> ( _ resultTy: R . Type ) async throws {
280
286
try await handler. onReturn /*<R>*/( value: resultBuffer. load ( as: resultTy) )
281
287
}
282
-
283
288
try await _openExistential ( returnType, do: onReturn)
284
289
} catch {
285
290
try await handler. onThrow ( error: error)
@@ -314,7 +319,7 @@ public struct RemoteCallTarget {
314
319
}
315
320
}
316
321
317
- /// Represents an invocation of a distributed target (method or computed property).
322
+ /// Used to encode an invocation of a distributed target (method or computed property).
318
323
///
319
324
/// ## Forming an invocation
320
325
///
@@ -345,46 +350,35 @@ public struct RemoteCallTarget {
345
350
/// Note that the decoding will be provided the specific types that the sending side used to preform the call,
346
351
/// so decoding can rely on simply invoking e.g. `Codable` (if that is the `SerializationRequirement`) decoding
347
352
/// entry points on the provided types.
348
- @available ( SwiftStdlib 5 . 6 , * )
349
- public protocol DistributedTargetInvocation {
350
- associatedtype ArgumentDecoder : DistributedTargetInvocationArgumentDecoder
353
+ public protocol DistributedTargetInvocationEncoder {
351
354
associatedtype SerializationRequirement
352
355
353
- // === Sending / recording -------------------------------------------------
354
356
/// The arguments must be encoded order-preserving, and once `decodeGenericSubstitutions`
355
357
/// is called, the substitutions must be returned in the same order in which they were recorded.
356
358
mutating func recordGenericSubstitution< T> ( _ type: T . Type ) throws
357
359
358
360
// /// Ad-hoc requirement
359
361
// ///
360
362
// /// Record an argument of `Argument` type in this arguments storage.
361
- // mutating func recordArgument<Argument: SerializationRequirement>(argument: Argument) throws
363
+ // mutating func recordArgument<Argument: SerializationRequirement>(_ argument: Argument) throws
364
+
362
365
mutating func recordErrorType< E: Error > ( _ type: E . Type ) throws
363
366
364
367
// /// Ad-hoc requirement
365
368
// ///
366
369
// /// Record the return type of the distributed method.
367
370
// mutating func recordReturnType<R: SerializationRequirement>(_ type: R.Type) throws
368
- mutating func doneRecording( ) throws
369
371
370
- // === Receiving / decoding -------------------------------------------------
371
- mutating func decodeGenericSubstitutions( ) throws -> [ Any . Type ]
372
-
373
- func makeArgumentDecoder( ) -> Self . ArgumentDecoder
374
-
375
- mutating func decodeReturnType( ) throws -> Any . Type ?
376
-
377
- mutating func decodeErrorType( ) throws -> Any . Type ?
372
+ mutating func doneRecording( ) throws
378
373
}
379
374
380
- /// Decoding iterator produced by `DistributedTargetInvocation.argumentDecoder()`.
381
- ///
382
- /// It will be called exactly `N` times where `N` is the known number of arguments
383
- /// to the target invocation.
384
- @available ( SwiftStdlib 5 . 6 , * )
385
- public protocol DistributedTargetInvocationArgumentDecoder {
375
+ /// Decoder that must be provided to `executeDistributedTarget` and is used
376
+ /// by the Swift runtime to decode arguments of the invocation.
377
+ public protocol DistributedTargetInvocationDecoder {
386
378
associatedtype SerializationRequirement
387
379
380
+ func decodeGenericSubstitutions( ) throws -> [ Any . Type ]
381
+
388
382
// /// Ad-hoc protocol requirement
389
383
// ///
390
384
// /// Attempt to decode the next argument from the underlying buffers into pre-allocated storage
@@ -398,14 +392,27 @@ public protocol DistributedTargetInvocationArgumentDecoder {
398
392
// /// buffer for all the arguments and their expected types. The 'pointer' passed here is a pointer
399
393
// /// to a "slot" in that pre-allocated buffer. That buffer will then be passed to a thunk that
400
394
// /// performs the actual distributed (local) instance method invocation.
401
- // mutating func decodeNext <Argument: SerializationRequirement>(
395
+ // mutating func decodeNextArgument <Argument: SerializationRequirement>(
402
396
// into pointer: UnsafeMutablePointer<Argument> // pointer to our hbuffer
403
397
// ) throws
404
398
// FIXME(distributed): remove this since it must have the ': SerializationRequirement'
405
- mutating func decodeNext < Argument> (
399
+ mutating func decodeNextArgument < Argument> (
406
400
_ argumentType: Argument . Type ,
407
401
into pointer: UnsafeMutablePointer < Argument > // pointer to our hbuffer
408
402
) throws
403
+
404
+ func decodeErrorType( ) throws -> Any . Type ?
405
+
406
+ func decodeReturnType( ) throws -> Any . Type ?
407
+ }
408
+
409
+ ///
410
+ /// It will be called exactly `N` times where `N` is the known number of arguments
411
+ /// to the target invocation.
412
+ @available ( SwiftStdlib 5 . 6 , * )
413
+ public protocol DistributedTargetInvocationArgumentDecoder {
414
+
415
+
409
416
}
410
417
411
418
@available ( SwiftStdlib 5 . 6 , * )
@@ -427,8 +434,9 @@ public protocol DistributedActorSystemError: Error {}
427
434
428
435
@available ( SwiftStdlib 5 . 6 , * )
429
436
public struct ExecuteDistributedTargetError : DistributedActorSystemError {
430
- private let message : String
431
- internal init ( message: String ) {
437
+ let message : String
438
+
439
+ public init ( message: String ) {
432
440
self . message = message
433
441
}
434
442
}
0 commit comments