Concurrency Coordination Reports
MPSC Try-Recv Coordination Report
A drain report records nonblocking receives from a channel. This program fills a channel, then uses try_recv a selected number of times and reports drained versus empty receives.
Program
Play the program to choose how many receive attempts run and watch the queue drain and then report empty.
mpsc_try_recv_coordination_report.rs
Replay: real traced execution (multi-file project)
use std::sync::mpsc::channel;
fn main() {
let attempts = 3;
let (tx, rx) = channel();
for value in 0..3 {
let _ = tx.send(value);
}
let mut drained = 0;
let mut empty_hits = 0;
for _ in 0..attempts {
match rx.try_recv() {
Ok(_) => drained += 1,
Err(_) => empty_hits += 1,
}
}
let status = if drained == 0 {
"idle"
} else if empty_hits > 0 {
"drained"
} else {
"draining"
};
println!("attempts={attempts} drained={drained} empty={empty_hits} {status}");
}
use std::sync::mpsc::channel;
fn main() {
let attempts = 0;
let (tx, rx) = channel();
for value in 0..3 {
let _ = tx.send(value);
}
let mut drained = 0;
let mut empty_hits = 0;
for _ in 0..attempts {
match rx.try_recv() {
Ok(_) => drained += 1,
Err(_) => empty_hits += 1,
}
}
let status = if drained == 0 {
"idle"
} else if empty_hits > 0 {
"drained"
} else {
"draining"
};
println!("attempts={attempts} drained={drained} empty={empty_hits} {status}");
}
use std::sync::mpsc::channel;
fn main() {
let attempts = 5;
let (tx, rx) = channel();
for value in 0..3 {
let _ = tx.send(value);
}
let mut drained = 0;
let mut empty_hits = 0;
for _ in 0..attempts {
match rx.try_recv() {
Ok(_) => drained += 1,
Err(_) => empty_hits += 1,
}
}
let status = if drained == 0 {
"idle"
} else if empty_hits > 0 {
"drained"
} else {
"draining"
};
println!("attempts={attempts} drained={drained} empty={empty_hits} {status}");
}
attempts ← 3
3fn main() {4 let attempt→ 3s = 3; //@attempts=3, 0, 55 let (tx, rx) = channel();6 for value in 0..3 {for value in 0..3
pass 1 of 35let (tx, rx) = channel();6for valu0e in 0..3 {7 let _ = tx.send(value);8}All 3 passes — pass 1 is the card above pass value1 0 2 1 3 2 drained ← 0, empty_hits ← 0
8}9let mut draine→ 0d = 0;10let mut empty_hit→ 0s = 0;11for _ in 0..attempts {for _ in 0..attempts
pass 1 of 310let mut empty_hits = 0;11for _ in 0..attempt3s {12 match rx.try_recv() {status ← "draining"
16 }17 let statu→ "draining"s = if draine3d == 0 {18 "idle"19 } else if empty_hit0s > 0 {20 "drained"21 } else {22 "draining"23 };24 println!("attempts={attempts} drained={drained} empty={empty_hits} {status}");25}outputattempts=3 drained=3 empty=0 draining
attempts ← 0
3fn main() {4 let attempt→ 0s = 0;5 let (tx, rx) = channel();6 for value in 0..3 {for value in 0..3
pass 1 of 35let (tx, rx) = channel();6for valu0e in 0..3 {7 let _ = tx.send(value);8}All 3 passes — pass 1 is the card above pass value1 0 2 1 3 2 drained ← 0, empty_hits ← 0, status ← "idle"
8 }9 let mut draine→ 0d = 0;10 let mut empty_hit→ 0s = 0;11 for _ in 0..attempts {12 match rx.try_recv() {13 Ok(_) => drained += 1,14 Err(_) => empty_hits += 1,15 }16 }17 let statu→ "idle"s = if draine0d == 0 {18 "idle"19 } else if empty_hit0s > 0 {20 "drained"21 } else {22 "draining"23 };24 println!("attempts={attempts} drained={drained} empty={empty_hits} {status}");25}outputattempts=0 drained=0 empty=0 idle
attempts ← 5
3fn main() {4 let attempt→ 5s = 5;5 let (tx, rx) = channel();6 for value in 0..3 {for value in 0..3
pass 1 of 35let (tx, rx) = channel();6for valu0e in 0..3 {7 let _ = tx.send(value);8}All 3 passes — pass 1 is the card above pass value1 0 2 1 3 2 drained ← 0, empty_hits ← 0
8}9let mut draine→ 0d = 0;10let mut empty_hit→ 0s = 0;11for _ in 0..attempts {for _ in 0..attempts
pass 1 of 510let mut empty_hits = 0;11for _ in 0..attempt5s {12 match rx.try_recv() {status ← "drained"
16 }17 let statu→ "drained"s = if draine3d == 0 {18 "idle"19 } else if empty_hit2s > 0 {20 "drained"21 } else {22 "draining"23 };24 println!("attempts={attempts} drained={drained} empty={empty_hits} {status}");25}outputattempts=5 drained=3 empty=2 drained
nonblocking receive
`try_recv` returns `Ok` while messages remain and `Err` once the queue is empty, so it never blocks the caller.
drain report
Counting `Ok` results reports how many buffered messages were drained by the selected number of attempts.
empty signal
Extra attempts past the buffered messages report empty receives instead of waiting for new data.