#![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
extern crate rand;
extern crate session_types;
use session_types::*;
use std::thread::spawn;
use rand::random;
type Server = Recv<u8, Choose<Send<u8, Eps>, Eps>>;
type Client = <Server as HasDual>::Dual;
fn server_handler(c: Chan<(), Server>) {
let (c, n) = c.recv();
match n.checked_add(42) {
Some(n) => c.sel1().send(n).close(),
None => c.sel2().close(),
}
}
type ChanChan = Offer<Eps, Recv<Chan<(), Server>, Var<Z>>>;
fn server(rx: Chan<(), Rec<ChanChan>>) -> usize {
let mut count = 0;
let mut c = rx.enter();
loop {
c = offer! { c,
Quit => {
c.close();
break
},
NewChan => {
let (c, new_chan) = c.recv();
spawn(move || server_handler(new_chan));
count += 1;
c.zero()
}
}
}
count
}
fn client_handler(c: Chan<(), Client>) {
let n = random();
match c.send(n).offer() {
Left(c) => {
let (c, n2) = c.recv();
c.close();
println!("{} + 42 = {}", n, n2);
}
Right(c) => {
c.close();
println!("{} + 42 is an overflow :(", n);
}
}
}
fn main() {
let (tx, rx) = session_channel();
let n: u8 = random();
let mut tx = tx.enter();
println!("Spawning {} clients", n);
let mut ts = vec![];
for _ in 0..n {
let (c1, c2) = session_channel();
ts.push(spawn(move || {
client_handler(c2);
}));
tx = tx.sel2().send(c1).zero();
}
tx.sel1().close();
let count = server(rx);
for t in ts {
let _ = t.join();
}
println!("Handled {} connections", count);
}