Skip to main content

Module mailbox

Module mailbox 

Source
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):

OperationMailboxtokio 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::spawn wakeups (batch drain amortizes)
  • Message clone on fanout (Arc::clone is 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§

MailboxReceiver
The receiver half of a mailbox. Unique — only one consumer.
MailboxSender
The sender half of a mailbox. Clonable — multiple senders share the same underlying queue via Arc.

Functions§

mailbox
Creates a bounded mailbox pair with the given capacity.