reifydb_runtime/actor/mailbox/
mod.rs1#[cfg(all(reifydb_single_threaded, not(reifydb_dst)))]
5use std::cell::{Cell, RefCell};
6use std::fmt;
7#[cfg(all(reifydb_single_threaded, not(reifydb_dst)))]
8use std::rc::Rc;
9#[cfg(all(reifydb_single_threaded, not(reifydb_dst)))]
10use std::sync::Arc;
11#[cfg(all(reifydb_single_threaded, not(reifydb_dst)))]
12use std::sync::atomic::AtomicBool;
13#[cfg(reifydb_target = "wasm")]
14use std::time::Duration;
15
16use cfg_if::cfg_if;
17
18#[cfg(reifydb_target = "wasm")]
19use crate::actor::timers::wasm::schedule_once_fn;
20
21#[cfg(not(reifydb_single_threaded))]
22pub(crate) mod host;
23
24#[cfg(all(reifydb_single_threaded, not(reifydb_dst)))]
25pub(crate) mod wasm;
26
27#[cfg(reifydb_dst)]
28pub(crate) mod dst;
29
30cfg_if! {
31 if #[cfg(reifydb_dst)] {
32 type ActorRefInnerImpl<M> = dst::ActorRefInner<M>;
33 } else if #[cfg(not(reifydb_single_threaded))] {
34 type ActorRefInnerImpl<M> = host::ActorRefInner<M>;
35 } else {
36 type ActorRefInnerImpl<M> = wasm::ActorRefInner<M>;
37 }
38}
39
40#[derive(Debug, Clone, PartialEq, Eq)]
41pub enum SendError<M> {
42 Closed(M),
43
44 Full(M),
45}
46
47impl<M> SendError<M> {
48 #[inline]
49 pub fn into_inner(self) -> M {
50 match self {
51 SendError::Closed(m) => m,
52 SendError::Full(m) => m,
53 }
54 }
55}
56
57impl<M: fmt::Debug> fmt::Display for SendError<M> {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 match self {
60 SendError::Closed(_) => write!(f, "actor mailbox closed"),
61 SendError::Full(_) => write!(f, "actor mailbox full"),
62 }
63 }
64}
65
66impl<M: fmt::Debug> error::Error for SendError<M> {}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
69pub enum AskError {
70 SendFailed,
71
72 ResponseClosed,
73}
74
75impl fmt::Display for AskError {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 match self {
78 AskError::SendFailed => write!(f, "failed to send ask request"),
79 AskError::ResponseClosed => write!(f, "response channel closed"),
80 }
81 }
82}
83
84impl error::Error for AskError {}
85
86pub struct ActorRef<M> {
87 inner: ActorRefInnerImpl<M>,
88}
89
90impl<M> Clone for ActorRef<M> {
91 #[inline]
92 fn clone(&self) -> Self {
93 Self {
94 inner: self.inner.clone(),
95 }
96 }
97}
98
99impl<M> fmt::Debug for ActorRef<M> {
100 #[inline]
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 self.inner.fmt(f)
103 }
104}
105
106#[cfg(reifydb_single_threaded)]
109unsafe impl<M> Send for ActorRef<M> {}
110
111#[cfg(reifydb_single_threaded)]
112unsafe impl<M> Sync for ActorRef<M> {}
113
114impl<M> ActorRef<M> {
115 #[inline]
116 pub(crate) fn from_inner(inner: ActorRefInnerImpl<M>) -> Self {
117 Self {
118 inner,
119 }
120 }
121}
122
123#[cfg(not(reifydb_single_threaded))]
124impl<M: Send> ActorRef<M> {
125 #[inline]
126 pub(crate) fn new(tx: Sender<M>) -> Self {
127 Self {
128 inner: host::ActorRefInner::new(tx),
129 }
130 }
131
132 #[inline]
133 pub(crate) fn set_notify(&self, f: sync::Arc<dyn Fn() + Send + Sync>) {
134 self.inner.set_notify(f)
135 }
136
137 #[inline]
138 pub fn send(&self, msg: M) -> Result<(), SendError<M>> {
139 self.inner.send(msg)
140 }
141
142 #[inline]
143 pub fn send_deferred(&self, msg: M) -> Result<(), SendError<M>> {
144 self.inner.send(msg)
145 }
146
147 #[inline]
148 pub fn send_blocking(&self, msg: M) -> Result<(), SendError<M>> {
149 self.inner.send_blocking(msg)
150 }
151
152 #[inline]
153 pub fn is_alive(&self) -> bool {
154 self.inner.is_alive()
155 }
156}
157
158#[cfg(reifydb_dst)]
159impl<M> ActorRef<M> {
160 #[inline]
161 pub fn send(&self, msg: M) -> Result<(), SendError<M>> {
162 self.inner.send(msg)
163 }
164
165 #[inline]
166 pub fn send_deferred(&self, msg: M) -> Result<(), SendError<M>> {
167 self.inner.send(msg)
168 }
169
170 #[inline]
171 pub fn send_blocking(&self, msg: M) -> Result<(), SendError<M>> {
172 self.inner.send_blocking(msg)
173 }
174
175 #[inline]
176 pub fn is_alive(&self) -> bool {
177 self.inner.is_alive()
178 }
179
180 #[inline]
181 pub(crate) fn mark_stopped(&self) {
182 self.inner.mark_stopped()
183 }
184
185 #[inline]
186 pub(crate) fn set_notify(&self, f: Box<dyn Fn()>) {
187 self.inner.set_notify(f)
188 }
189}
190
191#[cfg(all(reifydb_single_threaded, not(reifydb_dst)))]
192impl<M> ActorRef<M> {
193 #[inline]
194 pub(crate) fn from_wasm_inner(
195 processor: Rc<RefCell<Option<Box<dyn FnMut(M)>>>>,
196 alive: Arc<AtomicBool>,
197 queue: Rc<RefCell<Vec<M>>>,
198 processing: Rc<Cell<bool>>,
199 ) -> Self {
200 Self {
201 inner: wasm::ActorRefInner::new(processor, alive, queue, processing),
202 }
203 }
204
205 #[inline]
206 pub fn send(&self, msg: M) -> Result<(), SendError<M>> {
207 self.inner.send(msg)
208 }
209
210 #[cfg(reifydb_target = "wasm")]
211 pub fn send_deferred(&self, msg: M) -> Result<(), SendError<M>>
212 where
213 M: Send + 'static,
214 {
215 if !self.is_alive() {
216 return Err(SendError::Closed(msg));
217 }
218 schedule_once_fn(self.clone(), Duration::ZERO, move || msg);
219 Ok(())
220 }
221
222 #[cfg(reifydb_target = "wasi")]
223 #[inline]
224 pub fn send_deferred(&self, msg: M) -> Result<(), SendError<M>> {
225 self.inner.send(msg)
226 }
227
228 #[inline]
229 pub fn send_blocking(&self, msg: M) -> Result<(), SendError<M>> {
230 self.inner.send_blocking(msg)
231 }
232
233 #[inline]
234 pub fn is_alive(&self) -> bool {
235 self.inner.is_alive()
236 }
237
238 #[inline]
239 pub(crate) fn mark_stopped(&self) {
240 self.inner.mark_stopped()
241 }
242
243 #[inline]
244 pub(crate) fn processor(&self) -> &Rc<RefCell<Option<Box<dyn FnMut(M)>>>> {
245 &self.inner.processor
246 }
247}
248
249use std::error;
250#[cfg(not(reifydb_single_threaded))]
251use std::sync;
252
253#[cfg(not(reifydb_single_threaded))]
254use crossbeam_channel::Sender;
255#[cfg(reifydb_dst)]
256pub(crate) use dst::create_mailbox as create_dst_mailbox;
257#[cfg(not(reifydb_single_threaded))]
258pub(crate) use host::create_mailbox;
259#[cfg(all(reifydb_single_threaded, not(reifydb_dst)))]
260pub(crate) use wasm::create_actor_ref;