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 {}