Message Passing
Multiple-Producer Channels
A multiple-producer channel fans messages from $N$ concurrent producer threads into a single consumer thread (M:1 fan-in topology). In std::sync::mpsc, each producer thread is given a cloned Sender<T> (or SyncSender<T>), and all messages sent by any producer are interleaved safely into the receiver's queue.
FIFO Ordering Guarantees Across Multiple Producers
- Per-producer FIFO order: Messages sent sequentially by the same producer thread (
tx1.send(A)followed bytx1.send(B)) are guaranteed to arrive at theReceiver<T>in the exact orderAthenB. - Cross-producer interleaving: Messages sent concurrently by different producer threads (
tx1vs.tx2) arrive interleaved in the order their atomic enqueue operations complete at runtime.
Fan-In Topology (3 Producers -> 1 Aggregator Consumer):
Worker 0 (tx.clone()) --- [ (0, "step A"), (0, "step B") ] ---\
Worker 1 (tx.clone()) --- [ (1, "step A"), (1, "step B") ] ----+--> [ Receiver ]
Worker 2 (tx.clone()) --- [ (2, "step A"), (2, "step B") ] ---/
(Per-worker order `(i, "step A")` before `(i, "step B")` is strictly preserved!)
Typed Enum Messages for Heterogeneous Producers
When different subsystem threads (such as a network listener, a timer thread, and a signal watcher) feed events into a single central event loop, define an enum Event covering all producer message types and share Sender<Event> across all producers:
use std::sync::mpsc;
use std::thread;
#[derive(Debug)]
enum SystemEvent {
HttpRequest { client_ip: &'static str, path: &'static str },
HealthTick { uptime_secs: u64 },
Shutdown,
}
fn main() {
let (tx, rx) = mpsc::channel::<SystemEvent>();
let http_tx = tx.clone();
let http_worker = thread::spawn(move || {
http_tx
.send(SystemEvent::HttpRequest {
client_ip: "10.0.0.5",
path: "/api/orders",
})
.unwrap();
});
let timer_tx = tx.clone();
let timer_worker = thread::spawn(move || {
timer_tx
.send(SystemEvent::HealthTick { uptime_secs: 60 })
.unwrap();
});
http_worker.join().unwrap();
timer_worker.join().unwrap();
tx.send(SystemEvent::Shutdown).unwrap();
for event in rx {
match event {
SystemEvent::HttpRequest { client_ip, path } => {
println!("handled request from {} to {}", client_ip, path);
}
SystemEvent::HealthTick { uptime_secs } => {
println!("health check at uptime {}s", uptime_secs);
}
SystemEvent::Shutdown => {
println!("received Shutdown event; exiting loop");
break;
}
}
}
}
handled request from 10.0.0.5 to /api/orders
health check at uptime 60s
received Shutdown event; exiting loop