compio_actor\mailbox/
mod.rs1mod call;
4mod error;
5mod name;
6mod receiver;
7
8use std::{
9 any::Any,
10 fmt,
11 num::NonZeroUsize,
12 sync::{
13 Arc,
14 atomic::{AtomicBool, Ordering},
15 },
16};
17
18pub(crate) use call::call_with;
19#[doc(inline)]
20pub use call::{Call, Reply};
21#[doc(inline)]
22pub use error::{CallError, DeliverError};
23use flume::{Sender, TrySendError};
24pub(crate) use name::Name;
25pub(crate) use receiver::{MailboxEvent, Receiver, make_mailbox};
26
27use crate::{Actor, Handler, Message, actor::Delivering};
28
29pub const DEFAULT_MAILBOX_CAPACITY: NonZeroUsize = NonZeroUsize::new(64).unwrap();
31
32struct MailboxInner<A: Actor> {
33 name: Option<Name>,
34 messages: Sender<Delivering<A>>,
35 stop: Sender<()>,
36 stopping: AtomicBool,
37 capacity: NonZeroUsize,
38}
39
40impl<A: Actor> MailboxInner<A> {
41 fn send<M>(&self, message: M) -> Result<(), DeliverError<M>>
42 where
43 A: Handler<M>,
44 M: Message,
45 {
46 if self.is_closed() {
47 return Err(DeliverError::Closed(message));
48 }
49
50 self.messages
51 .try_send(Delivering::<A>::from_msg(message))
52 .map_err(|error| match error {
53 TrySendError::Full(message) => DeliverError::Full(message.recover::<M>()),
54 TrySendError::Disconnected(message) => DeliverError::Closed(message.recover::<M>()),
55 })
56 }
57
58 fn stop(&self) -> bool {
59 if self.stopping.swap(true, Ordering::AcqRel) {
60 return false;
61 }
62 self.stop.try_send(()).is_ok()
63 }
64
65 fn begin_stop(&self) {
66 self.stopping.store(true, Ordering::Release);
67 }
68
69 fn is_closed(&self) -> bool {
70 self.stopping.load(Ordering::Acquire)
71 || self.messages.is_disconnected()
72 || self.stop.is_disconnected()
73 }
74}
75
76pub struct Mailbox<A: Actor> {
78 inner: Arc<MailboxInner<A>>,
79}
80
81impl<A: Actor> Mailbox<A> {
82 pub(crate) fn begin_stop(&self) {
83 self.inner.begin_stop();
84 }
85
86 pub fn name(&self) -> Option<&str> {
88 self.inner.name.as_ref().map(Name::as_str)
89 }
90
91 pub fn send<M>(&self, message: M) -> Result<(), DeliverError<M>>
93 where
94 A: Handler<M>,
95 M: Message,
96 {
97 self.inner.send(message)
98 }
99
100 pub fn broker<M>(&self) -> Broker<M>
102 where
103 A: Handler<M>,
104 M: Message,
105 {
106 let inner: Arc<dyn BrokerSink<M>> = self.inner.clone();
107 Broker { inner }
108 }
109
110 pub fn stop(&self) -> bool {
112 self.inner.stop()
113 }
114
115 pub fn is_closed(&self) -> bool {
117 self.inner.is_closed()
118 }
119
120 pub fn capacity(&self) -> NonZeroUsize {
122 self.inner.capacity
123 }
124}
125
126impl<A: Actor> Clone for Mailbox<A> {
127 fn clone(&self) -> Self {
128 Self {
129 inner: self.inner.clone(),
130 }
131 }
132}
133
134impl<A: Actor> fmt::Debug for Mailbox<A> {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 f.debug_struct("Mailbox")
137 .field("name", &self.name())
138 .field("capacity", &self.inner.capacity)
139 .field("queued", &self.inner.messages.len())
140 .field("closed", &self.is_closed())
141 .finish()
142 }
143}
144
145trait BrokerSink<M: Message>: Send + Sync {
146 fn name(&self) -> Option<&str>;
147 fn send(&self, message: M) -> Result<(), DeliverError<M>>;
148}
149
150impl<A, M> BrokerSink<M> for MailboxInner<A>
151where
152 A: Handler<M>,
153 M: Message,
154{
155 fn name(&self) -> Option<&str> {
156 self.name.as_ref().map(Name::as_str)
157 }
158
159 fn send(&self, message: M) -> Result<(), DeliverError<M>> {
160 MailboxInner::send(self, message)
161 }
162}
163
164pub struct Broker<M: Message> {
166 inner: Arc<dyn BrokerSink<M>>,
167}
168
169impl<M: Message> Broker<M> {
170 pub fn name(&self) -> Option<&str> {
172 self.inner.name()
173 }
174
175 pub fn send(&self, message: M) -> Result<(), DeliverError<M>> {
177 self.inner.send(message)
178 }
179}
180
181impl<M: Message> Clone for Broker<M> {
182 fn clone(&self) -> Self {
183 Self {
184 inner: self.inner.clone(),
185 }
186 }
187}
188
189impl<M: Message> fmt::Debug for Broker<M> {
190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191 f.debug_struct("Broker")
192 .field("name", &self.name())
193 .finish_non_exhaustive()
194 }
195}
196
197pub(crate) type ErasedMailbox = Arc<dyn Any + Send + Sync>;
198
199impl<A: Actor> Mailbox<A> {
200 pub(crate) fn erase(&self) -> ErasedMailbox {
201 self.inner.clone()
202 }
203
204 pub(crate) fn from_erased(inner: ErasedMailbox) -> Option<Self> {
205 Arc::downcast::<MailboxInner<A>>(inner)
206 .ok()
207 .map(|inner| Self { inner })
208 }
209}