@@ -15,21 +15,151 @@ import _Concurrency
1515
1616// ==== Distributed Actor -----------------------------------------------------
1717
18+
19+
1820/// Common protocol to which all distributed actors conform implicitly.
1921///
20- /// It is not possible to conform to this protocol manually explicitly.
21- /// Only a 'distributed actor' declaration or protocol with 'DistributedActor'
22- /// requirement may conform to this protocol.
22+ /// The `DistributedActor` protocol generalizes over all distributed actor types.
23+ /// Distributed actor types implicitly conform to this protocol.
24+ ///
25+ /// It is not possible to conform to this protocol manually by any other type
26+ /// than a `distributed actor`.
27+ ///
28+ /// It is possible to require a type conform to the
29+ /// ``DistributedActor`` protocol by refining it with another protocol,
30+ /// or by using a generic constraint.
31+ ///
32+ ///
33+ /// ## The ActorSystem associated type
34+ /// Every distributed actor must declare what type of distributed actor system
35+ /// it is part of by implementing the ``ActorSystem`` associated type requirement.
36+ ///
37+ /// This causes a number of other properties of the actor to be inferred:
38+ /// - the ``SerializationRequirement`` that will be used at compile time to
39+ /// verify `distributed` target declarations are well formed,
40+ /// - if the distributed actor is `Codable`, based on the ``ID`` being Codable or not,
41+ /// - the type of the `ActorSystem` accepted in the synthesized default initializer.
42+ ///
43+ /// A distributed actor must declare what type of actor system it is ready to
44+ /// work with by fulfilling the ``ActorSystem`` type member requirement:
45+ ///
46+ /// ```swift
47+ /// distributed actor Greeter {
48+ /// typealias ActorSystem = GreetingSystem // which conforms to DistributedActorSystem
49+ ///
50+ /// func greet() -> String { "Hello!" }
51+ /// }
52+ /// ```
53+ ///
54+ /// ### The DefaultDistributedActorSystem type alias
55+ /// Since it is fairly common to only be using one specific type of actor system
56+ /// within a module or entire codebase, it is possible to declare the default type
57+ /// or actor system all distributed actors will be using in a module by declaring
58+ /// a `DefaultDistributedActorSystem` module wide typealias:
59+ ///
60+ /// ```swift
61+ /// import Distributed
62+ /// import AmazingActorSystemLibrary
63+ ///
64+ /// typealias DefaultDistributedActorSystem = AmazingActorSystem
65+ ///
66+ /// distributed actor Greeter {} // ActorSystem == AmazingActorSystem
67+ /// ```
68+ ///
69+ /// This declaration makes all `distributed actor` declarations,
70+ /// which do not explicitly specify an ``ActorSystem`` typealias, to assume the
71+ /// `AmazingActorSystem` as their `ActorSystem`.
72+ ///
73+ /// It is possible for a specific actor to override the system it is using,
74+ /// by declaring an ``ActorSystem`` type alias as usual:
75+ ///
76+ /// ```swift
77+ /// typealias DefaultDistributedActorSystem = AmazingActorSystem
78+ ///
79+ /// distributed actor Amazing {
80+ /// // ActorSystem == AmazingActorSystem
81+ /// }
82+ ///
83+ /// distributed actor Superb {
84+ /// typealias ActorSystem = SuperbActorSystem
85+ /// }
86+ /// ```
2387///
24- /// The 'DistributedActor' protocol provides the core functionality of any
25- /// distributed actor .
88+ /// In general the `DefaultDistributedActorSystem` should not be declared public,
89+ /// as picking the default should be left up to each specific module of a project .
2690///
27- /// ## Implicit `Codable` conformance
91+ /// ## Default initializer
92+ /// While classes and actors receive a synthesized *argument-free default
93+ /// initializer* (`init()`), distributed actors synthesize a default initializer
94+ /// that accepts a distributed actor system the actor is part of: `init(actorSystem:)`.
95+ ///
96+ /// The accepted actor system must be of the `Self.ActorSystem` type, which
97+ /// must conform to the ``DistributedActorSystem`` protocol. This is required
98+ /// because of how distributed actors are always managed by, a concrete
99+ /// distributed actor system, and cannot exist on their own without one.
100+ ///
101+ /// It is possible to explicitly declare an parameter-free initializer (`init()`),
102+ /// however the `actorSystem` property still must be assigned a concrete actor
103+ /// system instance the actor shall be part of.
104+
105+ /// In general it is recommended to always have an `actorSystem` parameter as
106+ /// the last non-defaulted non-closure parameter in every distributed actors
107+ /// initializer parameter list. This way it is simple to swap in a "test actor
108+ // system" instance in unit tests, and avoid relying on global state which could
109+ /// make testing more difficult.
110+ ///
111+ /// ## Implicit properties
112+ /// Every concrete `distributed actor` type receives two synthesized properties,
113+ /// which implement the protocol requirements of this protocol: `id` and `actorSystem`.
114+ ///
115+ /// ### Property: Actor System
116+ /// The ``actorSystem`` property is an important part of every distributed actor's lifecycle management.
117+ /// Initialization as well as de-initialization both require interactions with the actor system,
118+ /// and it is the actor system that delivers
119+ ///
120+ ///
121+ /// The ``actorSystem`` property must be assigned in every designated initializer
122+ /// of a distributed actor explicitly. It is highly recommended to make it a
123+ /// parameter of every distributed actor initializer, and simply forward the
124+ /// value to the stored property, like this:
125+ ///
126+ /// ```swift
127+ /// init(name: String, actorSystem: Self.ActorSystem) {
128+ /// self.name = name
129+ /// self.actorSystem = actorSystem
130+ /// }
131+ /// ```
132+ ///
133+ /// ### Property: Distributed Actor Identity
134+ /// The ``id`` is assigned by the actor system during the distributed actor's
135+ /// initialization, and cannot be set or mutated by the actor itself.
136+ ///
137+ /// The ``id`` is the effective identity of the actor, and is used in equality checks.
138+ ///
139+ /// ## Automatic Conformances
140+ ///
141+ /// ### Hashable and Identifiable conformance
142+ /// Every distributed actor conforms to the Hashable and Identifiable protocols.
143+ /// Its identity is strictly driven by its `id`, and therefore hash and equality
144+ /// implementations directly delegate to the `id` property.
145+ ///
146+ /// Comparing a local distributed actor instance and a remote reference to it
147+ /// (both using the same ``id``) always returns true, as they both conceptually
148+ /// point at the same distributed actor.
149+ ///
150+ /// It is not possible to implement those protocols relying on the actual actor's
151+ /// state, because it may be remote and the state may not be available. In other
152+ /// words, since these protocols must be implemented using `nonisolated` functions,
153+ /// only `nonisolated` `id` and `actorSystem` properties are accessible for their
154+ /// implementations.
155+ ///
156+ /// ### Implicit `Codable` conformance
28157/// If created with an actor system whose `ActorID` is `Codable`, the
29158/// compiler will synthesize code for the concrete distributed actor to conform
30- /// to `Codable` as well. This is necessary to support distributed calls where
31- /// the `SerializationRequirement` is `Codable` and thus users may want to pass
32- /// actors as arguments to remote calls.
159+ /// to `Codable` as well.
160+ ///
161+ /// This is necessary to support distributed calls where the `SerializationRequirement`
162+ /// is `Codable` and thus users may want to pass actors as arguments to remote calls.
33163///
34164/// The synthesized implementations use a single `SingleValueContainer` to
35165/// encode/decode the `self.id` property of the actor. The `Decoder` required
@@ -40,6 +170,10 @@ import _Concurrency
40170///
41171/// Use the `CodingUserInfoKey.actorSystemKey` to provide the necessary
42172/// actor system for the decoding initializer when decoding a distributed actor.
173+ ///
174+ /// - SeeAlso: ``DistributedActorSystem``
175+ /// - SeeAlso: ``Actor``
176+ /// - SeeAlso: ``AnyActor``
43177@available ( SwiftStdlib 5 . 7 , * )
44178public protocol DistributedActor : AnyActor , Identifiable , Hashable
45179 where ID == ActorSystem . ActorID ,
@@ -102,6 +236,13 @@ extension DistributedActor {
102236// ==== Codable conformance ----------------------------------------------------
103237
104238extension CodingUserInfoKey {
239+
240+ /// Key which is required to be set on a `Decoder`'s `userInfo` while attempting
241+ /// to `init(from:)` a `DistributedActor`. The stored value under this key must
242+ /// conform to ``DistributedActorSystem``.
243+ ///
244+ /// Missing to set this key will result in that initializer throwing, because
245+ /// an actor system is required
105246 @available ( SwiftStdlib 5 . 7 , * )
106247 public static let actorSystemKey = CodingUserInfoKey ( rawValue: " $distributed_actor_system " ) !
107248}
0 commit comments