#![allow(
clippy::type_complexity,
clippy::too_many_arguments,
clippy::large_enum_variant
)]
use mpstthree::binary::close::close;
use mpstthree::binary::fork::fork_with_thread_id;
use mpstthree::binary::recv::recv;
use mpstthree::binary::send::send;
use mpstthree::binary::struct_trait::{end::End, recv::Recv, send::Send, session::Session};
use mpstthree::{choose, offer};
use std::error::Error;
use std::thread::{spawn, JoinHandle};
enum BinaryA {
More(Recv<(), Send<(), RecursA>>),
Done(End),
}
type RecursA = Recv<BinaryA, End>;
fn binary_a_to_b(s: RecursA) -> Result<(), Box<dyn Error>> {
offer!(s, {
BinaryA::Done(s) => {
close(s)
},
BinaryA::More(s) => {
let (_, s) = recv(s)?;
let s = send((), s);
binary_a_to_b(s)
},
})
}
type RecursB = <RecursA as Session>::Dual;
fn binary_b_to_a(s: Send<(), Recv<(), RecursB>>) -> Result<RecursB, Box<dyn Error>> {
let s = send((), s);
let (_, s) = recv(s)?;
Ok(s)
}
fn main() {
let mut threads = Vec::new();
let mut sessions = Vec::new();
for _ in 0..28 {
let (thread, s): (JoinHandle<()>, RecursB) = fork_with_thread_id(binary_a_to_b);
threads.push(thread);
sessions.push(s);
}
let main = spawn(move || {
for _ in 0..100 {
sessions = sessions
.into_iter()
.map(|s| binary_b_to_a(choose!(BinaryA::More, s)).unwrap())
.collect::<Vec<_>>();
}
sessions
.into_iter()
.for_each(|s| close(choose!(BinaryA::Done, s)).unwrap());
threads
.into_iter()
.for_each(|elt| assert!(elt.join().is_ok()));
});
assert!(main.join().is_ok());
}