#[macro_use]
extern crate log;
extern crate env_logger;
extern crate num_cpus;
extern crate futures;
extern crate ruyi;
use std::thread;
use futures::{future, Future, Stream};
use ruyi::stream::IntoStream;
use ruyi::channel::spsc;
use ruyi::io;
use ruyi::net::{TcpStream, TcpListener};
use ruyi::reactor::{self, IntoTask};
fn echo(sock: TcpStream) {
let task = future::result(sock.set_nodelay(true))
.and_then(|_| {
let (r, w) = io::split(sock);
io::copy(r, w)
})
.map_err(|e| error!("{}", e))
.into_task();
reactor::spawn(task);
}
fn main() {
env_logger::init().unwrap();
let n = num_cpus::get();
let mask = n - 1;
let mut workers = Vec::with_capacity(n);
for _ in 0..n {
let (tx, rx) = spsc::sync_channel(512).unwrap();
thread::spawn(move || {
reactor::run(rx.into_stream().for_each(|s| Ok(echo(s)))).unwrap()
});
workers.push(tx);
}
let mut i = 0;
let acceptor = TcpListener::builder()
.port(10007)
.build()
.unwrap()
.incoming()
.for_each(|(sock, _)| {
workers[i].try_send(sock).unwrap();
i = (i + 1) & mask;
Ok(())
});
reactor::run(acceptor).unwrap();
}