macro_rules! channel {
($expr:expr, wrap = true) => { ... };
($expr:expr, wrap = true, label = $label:expr) => { ... };
($expr:expr, wrap = true, log = true) => { ... };
($expr:expr, wrap = true, label = $label:expr, log = true) => { ... };
($expr:expr, wrap = true, log = true, label = $label:expr) => { ... };
($expr:expr, wrap = true, capacity = $capacity:expr) => { ... };
($expr:expr, capacity = $capacity:expr, wrap = true) => { ... };
($expr:expr, wrap = true, capacity = $capacity:expr, label = $label:expr) => { ... };
($expr:expr, wrap = true, label = $label:expr, capacity = $capacity:expr) => { ... };
($expr:expr, wrap = true, capacity = $capacity:expr, log = true) => { ... };
($expr:expr, wrap = true, log = true, capacity = $capacity:expr) => { ... };
($expr:expr, wrap = true, capacity = $capacity:expr, label = $label:expr, log = true) => { ... };
($expr:expr, wrap = true, label = $label:expr, capacity = $capacity:expr, log = true) => { ... };
($expr:expr, label = $label:expr, wrap = true) => { ... };
($expr:expr, log = true, wrap = true) => { ... };
($expr:expr, label = $label:expr, wrap = true, log = true) => { ... };
($expr:expr, log = true, wrap = true, label = $label:expr) => { ... };
($expr:expr, label = $label:expr, log = true, wrap = true) => { ... };
($expr:expr, log = true, label = $label:expr, wrap = true) => { ... };
($expr:expr) => { ... };
($expr:expr, label = $label:expr) => { ... };
($expr:expr, capacity = $capacity:expr) => { ... };
($expr:expr, label = $label:expr, capacity = $capacity:expr) => { ... };
($expr:expr, capacity = $capacity:expr, label = $label:expr) => { ... };
($expr:expr, log = true) => { ... };
($expr:expr, label = $label:expr, log = true) => { ... };
($expr:expr, log = true, label = $label:expr) => { ... };
($expr:expr, capacity = $capacity:expr, log = true) => { ... };
($expr:expr, log = true, capacity = $capacity:expr) => { ... };
($expr:expr, label = $label:expr, capacity = $capacity:expr, log = true) => { ... };
($expr:expr, label = $label:expr, log = true, capacity = $capacity:expr) => { ... };
($expr:expr, capacity = $capacity:expr, label = $label:expr, log = true) => { ... };
($expr:expr, capacity = $capacity:expr, log = true, label = $label:expr) => { ... };
($expr:expr, log = true, label = $label:expr, capacity = $capacity:expr) => { ... };
($expr:expr, log = true, capacity = $capacity:expr, label = $label:expr) => { ... };
(@wrap_munch $id:ident, $e:expr ; $lbl:tt $cap:tt $log:tt $wrap:tt ;) => { ... };
(@wrap_munch $id:ident, $e:expr ; $lbl:tt $cap:tt $log:tt $wrap:tt ; wrap = true $(, $($r:tt)*)?) => { ... };
(@wrap_munch $id:ident, $e:expr ; $lbl:tt $cap:tt $log:tt $wrap:tt ; label = $l:expr $(, $($r:tt)*)?) => { ... };
(@wrap_munch $id:ident, $e:expr ; $lbl:tt $cap:tt $log:tt $wrap:tt ; capacity = $c:expr $(, $($r:tt)*)?) => { ... };
(@wrap_munch $id:ident, $e:expr ; $lbl:tt $cap:tt $log:tt $wrap:tt ; log = true $(, $($r:tt)*)?) => { ... };
(@wrap_dispatch $id:ident, $e:expr ; [$l:expr] [$c:expr] [log] [wrap]) => { ... };
(@wrap_dispatch $id:ident, $e:expr ; [$l:expr] [$c:expr] [nolog] [wrap]) => { ... };
(@wrap_dispatch $id:ident, $e:expr ; [] [$c:expr] [log] [wrap]) => { ... };
(@wrap_dispatch $id:ident, $e:expr ; [] [$c:expr] [nolog] [wrap]) => { ... };
(@wrap_dispatch $id:ident, $e:expr ; [$l:expr] [] [log] [wrap]) => { ... };
(@wrap_dispatch $id:ident, $e:expr ; [$l:expr] [] [nolog] [wrap]) => { ... };
(@wrap_dispatch $id:ident, $e:expr ; [] [] [log] [wrap]) => { ... };
(@wrap_dispatch $id:ident, $e:expr ; [] [] [nolog] [wrap]) => { ... };
(@wrap_dispatch $id:ident, $e:expr ; $lbl:tt $cap:tt $log:tt [nowrap]) => { ... };
($expr:expr, $($rest:tt)*) => { ... };
}Expand description
Instrument a channel creation to wrap it with debugging proxies.
Optional parameters: label, log = true, capacity (in any order).
capacity is required for futures_channel::mpsc bounded channels.
log = true requires Debug on the message type.
§wrap = true
The channel expression must be constructed inline, e.g.
channel!(crossbeam_channel::unbounded::<T>(), wrap = true). The wrapper rebuilds
the inner channel (to carry a per-message id) and discards the one you pass in, so
any endpoint cloned before wrapping is orphaned and its messages are silently
dropped. Clone the returned wrapper endpoints instead.
Bounded std::sync::mpsc wrappers (sync_channel) cannot recover their capacity
from the endpoint, so capacity = N is required, e.g.
channel!(std::sync::mpsc::sync_channel::<T>(100), wrap = true, capacity = 100).
Unbounded std and crossbeam wrappers need no capacity.
The capacity you pass must match the sync_channel(N) argument. Wrap mode
rebuilds the inner channel from capacity and discards the one you constructed, so a
mismatch (e.g. sync_channel(100) with capacity = 1) silently builds a different
bounded channel - and only in profiled builds: with hotpath off, channel! returns
your original sync_channel(100) untouched. The result is different backpressure (and
potentially a deadlock) that appears only when profiling. There is no way to verify
this for you, because std exposes no capacity accessor - keep the two numbers equal.
§Examples
use tokio::sync::mpsc;
#[tokio::main]
async fn main() {
let (tx, rx) = hotpath::channel!(mpsc::channel::<String>(100));
tx.send("Hello".to_string()).await.unwrap();
}