Macro ergo::ch[]

macro_rules! ch {
    [ $ send : ident <- ? $ value : expr ] => { ... };
    [ $ send : ident <- $ value : expr ] => { ... };
    [
<- ? $ recv : ident ] => { ... };
    [ <- $ recv : ident ] => { ... };
    [
! <- ? $ recv : ident ] => { ... };
    [ ! <- $ recv : ident ] => { ... };
}

Use with channels with ergonomic syntax and panic with helpful error messages when sending/receiving on a channel is invalid.

  • ch!(send <- 42) for sending a value.
  • let v = ch!(<- recv) for receiving a value.
  • ch!(! <- recv) to wait for channels to close.
  • <-? for async operation support.

Blocking syntax:

  • ch!(send <- value): blocks until a value is sent, panics if all receivers are dropped.
  • ch!(<- recv): blocks until a value is received, panics if all senders are dropped.
  • ch!(! <- recv): blocks until all senders are dropped, panics if a value is received. Used for signaling.

This syntax works with both crossbeam-channel channels (which are exported by this crate) as well as std::mspc channels.

Note that these operations can deadlock if a channel is leaked.

Non-Blocking syntax:

  • ch!(send <-? value): returns None if the value was sent, Some(value) if the value was not sent. Panics if all receivers are dropped.
  • ch!(<-? recv): returns None if no value is received, Some(value) if a value is received. Panics if all senders are dropped.
  • ch!(! <-? recv): returns true if there are still senders and false if the seners have been dropped. Panics if a value is received. Use with while ch!(! <-? recv) { /* ... */ }

Non-Blocking syntax does not work with std::mspc channels.

Examples

Example: Using ergo::chan channels

#[macro_use] extern crate ergo_sync;
use ergo_sync::*;
let (send, recv) = ch::bounded(3);
ch!(send <- 4);
ch!(send <- 7);
ch!(send <- 42);
assert_eq!(4, ch!(<- recv));
assert_eq!(7, ch!(<- recv));
let v = ch!(<- recv);
assert_eq!(42, v);

drop(send);
// ch!(<- recv); // panics
ch!(! <- recv);  // succeeds

Example: Using std::mspc channels

#[macro_use] extern crate ergo_sync;
use std::sync::mpsc::sync_channel;

let (send, recv) = sync_channel(3);
ch!(send <- 4);
ch!(send <- 7);
ch!(send <- 42);
assert_eq!(4, ch!(<- recv));
assert_eq!(7, ch!(<- recv));
let v = ch!(<- recv);
assert_eq!(42, v);

drop(send);
// ch!(<- recv); // panics
ch!(! <- recv);  // succeeds

Example: using non-blocking syntax

#[macro_use] extern crate ergo_sync;
use ergo_sync::*;
let (send, recv) = ch::bounded(3);
assert_eq!(None, ch!(<-? recv)); // no values sent yet

assert!(ch!(send <-? 4).is_none());
assert_eq!(Some(4), ch!(<-? recv));
assert_eq!(None, ch!(<-? recv));

assert!(ch!(send <-? 7).is_none());
assert!(ch!(send <-? 42).is_none());
assert!(ch!(send <-? 1).is_none());
// further attempts return the value
assert_eq!(Some(100), ch!(send <-? 100));

assert_eq!(Some(7), ch!(<-? recv));

assert_eq!(Some(42), ch!(<-? recv));
assert_eq!(Some(1), ch!(<-? recv));
assert_eq!(None, ch!(<-? recv));
assert!(ch!(! <-? recv)); // senders still exist

drop(send);
// ch!(<-? recv); // panics
ch!(! <-? recv);  // succeeds