Expand description
Pre-allocated mailbox for actor messages.
Replaces tokio’s mpsc channels with a bounded VecDeque protected
by a parking_lot::Mutex. Messages are wrapped in Arc<Message> so
fanout is a refcount bump (~2 ns), not a deep clone of [Message].
§Wait Strategy
The consumer calls tokio::sync::Notify::notified when the queue is
empty, and the producer calls tokio::sync::Notify::notify_one after
pushing. This is cooperative — not busy-spin — and works on every
platform (native + WASM) because Notify is backed by the tokio
scheduler on native and wasm_bindgen_futures on WASM.
§Performance
Compared to tokio::mpsc (which was measured at 309 µs per crossing):
| Operation | Mailbox | tokio mpc |
|---|---|---|
send | ~17 ns | ~309 µs |
recv | ~12 ns | ~309 µs |
recv_batch | ~0.8 ns/msg amortized | ~309 µs/msg |
The Mailbox eliminates:
- Per-message
tokio::task::spawnwakeups (batch drain amortizes) Messageclone on fanout (Arc::cloneis a refcount bump)- Channel overhead (crossbeam-queue-style allocation vs tokio’s internal task queue management)
§Backpressure
When the queue is at capacity, MailboxSender::send returns
Err(()). This matches the existing bounded-channel behavior and
provides backpressure for write-heavy actors (storage write actors).
§Example
use beam::mailbox;
use beam::message::Message;
use std::sync::Arc;
let (tx, mut rx) = mailbox(1024);
tx.send(Arc::new(Message::Hi {
from: beam::actor::Addr::noop(),
peer_id: "test".to_string(),
is_ack: None,
msg_id: "doc".to_string(),
})).unwrap();
let mut batch = Vec::with_capacity(64);
let n = rx.recv_batch(&mut batch, 64).await;
assert_eq!(n, 1);Structs§
- Mailbox
Receiver - The receiver half of a
mailbox. Unique — only one consumer. - Mailbox
Sender - The sender half of a
mailbox. Clonable — multiple senders share the same underlying queue viaArc.
Functions§
- mailbox
- Creates a bounded mailbox pair with the given capacity.