actors_rs/actor/props.rs
1use std::{
2 fmt,
3 panic::{RefUnwindSafe, UnwindSafe},
4 sync::{Arc, Mutex},
5};
6
7use crate::actor::Actor;
8
9/// Provides instances of `ActorProducer` for use when creating Actors (`actor_of`).
10///
11/// Actors are not created directly. Instead you provide an `ActorProducer`
12/// that allows the `ActorSystem` to start an actor when `actor_of` is used,
13/// or when an actor fails and a supervisor requests an actor to be restarted.
14///
15/// `ActorProducer` can hold values required by the actor's factory method
16/// parameters.
17pub struct Props;
18
19impl Props {
20 /// Creates an `ActorProducer` with no factory method parameters.
21 ///
22 /// # Examples
23 ///
24 /// ```
25 /// # use actors_rs::*;
26 ///
27 /// #[derive(Default)]
28 /// struct User;
29 ///
30 /// # impl Actor for User {
31 /// # type Msg = String;
32 /// # fn recv(&mut self, _ctx: &Context<String>, _msg: String, _sender: Sender) {}
33 /// # }
34 /// // main
35 /// let sys = ActorSystem::new().unwrap();
36 ///
37 /// // start the actor and get an `ActorRef`
38 /// let actor = sys.actor_of::<User>("user").unwrap();
39 /// ```
40 pub fn new_no_args<A, F>(creator: F) -> Arc<Mutex<impl ActorProducer<Actor = A>>>
41 where
42 A: Actor + Send + 'static,
43 F: Fn() -> A + Send + 'static,
44 {
45 Arc::new(Mutex::new(ActorProps::new_producer(creator)))
46 }
47
48 /// Creates an `ActorProducer` with one or more factory method parameters.
49 ///
50 /// # Examples
51 /// An actor requiring a single parameter.
52 /// ```
53 /// # use actors_rs::*;
54 ///
55 /// struct User {
56 /// name: String,
57 /// }
58 ///
59 /// impl ActorFactoryArgs<String> for User {
60 /// fn create_args(name: String) -> Self {
61 /// User { name }
62 /// }
63 /// }
64 ///
65 /// # impl Actor for User {
66 /// # type Msg = String;
67 /// # fn recv(&mut self, _ctx: &Context<String>, _msg: String, _sender: Sender) {}
68 /// # }
69 /// // main
70 /// let sys = ActorSystem::new().unwrap();
71 ///
72 /// let actor = sys.actor_of_args::<User, _>("user", "Naomi Nagata".into()).unwrap();
73 /// ```
74 /// An actor requiring multiple parameters.
75 /// ```
76 /// # use actors_rs::*;
77 ///
78 /// struct BankAccount {
79 /// name: String,
80 /// number: String,
81 /// }
82 ///
83 /// impl ActorFactoryArgs<(String, String)> for BankAccount {
84 /// fn create_args((name, number): (String, String)) -> Self {
85 /// BankAccount { name, number }
86 /// }
87 /// }
88 ///
89 /// # impl Actor for BankAccount {
90 /// # type Msg = String;
91 /// # fn recv(&mut self, _ctx: &Context<String>, _msg: String, _sender: Sender) {}
92 /// # }
93 /// // main
94 /// let sys = ActorSystem::new().unwrap();
95 ///
96 /// // start the actor and get an `ActorRef`
97 /// let actor = sys.actor_of_args::<BankAccount, _>("bank_account", ("James Holden".into(), "12345678".into())).unwrap();
98 /// ```
99 pub fn new_args<A, Args, F>(creator: F, args: Args) -> Arc<Mutex<impl ActorProducer<Actor = A>>>
100 where
101 A: Actor + Send + 'static,
102 Args: ActorArgs,
103 F: Fn(Args) -> A + Send + 'static,
104 {
105 Arc::new(Mutex::new(ActorPropsWithArgs::new_producer(creator, args)))
106 }
107}
108
109/// A `Clone`, `Send` and `Sync` `ActorProducer`
110// pub type BoxActorProd<Msg> = Arc<Mutex<ActorProducer<Actor=BoxActor<Msg>>>>;
111pub type BoxActorProd<A> = Arc<Mutex<dyn ActorProducer<Actor = A>>>;
112
113pub trait ActorFactory: Actor {
114 fn create() -> Self;
115}
116
117pub trait ActorFactoryArgs<Args: ActorArgs>: Actor {
118 fn create_args(args: Args) -> Self;
119}
120
121impl<A: Default + Actor> ActorFactory for A {
122 fn create() -> Self {
123 Self::default()
124 }
125}
126
127/// Represents the underlying Actor factory function for creating instances of `Actor`.
128///
129/// Actors are not created directly. Instead you provide an `ActorProducer`
130/// that allows the `ActorSystem` to start an actor when `actor_of` is used,
131/// or when an actor fails and a supervisor requests an actor to be restarted.
132///
133/// `ActorProducer` can hold values required by the actor's factory method
134/// parameters.
135pub trait ActorProducer: fmt::Debug + Send + UnwindSafe + RefUnwindSafe {
136 type Actor: Actor;
137
138 /// Produces an instance of an `Actor`.
139 ///
140 /// The underlying factory method provided
141 /// in the original `Props::new(f: Fn() -> A + Send`) or
142 /// `Props::new(f: Fn(Args) -> A + Send>, args: Args)` is called.
143 ///
144 /// Any parameters `Args` will be cloned and passed to the function.
145 ///
146 /// # Panics
147 /// If the provided factory method panics the panic will be caught
148 /// by the system, resulting in an error result returning to `actor_of`.
149 fn produce(&self) -> Self::Actor;
150}
151
152impl<A> ActorProducer for Arc<Mutex<Box<dyn ActorProducer<Actor = A>>>>
153where
154 A: Actor + Send + 'static,
155{
156 type Actor = A;
157
158 fn produce(&self) -> A {
159 self.lock().unwrap().produce()
160 }
161}
162
163impl<A> ActorProducer for Arc<Mutex<dyn ActorProducer<Actor = A>>>
164where
165 A: Actor + Send + 'static,
166{
167 type Actor = A;
168
169 fn produce(&self) -> A {
170 self.lock().unwrap().produce()
171 }
172}
173
174impl<A> ActorProducer for Box<dyn ActorProducer<Actor = A>>
175where
176 A: Actor + Send + 'static,
177{
178 type Actor = A;
179
180 fn produce(&self) -> A {
181 (**self).produce()
182 }
183}
184
185pub struct ActorProps<A: Actor> {
186 creator: Box<dyn Fn() -> A + Send>,
187}
188
189impl<A: Actor> UnwindSafe for ActorProps<A> {}
190impl<A: Actor> RefUnwindSafe for ActorProps<A> {}
191
192impl<A> ActorProps<A>
193where
194 A: Actor + Send + 'static,
195{
196 pub fn new_producer<F>(creator: F) -> impl ActorProducer<Actor = A>
197 where
198 F: Fn() -> A + Send + 'static,
199 {
200 Self {
201 creator: Box::new(creator),
202 }
203 }
204}
205
206impl<A> ActorProducer for ActorProps<A>
207where
208 A: Actor + Send + 'static,
209{
210 type Actor = A;
211
212 fn produce(&self) -> A {
213 let f = &self.creator;
214 f()
215 }
216}
217
218impl<A: Actor> fmt::Display for ActorProps<A> {
219 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
220 write!(f, "Props")
221 }
222}
223
224impl<A: Actor> fmt::Debug for ActorProps<A> {
225 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
226 write!(f, "Props")
227 }
228}
229
230pub struct ActorPropsWithArgs<A: Actor, Args: ActorArgs> {
231 creator: Box<dyn Fn(Args) -> A + Send>,
232 args: Args,
233}
234
235impl<A: Actor, Args: ActorArgs> UnwindSafe for ActorPropsWithArgs<A, Args> {}
236impl<A: Actor, Args: ActorArgs> RefUnwindSafe for ActorPropsWithArgs<A, Args> {}
237
238impl<A, Args> ActorPropsWithArgs<A, Args>
239where
240 A: Actor + Send + 'static,
241 Args: ActorArgs,
242{
243 pub fn new_producer<F>(creator: F, args: Args) -> impl ActorProducer<Actor = A>
244 where
245 F: Fn(Args) -> A + Send + 'static,
246 {
247 Self {
248 creator: Box::new(creator),
249 args,
250 }
251 }
252}
253
254impl<A, Args> ActorProducer for ActorPropsWithArgs<A, Args>
255where
256 A: Actor + Send + 'static,
257 Args: ActorArgs,
258{
259 type Actor = A;
260
261 fn produce(&self) -> A {
262 let f = &self.creator;
263 let args = self.args.clone();
264 f(args)
265 }
266}
267
268impl<A: Actor, Args: ActorArgs> fmt::Display for ActorPropsWithArgs<A, Args> {
269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270 write!(f, "Props")
271 }
272}
273
274impl<A: Actor, Args: ActorArgs> fmt::Debug for ActorPropsWithArgs<A, Args> {
275 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
276 write!(f, "Props")
277 }
278}
279
280pub trait ActorArgs: Clone + Send + Sync + 'static {}
281impl<T: Clone + Send + Sync + 'static> ActorArgs for T {}