#[macro_export]
macro_rules! go {
($body:expr) => {{
$crate::__spawn($body)
}};
}
#[macro_export]
macro_rules! select {
( recv($r:expr) -> $v:ident => $b:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r), &mut __r0),
];
let (_i, __ok) = unsafe { $crate::select::selectgo(&mut __sel, false) };
let $v: ::std::option::Option<_> = if __ok {
::std::option::Option::Some(unsafe { __r0.assume_init() })
} else {
::std::option::Option::None
};
$b
}};
( recv($r:expr) -> $v:ident => $b:block $(,)? default => $d:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r), &mut __r0),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, true) };
if __idx == 0 {
let $v: ::std::option::Option<_> = if __ok {
::std::option::Option::Some(unsafe { __r0.assume_init() })
} else {
::std::option::Option::None
};
$b
} else { $d }
}};
( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
recv($r2:expr) -> $v2:ident => $b2:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r1: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::recv_case_of(&($r2), &mut __r1),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, false) };
if __idx == 0 {
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$b1
} else {
let $v2: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r1.assume_init() }) } else { ::std::option::Option::None };
$b2
}
}};
( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
recv($r2:expr) -> $v2:ident => $b2:block $(,)?
default => $d:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r1: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::recv_case_of(&($r2), &mut __r1),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, true) };
if __idx == 0 {
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$b1
} else if __idx == 1 {
let $v2: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r1.assume_init() }) } else { ::std::option::Option::None };
$b2
} else { $d }
}};
( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
recv($r2:expr) -> $v2:ident => $b2:block $(,)?
recv($r3:expr) -> $v3:ident => $b3:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r1: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r2: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::recv_case_of(&($r2), &mut __r1),
$crate::select::recv_case_of(&($r3), &mut __r2),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, false) };
if __idx == 0 {
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$b1
} else if __idx == 1 {
let $v2: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r1.assume_init() }) } else { ::std::option::Option::None };
$b2
} else {
let $v3: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r2.assume_init() }) } else { ::std::option::Option::None };
$b3
}
}};
( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
recv($r2:expr) -> $v2:ident => $b2:block $(,)?
recv($r3:expr) -> $v3:ident => $b3:block $(,)?
default => $d:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r1: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r2: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::recv_case_of(&($r2), &mut __r1),
$crate::select::recv_case_of(&($r3), &mut __r2),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, true) };
if __idx == 0 {
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$b1
} else if __idx == 1 {
let $v2: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r1.assume_init() }) } else { ::std::option::Option::None };
$b2
} else if __idx == 2 {
let $v3: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r2.assume_init() }) } else { ::std::option::Option::None };
$b3
} else { $d }
}};
( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
recv($r2:expr) -> $v2:ident => $b2:block $(,)?
recv($r3:expr) -> $v3:ident => $b3:block $(,)?
recv($r4:expr) -> $v4:ident => $b4:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r1: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r2: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r3: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::recv_case_of(&($r2), &mut __r1),
$crate::select::recv_case_of(&($r3), &mut __r2),
$crate::select::recv_case_of(&($r4), &mut __r3),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, false) };
if __idx == 0 {
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$b1
} else if __idx == 1 {
let $v2: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r1.assume_init() }) } else { ::std::option::Option::None };
$b2
} else if __idx == 2 {
let $v3: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r2.assume_init() }) } else { ::std::option::Option::None };
$b3
} else {
let $v4: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r3.assume_init() }) } else { ::std::option::Option::None };
$b4
}
}};
( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
recv($r2:expr) -> $v2:ident => $b2:block $(,)?
recv($r3:expr) -> $v3:ident => $b3:block $(,)?
recv($r4:expr) -> $v4:ident => $b4:block $(,)?
default => $d:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r1: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r2: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r3: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::recv_case_of(&($r2), &mut __r1),
$crate::select::recv_case_of(&($r3), &mut __r2),
$crate::select::recv_case_of(&($r4), &mut __r3),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, true) };
if __idx == 0 {
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$b1
} else if __idx == 1 {
let $v2: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r1.assume_init() }) } else { ::std::option::Option::None };
$b2
} else if __idx == 2 {
let $v3: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r2.assume_init() }) } else { ::std::option::Option::None };
$b3
} else if __idx == 3 {
let $v4: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r3.assume_init() }) } else { ::std::option::Option::None };
$b4
} else { $d }
}};
( send($tx:expr, $sv:expr) => $sb:block $(,)? default => $d:block $(,)? ) => {{
let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
let mut __sel = ::std::vec![
$crate::select::send_case_of(&($tx), &mut __s0),
];
let (__idx, _ok) = unsafe { $crate::select::selectgo(&mut __sel, true) };
if __idx == 0 {
$sb
} else {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
$d
}
}};
( recv($r1:expr) -> $v1:ident => $rb:block $(,)?
send($tx:expr, $sv:expr) => $sb:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::send_case_of(&($tx), &mut __s0),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, false) };
if __idx == 0 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$rb
} else {
$sb
}
}};
( recv($r1:expr) -> $v1:ident => $rb:block $(,)?
send($tx:expr, $sv:expr) => $sb:block $(,)?
default => $d:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::send_case_of(&($tx), &mut __s0),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, true) };
if __idx == 0 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$rb
} else if __idx == 1 {
$sb
} else {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
$d
}
}};
( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
recv($r2:expr) -> $v2:ident => $b2:block $(,)?
send($tx:expr, $sv:expr) => $sb:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r1: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::recv_case_of(&($r2), &mut __r1),
$crate::select::send_case_of(&($tx), &mut __s0),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, false) };
if __idx == 0 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$b1
} else if __idx == 1 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
let $v2: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r1.assume_init() }) } else { ::std::option::Option::None };
$b2
} else {
$sb
}
}};
( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
recv($r2:expr) -> $v2:ident => $b2:block $(,)?
send($tx:expr, $sv:expr) => $sb:block $(,)?
default => $d:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r1: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::recv_case_of(&($r2), &mut __r1),
$crate::select::send_case_of(&($tx), &mut __s0),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, true) };
if __idx == 0 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$b1
} else if __idx == 1 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
let $v2: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r1.assume_init() }) } else { ::std::option::Option::None };
$b2
} else if __idx == 2 {
$sb
} else {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
$d
}
}};
( recv($r1:expr) -> $v1:ident => $b1:block $(,)?
recv($r2:expr) -> $v2:ident => $b2:block $(,)?
recv($r3:expr) -> $v3:ident => $b3:block $(,)?
send($tx:expr, $sv:expr) => $sb:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r1: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __r2: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv);
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::recv_case_of(&($r2), &mut __r1),
$crate::select::recv_case_of(&($r3), &mut __r2),
$crate::select::send_case_of(&($tx), &mut __s0),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, false) };
if __idx == 0 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$b1
} else if __idx == 1 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
let $v2: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r1.assume_init() }) } else { ::std::option::Option::None };
$b2
} else if __idx == 2 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
let $v3: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r2.assume_init() }) } else { ::std::option::Option::None };
$b3
} else {
$sb
}
}};
( recv($r1:expr) -> $v1:ident => $rb:block $(,)?
send($tx1:expr, $sv1:expr) => $sb1:block $(,)?
send($tx2:expr, $sv2:expr) => $sb2:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv1);
let mut __s1: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv2);
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::send_case_of(&($tx1), &mut __s0),
$crate::select::send_case_of(&($tx2), &mut __s1),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, false) };
if __idx == 0 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0); ::std::mem::ManuallyDrop::drop(&mut __s1) };
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$rb
} else if __idx == 1 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s1) };
$sb1
} else {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
$sb2
}
}};
( recv($r1:expr) -> $v1:ident => $rb:block $(,)?
send($tx1:expr, $sv1:expr) => $sb1:block $(,)?
send($tx2:expr, $sv2:expr) => $sb2:block $(,)?
default => $d:block $(,)? ) => {{
let mut __r0: ::std::mem::MaybeUninit<_> = ::std::mem::MaybeUninit::uninit();
let mut __s0: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv1);
let mut __s1: ::std::mem::ManuallyDrop<_> = ::std::mem::ManuallyDrop::new($sv2);
let mut __sel = ::std::vec![
$crate::select::recv_case_of(&($r1), &mut __r0),
$crate::select::send_case_of(&($tx1), &mut __s0),
$crate::select::send_case_of(&($tx2), &mut __s1),
];
let (__idx, __ok) = unsafe { $crate::select::selectgo(&mut __sel, true) };
if __idx == 0 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0); ::std::mem::ManuallyDrop::drop(&mut __s1) };
let $v1: ::std::option::Option<_> = if __ok { ::std::option::Option::Some(unsafe { __r0.assume_init() }) } else { ::std::option::Option::None };
$rb
} else if __idx == 1 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s1) };
$sb1
} else if __idx == 2 {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0) };
$sb2
} else {
unsafe { ::std::mem::ManuallyDrop::drop(&mut __s0); ::std::mem::ManuallyDrop::drop(&mut __s1) };
$d
}
}};
}
#[cfg(all(test, not(loom)))]
#[allow(unused_assignments)] mod tests {
use crate::chan::chan;
use crate::runtime::sched::run_impl;
use std::sync::atomic::{AtomicI32, Ordering};
use std::sync::Arc;
#[test]
fn go_macro_spawns() {
let count = Arc::new(AtomicI32::new(0));
let c2 = Arc::clone(&count);
run_impl(move || {
go!(move || { c2.fetch_add(1, Ordering::Relaxed); });
for _ in 0..50 { crate::gosched(); }
});
assert_eq!(count.load(Ordering::Acquire), 1);
}
#[test]
fn select_recv_default_data_ready() {
run_impl(|| {
let (tx, rx) = chan::<i32>(1);
tx.send(7);
let mut got = -1_i32;
select! {
recv(rx) -> v => { got = v.unwrap(); }
default => { panic!("default should not fire"); }
}
assert_eq!(got, 7);
});
}
#[test]
fn select_default_when_empty() {
run_impl(|| {
let (_tx, rx) = chan::<i32>(1);
let mut took_default = false;
select! {
recv(rx) -> _v => { panic!("should not recv"); }
default => { took_default = true; }
}
assert!(took_default);
});
}
#[test]
fn select_two_recv_first_ready() {
run_impl(|| {
let (tx1, rx1) = chan::<i32>(1);
let (_tx2, rx2) = chan::<i32>(1);
tx1.send(42);
let mut winner = -1_i32;
select! {
recv(rx1) -> v => { winner = v.unwrap(); }
recv(rx2) -> _v => { panic!("rx2 should not fire"); }
default => {}
}
assert_eq!(winner, 42);
});
}
#[test]
fn select_send_default_space_available() {
run_impl(|| {
let (tx, rx) = chan::<i32>(1);
let mut sent = false;
select! {
send(tx, 99_i32) => { sent = true; }
default => { panic!("default should not fire"); }
}
assert!(sent);
assert_eq!(rx.recv(), Some(99));
});
}
#[test]
fn select_send_default_buffer_full() {
run_impl(|| {
let (tx, rx) = chan::<i32>(1);
tx.send(1); let mut took_default = false;
select! {
send(tx, 2_i32) => { panic!("should not send"); }
default => { took_default = true; }
}
assert!(took_default);
assert_eq!(rx.recv(), Some(1));
});
}
#[test]
fn select_recv_send_default() {
run_impl(|| {
let (tx1, rx1) = chan::<i32>(1);
let (tx2, rx2) = chan::<i32>(1);
tx1.send(10);
let mut recv_val = -1_i32;
let mut send_ok = false;
select! {
recv(rx1) -> v => { recv_val = v.unwrap(); }
send(tx2, 20_i32) => { send_ok = true; }
default => {}
}
assert!(recv_val == 10 || send_ok);
let _ = rx2.try_recv(); });
}
#[test]
fn select_blocking_recv() {
let result = Arc::new(AtomicI32::new(-1));
let r2 = Arc::clone(&result);
run_impl(move || {
let (tx, rx) = chan::<i32>(0);
go!(move || { tx.send(55); });
select! {
recv(rx) -> v => { r2.store(v.unwrap(), Ordering::Relaxed); }
}
});
assert_eq!(result.load(Ordering::Acquire), 55);
}
#[test]
fn select_blocking_two_recv() {
let winner = Arc::new(AtomicI32::new(-1));
let w2 = Arc::clone(&winner);
run_impl(move || {
let (tx1, rx1) = chan::<i32>(0);
let (tx2, rx2) = chan::<i32>(0);
go!(move || { tx1.send(1); });
go!(move || { tx2.send(2); });
select! {
recv(rx1) -> v => { w2.store(v.unwrap(), Ordering::Relaxed); }
recv(rx2) -> v => { w2.store(v.unwrap(), Ordering::Relaxed); }
}
});
let w = winner.load(Ordering::Acquire);
assert!(w == 1 || w == 2, "winner should be 1 or 2, got {w}");
}
#[test]
fn select_blocking_recv_send() {
let recv_val = Arc::new(AtomicI32::new(-1));
let rv2 = Arc::clone(&recv_val);
run_impl(move || {
let (tx1, rx1) = chan::<i32>(0); let (tx2, rx2) = chan::<i32>(0); go!(move || { tx1.send(77); });
go!(move || {
crate::gosched();
let _ = rx2.recv();
});
select! {
recv(rx1) -> v => { rv2.store(v.unwrap(), Ordering::Relaxed); }
send(tx2, 99_i32) => {}
}
});
let v = recv_val.load(Ordering::Acquire);
assert!(v == 77 || v == -1, "unexpected value {v}");
}
#[test]
fn select_recv_closed_yields_none() {
run_impl(|| {
let (tx, rx) = chan::<i32>(0);
tx.close();
let mut ok_flag = true;
select! {
recv(rx) -> v => { ok_flag = v.is_some(); }
}
assert!(!ok_flag, "should be None for closed channel");
});
}
}