actors_rs/actor/
actor_ref.rs

1use std::fmt;
2
3use crate::{
4    actor::{
5        actor_cell::{ActorCell, ExtendedCell},
6        props::{ActorArgs, ActorFactory, ActorFactoryArgs},
7        Actor, ActorPath, ActorUri, BoxActorProd, CreateError,
8    },
9    system::{ActorSystem, SystemMsg},
10    AnyMessage, Envelope, Message,
11};
12
13pub trait ActorReference {
14    /// Actor name.
15    ///
16    /// Unique among siblings.
17    fn name(&self) -> &str;
18
19    /// Actor URI.
20    ///
21    /// Returns the URI for this actor.
22    fn uri(&self) -> &ActorUri;
23
24    /// Actor path.
25    ///
26    /// e.g. `/user/actor_a/actor_b`
27    fn path(&self) -> &ActorPath;
28
29    /// True if this actor is the top level root
30    ///
31    /// I.e. `/root`
32    fn is_root(&self) -> bool;
33
34    /// Parent reference
35    ///
36    /// Returns the `BasicActorRef` of this actor's parent actor
37    fn parent(&self) -> BasicActorRef;
38
39    /// User root reference
40    ///
41    /// I.e. `/root/user`
42    fn user_root(&self) -> BasicActorRef;
43
44    /// True is this actor has any children actors
45    fn has_children(&self) -> bool;
46
47    /// True if the given actor is a child of this actor
48    fn is_child(&self, actor: &BasicActorRef) -> bool;
49
50    /// Iterator over children references.
51    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = BasicActorRef> + 'a>;
52
53    /// Send a system message to this actor
54    fn sys_tell(&self, msg: SystemMsg);
55}
56
57pub type BoxedTell<T> = Box<dyn Tell<T> + Send + 'static>;
58
59pub trait Tell<T>: ActorReference + Send + 'static {
60    fn tell(&self, msg: T, sender: Option<BasicActorRef>);
61    fn box_clone(&self) -> BoxedTell<T>;
62}
63
64impl<T, M> Tell<T> for ActorRef<M>
65where
66    T: Message + Into<M>,
67    M: Message,
68{
69    fn tell(&self, msg: T, sender: Sender) {
70        self.send_msg(msg.into(), sender);
71    }
72
73    fn box_clone(&self) -> BoxedTell<T> {
74        Box::new((*self).clone())
75    }
76}
77
78impl<T> ActorReference for BoxedTell<T>
79where
80    T: Message,
81{
82    /// Actor name.
83    ///
84    /// Unique among siblings.
85    fn name(&self) -> &str {
86        (**self).name()
87    }
88
89    fn uri(&self) -> &ActorUri {
90        (**self).uri()
91    }
92
93    /// Actor path.
94    ///
95    /// e.g. `/user/actor_a/actor_b`
96    fn path(&self) -> &ActorPath {
97        (**self).path()
98    }
99
100    fn is_root(&self) -> bool {
101        (**self).is_root()
102    }
103
104    /// Parent reference.
105    fn parent(&self) -> BasicActorRef {
106        (**self).parent()
107    }
108
109    fn user_root(&self) -> BasicActorRef {
110        (**self).user_root()
111    }
112
113    fn has_children(&self) -> bool {
114        (**self).has_children()
115    }
116
117    fn is_child(&self, actor: &BasicActorRef) -> bool {
118        (**self).is_child(actor)
119    }
120
121    /// Iterator over children references.
122    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = BasicActorRef> + 'a> {
123        (**self).children()
124    }
125
126    fn sys_tell(&self, msg: SystemMsg) {
127        (**self).sys_tell(msg)
128    }
129}
130
131impl<T> PartialEq for BoxedTell<T> {
132    fn eq(&self, other: &Self) -> bool {
133        self.path() == other.path()
134    }
135}
136
137impl<T> fmt::Debug for BoxedTell<T> {
138    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
139        write!(f, "Tell[{:?}]", self.uri())
140    }
141}
142
143impl<T> fmt::Display for BoxedTell<T> {
144    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145        write!(f, "Tell[{}]", self.uri())
146    }
147}
148
149impl<T: 'static> Clone for BoxedTell<T> {
150    fn clone(&self) -> Self {
151        self.box_clone()
152    }
153}
154
155/// A lightweight, un-typed reference to interact with its underlying
156/// actor instance through concurrent messaging.
157///
158/// `BasicActorRef` can be derived from an original `ActorRef<Msg>`.
159///
160/// `BasicActorRef` allows for un-typed messaging using `try_tell`,
161/// that will return a `Result`. If the message type was not supported,
162/// the result will contain an `Error`.
163///
164/// `BasicActorRef` can be used when the original `ActorRef` isn't available,
165/// when you need to use collections to store references from different actor
166/// types, or when using actor selections to message parts of the actor hierarchy.
167///
168/// In general, it is better to use `ActorRef` where possible.
169#[derive(Clone)]
170pub struct BasicActorRef {
171    pub cell: ActorCell,
172}
173
174impl BasicActorRef {
175    #[doc(hidden)]
176    #[must_use]
177    pub const fn new(cell: ActorCell) -> Self {
178        Self { cell }
179    }
180
181    #[allow(clippy::unused_self)]
182    pub fn typed<Msg: Message>(&self, cell: ExtendedCell<Msg>) -> ActorRef<Msg> {
183        ActorRef { cell }
184    }
185
186    pub(crate) fn sys_init(&self, sys: &ActorSystem) {
187        self.cell.kernel().sys_init(sys);
188    }
189
190    /// Send a message to this actor
191    ///
192    /// Returns a result. If the message type is not supported Error is returned.
193    pub fn try_tell<Msg>(&self, msg: Msg, sender: impl Into<Option<Self>>) -> Result<(), ()>
194    where
195        Msg: Message + Send,
196    {
197        self.try_tell_any(&mut AnyMessage::new(msg, true), sender)
198    }
199
200    pub fn try_tell_any(
201        &self,
202        msg: &mut AnyMessage,
203        sender: impl Into<Option<Self>>,
204    ) -> Result<(), ()> {
205        self.cell.send_any_msg(msg, sender.into())
206    }
207}
208
209impl ActorReference for BasicActorRef {
210    /// Actor name.
211    ///
212    /// Unique among siblings.
213    fn name(&self) -> &str {
214        self.cell.uri().name.as_str()
215    }
216
217    fn uri(&self) -> &ActorUri {
218        self.cell.uri()
219    }
220
221    /// Actor path.
222    ///
223    /// e.g. `/user/actor_a/actor_b`
224    fn path(&self) -> &ActorPath {
225        &self.cell.uri().path
226    }
227
228    fn is_root(&self) -> bool {
229        self.cell.is_root()
230    }
231
232    /// Parent reference.
233    fn parent(&self) -> BasicActorRef {
234        self.cell.parent()
235    }
236
237    fn user_root(&self) -> BasicActorRef {
238        self.cell.user_root()
239    }
240
241    fn has_children(&self) -> bool {
242        self.cell.has_children()
243    }
244
245    fn is_child(&self, actor: &BasicActorRef) -> bool {
246        self.cell.is_child(actor)
247    }
248
249    /// Iterator over children references.
250    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = BasicActorRef> + 'a> {
251        self.cell.children()
252    }
253
254    fn sys_tell(&self, msg: SystemMsg) {
255        let envelope = Envelope { msg, sender: None };
256        let _ = self.cell.send_sys_msg(envelope);
257    }
258}
259
260impl ActorReference for &BasicActorRef {
261    /// Actor name.
262    ///
263    /// Unique among siblings.
264    fn name(&self) -> &str {
265        self.cell.uri().name.as_str()
266    }
267
268    fn uri(&self) -> &ActorUri {
269        self.cell.uri()
270    }
271
272    /// Actor path.
273    ///
274    /// e.g. `/user/actor_a/actor_b`
275    fn path(&self) -> &ActorPath {
276        &self.cell.uri().path
277    }
278
279    fn is_root(&self) -> bool {
280        self.cell.is_root()
281    }
282
283    /// Parent reference.
284    fn parent(&self) -> BasicActorRef {
285        self.cell.parent()
286    }
287
288    fn user_root(&self) -> BasicActorRef {
289        self.cell.user_root()
290    }
291
292    fn has_children(&self) -> bool {
293        self.cell.has_children()
294    }
295
296    fn is_child(&self, actor: &BasicActorRef) -> bool {
297        self.cell.is_child(actor)
298    }
299
300    /// Iterator over children references.
301    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = BasicActorRef> + 'a> {
302        self.cell.children()
303    }
304
305    fn sys_tell(&self, msg: SystemMsg) {
306        let envelope = Envelope { msg, sender: None };
307        let _ = self.cell.send_sys_msg(envelope);
308    }
309}
310
311impl fmt::Debug for BasicActorRef {
312    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
313        write!(f, "BasicActorRef[{:?}]", self.cell.uri())
314    }
315}
316
317impl fmt::Display for BasicActorRef {
318    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319        write!(f, "BasicActorRef[{}]", self.cell.uri())
320    }
321}
322
323impl PartialEq for BasicActorRef {
324    fn eq(&self, other: &Self) -> bool {
325        self.cell.uri().path == other.cell.uri().path
326    }
327}
328
329impl<Msg> From<ActorRef<Msg>> for BasicActorRef
330where
331    Msg: Message,
332{
333    fn from(actor: ActorRef<Msg>) -> Self {
334        Self::new(ActorCell::from(actor.cell))
335    }
336}
337
338impl<Msg> From<ActorRef<Msg>> for Option<BasicActorRef>
339where
340    Msg: Message,
341{
342    fn from(actor: ActorRef<Msg>) -> Self {
343        Some(BasicActorRef::new(ActorCell::from(actor.cell)))
344    }
345}
346
347pub type Sender = Option<BasicActorRef>;
348
349/// A lightweight, typed reference to interact with its underlying
350/// actor instance through concurrent messaging.
351///
352/// All `ActorRefs` are products of `system.actor_of`
353/// or `context.actor_of`. When an actor is created using `actor_of`
354/// an `ActorRef<Msg>` is returned, where `Msg` is the mailbox
355/// message type for the actor.
356///
357/// Actor references are lightweight and can be cloned without concern
358/// for memory use.
359///
360/// Messages sent to an actor are added to the actor's mailbox.
361///
362/// In the event that the underlying actor is terminated messages sent
363/// to the actor will be routed to dead letters.
364///
365/// If an actor is restarted all existing references continue to
366/// be valid.
367#[derive(Clone)]
368pub struct ActorRef<Msg: Message> {
369    pub cell: ExtendedCell<Msg>,
370}
371
372impl<Msg: Message> ActorRef<Msg> {
373    #[doc(hidden)]
374    pub fn new(cell: ExtendedCell<Msg>) -> Self {
375        Self { cell }
376    }
377
378    pub fn send_msg(&self, msg: Msg, sender: impl Into<Option<BasicActorRef>>) {
379        let envelope = Envelope {
380            msg,
381            sender: sender.into(),
382        };
383        // consume the result (we don't return it to user)
384        let _ = self.cell.send_msg(envelope);
385    }
386}
387
388impl<Msg: Message> ActorReference for ActorRef<Msg> {
389    /// Actor name.
390    ///
391    /// Unique among siblings.
392    fn name(&self) -> &str {
393        self.cell.uri().name.as_str()
394    }
395
396    fn uri(&self) -> &ActorUri {
397        self.cell.uri()
398    }
399
400    /// Actor path.
401    ///
402    /// e.g. `/user/actor_a/actor_b`
403    fn path(&self) -> &ActorPath {
404        &self.cell.uri().path
405    }
406
407    fn is_root(&self) -> bool {
408        self.cell.is_root()
409    }
410
411    /// Parent reference.
412    fn parent(&self) -> BasicActorRef {
413        self.cell.parent()
414    }
415
416    fn user_root(&self) -> BasicActorRef {
417        self.cell.user_root()
418    }
419
420    fn has_children(&self) -> bool {
421        self.cell.has_children()
422    }
423
424    fn is_child(&self, actor: &BasicActorRef) -> bool {
425        self.cell.is_child(actor)
426    }
427
428    /// Iterator over children references.
429    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = BasicActorRef> + 'a> {
430        self.cell.children()
431    }
432
433    fn sys_tell(&self, msg: SystemMsg) {
434        let envelope = Envelope { msg, sender: None };
435        let _ = self.cell.send_sys_msg(envelope);
436    }
437}
438
439impl<Msg: Message> ActorReference for &ActorRef<Msg> {
440    /// Actor name.
441    ///
442    /// Unique among siblings.
443    fn name(&self) -> &str {
444        self.cell.uri().name.as_str()
445    }
446
447    fn uri(&self) -> &ActorUri {
448        self.cell.uri()
449    }
450
451    /// Actor path.
452    ///
453    /// e.g. `/user/actor_a/actor_b`
454    fn path(&self) -> &ActorPath {
455        &self.cell.uri().path
456    }
457
458    fn is_root(&self) -> bool {
459        self.cell.is_root()
460    }
461
462    /// Parent reference.
463    fn parent(&self) -> BasicActorRef {
464        self.cell.parent()
465    }
466
467    fn user_root(&self) -> BasicActorRef {
468        self.cell.user_root()
469    }
470
471    fn has_children(&self) -> bool {
472        self.cell.has_children()
473    }
474
475    fn is_child(&self, actor: &BasicActorRef) -> bool {
476        self.cell.is_child(actor)
477    }
478
479    /// Iterator over children references.
480    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = BasicActorRef> + 'a> {
481        self.cell.children()
482    }
483
484    fn sys_tell(&self, msg: SystemMsg) {
485        let envelope = Envelope { msg, sender: None };
486        let _ = self.cell.send_sys_msg(envelope);
487    }
488}
489
490impl<Msg: Message> fmt::Debug for ActorRef<Msg> {
491    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
492        write!(f, "ActorRef[{:?}]", self.uri())
493    }
494}
495
496impl<Msg: Message> fmt::Display for ActorRef<Msg> {
497    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
498        write!(f, "ActorRef[{}]", self.uri())
499    }
500}
501
502impl<Msg: Message> PartialEq for ActorRef<Msg> {
503    fn eq(&self, other: &Self) -> bool {
504        self.uri().path == other.uri().path
505    }
506}
507
508/// Produces `ActorRef`s. `actor_of` blocks on the current thread until
509/// the actor has successfully started or failed to start.
510///
511/// It is advised to return from the actor's factory method quickly and
512/// handle any initialization in the actor's `pre_start` method, which is
513/// invoked after the `ActorRef` is returned.
514pub trait ActorRefFactory {
515    fn actor_of_props<A>(
516        &self,
517        props: BoxActorProd<A>,
518        name: &str,
519    ) -> Result<ActorRef<A::Msg>, CreateError>
520    where
521        A: Actor;
522
523    fn actor_of<A>(&self, name: &str) -> Result<ActorRef<<A as Actor>::Msg>, CreateError>
524    where
525        A: ActorFactory + Actor;
526
527    fn actor_of_args<A, Args>(
528        &self,
529        name: &str,
530        args: Args,
531    ) -> Result<ActorRef<<A as Actor>::Msg>, CreateError>
532    where
533        Args: ActorArgs,
534        A: ActorFactoryArgs<Args>;
535
536    fn stop(&self, actor: impl ActorReference);
537}
538
539/// Produces `ActorRef`s under the `temp` guardian actor.
540pub trait TmpActorRefFactory {
541    fn tmp_actor_of_props<A>(
542        &self,
543        props: BoxActorProd<A>,
544    ) -> Result<ActorRef<A::Msg>, CreateError>
545    where
546        A: Actor;
547
548    fn tmp_actor_of<A>(&self) -> Result<ActorRef<<A as Actor>::Msg>, CreateError>
549    where
550        A: ActorFactory + Actor;
551
552    fn tmp_actor_of_args<A, Args>(
553        &self,
554        args: Args,
555    ) -> Result<ActorRef<<A as Actor>::Msg>, CreateError>
556    where
557        Args: ActorArgs,
558        A: ActorFactoryArgs<Args>;
559}