I’d like to make multi-threading http server, and I found new released tokio-runtime https://tokio.rs/blog/2018-03-tokio-runtime/ whick has work-stealing based thread pool for scheduling and executing the application’s code. I think it’s very nice.
I guess the future representing hyper::Response does not implement Send
trait and it’s not thread safe. How can I integrate with hyper?
My code is like below:
struct RealService;
impl Service for RealService {
type Request = hyper::Request;
type Response = hyper::Response;
type Error = hyper::Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
fn call(&self, _req: Self::Request) -> Self::Future { ... }
fn main() {
....
let listener = TcpListener::bind(&addr).unwrap();
let server = listener.incoming().for_each(|stream| {
let future = Http::<hyper::Chunk>::new()
.serve_connection( stream, RealService)
.map_err(|e| {
std::io::Error::new( std::io::ErrorKind::Other, format!("Failed to serve connection: {}", e))
});
tokio::spawn(future);
Ok(())
});
tokio::run(server);
}
I got error like below:
error[E0271]: type mismatch resolving `<[closure@src/main.rs:170:22: 172:14] as std::ops::FnOnce<(hyper::Error,)>>::Output == ()`
--> src/main.rs:173:9
|
173 | tokio::spawn(future);
| ^^^^^^^^^^^^ expected struct `std::io::Error`, found ()
|
= note: expected type `std::io::Error`
found type `()`
= note: required because of the requirements on the impl of `futures::Future` for `futures::MapErr<hyper::server::Connection<tokio::net::TcpStream, RealService>, [closure@src/main.rs:170:22: 172:14]>`
= note: required by `tokio::spawn`
error[E0277]: the trait bound `futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static: std::marker::Send` is not satisfied
--> src/main.rs:173:9
|
173 | tokio::spawn(future);
| ^^^^^^^^^^^^ `futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static>`
= note: required because it appears within the type `std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static>`
= note: required because it appears within the type `std::option::Option<std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static>>`
= note: required because it appears within the type `hyper::proto::h1::dispatch::Server<RealService>`
= note: required because it appears within the type `hyper::proto::h1::dispatch::Dispatcher<hyper::proto::h1::dispatch::Server<RealService>, hyper::Body, tokio::net::TcpStream, hyper::Chunk, hyper::proto::h1::role::Server<hyper::proto::h1::role::YesUpgrades>>`
= note: required because it appears within the type `hyper::server::Connection<tokio::net::TcpStream, RealService>`
= note: required because it appears within the type `futures::MapErr<hyper::server::Connection<tokio::net::TcpStream, RealService>, [closure@src/main.rs:170:22: 172:14]>`
= note: required by `tokio::spawn`
error[E0271]: type mismatch resolving `<futures::stream::ForEach<tokio::net::Incoming, [closure@src/main.rs:159:47: 175:6 handle:_, pool:_], std::result::Result<(), std::io::Error>> as futures::Future>::Error == ()`
--> src/main.rs:176:5
|
176 | tokio::run(server);
| ^^^^^^^^^^ expected struct `std::io::Error`, found ()
|
= note: expected type `std::io::Error`
found type `()`
= note: required by `tokio::run`
error: aborting due to 3 previous errors