black_box/actors/mod.rs
1use std::future::Future;
2
3use async_channel::Sender;
4
5use crate::{
6 executor::Context,
7 message::{Envelope, Message},
8};
9
10/// Abstraction for message handleing
11///
12/// Actors are spawned in an [`Executor`](crate::Executor), and run in the executor's event loop.
13/// When new messages are received by the executor, the appropriate handler [`Handler`] is invoked,
14/// allowing the actor to take any necessary action, including mutating it's internal state.
15pub trait Actor: Sized {
16 fn starting(&mut self, _ctx: &Context<Self>) -> impl Future<Output = ()> + Send {
17 std::future::ready(())
18 }
19
20 fn stopping(&mut self, _ctx: &Context<Self>) -> impl Future<Output = ()> + Send {
21 std::future::ready(())
22 }
23}
24
25/// The implementation for how an actor handles a particular message
26///
27/// An [`Actor`], can implement the Handler trait any number of time, with a unique message type for
28/// each implementation.
29pub trait Handler<M>
30where
31 Self: Actor,
32 M: Message,
33{
34 /// Asynchronously act on the message, with mutable access to self
35 fn handle(&mut self, msg: M, ctx: &Context<Self>) -> impl Future<Output = ()> + Send;
36}
37
38/// A cloneable address which can be used to send messages to the associated [`Actor`]
39///
40/// This is a cheaply cloneable type and can be used to send an actor address to other actors, other
41/// runtimes, etc.
42pub struct Address<A> {
43 sender: Sender<Envelope<A>>,
44}
45
46// SAFETY: The address is a queue abstraction for *messages* sent to the actor. Even if the actor
47// itself is not Send/Sync the address should be. The Message trait itself already requires that
48// the implementer be Send
49unsafe impl<A> std::marker::Send for Address<A> {}
50// SAFETY: As above but for Sync
51unsafe impl<A> std::marker::Sync for Address<A> {}
52
53impl<A> Clone for Address<A> {
54 fn clone(&self) -> Self {
55 Self {
56 sender: self.sender.clone(),
57 }
58 }
59}
60
61impl<A> Address<A> {
62 pub(crate) fn new(sender: Sender<Envelope<A>>) -> Self {
63 Self { sender }
64 }
65}
66
67impl<A> Address<A>
68where
69 A: 'static + Actor + Send,
70{
71 /// Send the given message to the actor's receiver.
72 ///
73 /// If the receiver is currently full, it will await capacity to enqueue the message
74 pub async fn send<M>(&self, message: M)
75 where
76 A: Handler<M>,
77 M: Message,
78 {
79 let env = Envelope::pack(message);
80
81 // TODO: Decide what to do here
82 let _ = self.sender.send(env).await;
83 }
84
85 pub fn try_send<M>(&self, message: M)
86 where
87 A: Handler<M>,
88 M: Message,
89 {
90 let env = Envelope::pack(message);
91
92 // TODO: Decide what to do here
93 let _ = self.sender.try_send(env);
94 }
95}