1pub extern crate crossbeam_channel;
2pub use paste;
3pub use sync_unsafe_cell;
4
5#[macro_export]
21macro_rules! global_channel {
22 ($channel_name:ident, $bounds:expr, $item:ty) => {
23 $crate::paste::paste! {
24 #[allow(non_upper_case_globals)]
25 static [<__ $channel_name _TX>]: $crate::sync_unsafe_cell::SyncUnsafeCell<
26 ::std::mem::MaybeUninit<$crate::crossbeam_channel::Sender<$item>>
27 > = $crate::sync_unsafe_cell::SyncUnsafeCell::new(::std::mem::MaybeUninit::uninit());
28
29 #[allow(non_upper_case_globals)]
30 static [<__ $channel_name _RX>]: $crate::sync_unsafe_cell::SyncUnsafeCell<
31 ::std::mem::MaybeUninit<$crate::crossbeam_channel::Receiver<$item>>
32 > = $crate::sync_unsafe_cell::SyncUnsafeCell::new(::std::mem::MaybeUninit::uninit());
33
34 #[allow(non_snake_case)]
36 fn [<setup_channel_ $channel_name>](bounds: Option<usize>) {
37 static INIT: ::std::sync::Once = ::std::sync::Once::new();
38 INIT.call_once(|| {
39 let (tx, rx) = match bounds {
40 Some(b) => $crate::crossbeam_channel::bounded(b),
41 None => $crate::crossbeam_channel::unbounded(),
42 };
43 unsafe {
44 let tx_ref = &mut *[<__ $channel_name _TX>].get();
45 let rx_ref = &mut *[<__ $channel_name _RX>].get();
46 tx_ref.write(tx);
47 rx_ref.write(rx);
48 }
49 });
50 }
51
52 #[allow(non_snake_case)]
53 #[inline]
54 pub fn [<$channel_name _tx>]() -> &'static $crate::crossbeam_channel::Sender<$item> {
55 [<setup_channel_ $channel_name>]($bounds);
56 unsafe { &*(*[<__ $channel_name _TX>].get()).as_ptr() }
57 }
58
59 #[allow(non_snake_case)]
60 #[inline]
61 pub fn [<$channel_name _rx>]() -> &'static $crate::crossbeam_channel::Receiver<$item> {
62 [<setup_channel_ $channel_name>]($bounds);
63 unsafe { &*(*[<__ $channel_name _RX>].get()).as_ptr() }
64 }
65 }
66 };
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 global_channel!(test_channel, None, u32);
74
75 #[test]
76 fn test_basic_usage() {
77 let tx = test_channel_tx();
78 let rx = test_channel_rx();
79 tx.send(42).unwrap();
80 assert_eq!(rx.recv().unwrap(), 42);
81 }
82}