futurify 0.1.1

Convert your sync functions into non-blocking thread futures
Documentation

Futurify

ActionsStatus Crates.io

Convert your sync functions into non-blocking thread futures.

When to use it

This is just an example to illustrate when this library could be useful.

Imagine you're creating an actix-web API and you have and endpoint that has to execute a very long synchronous task.

Normally, most of the modern crates will provide some async variants but still there are some of them that only provide a sync implementation.

This could be problematic as this endpoint could block the main thread and avoid other endpoints from being executed.

Take a look at this code:

use actix_web::{web, App, Error, HttpResponse, HttpServer, Responder};
use futures::{Async, Future, Poll};

fn index_async() -> impl Future<Item = impl Responder, Error = Error> {
    futures::future::ok("Hello world")
}

fn index_async_blocking() -> impl Future<Item = impl Responder, Error = Error> {
    futures::lazy(|| {
        std::thread::sleep(Duration::from_secs(5));
        futures::future::ok("Hello blocking world")
    })
}

fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/", web::get().to_async(index_async))
            .route("/blocking", web::get().to_async(index_async_blocking))
    })
    .workers(1)
    .bind("localhost:8080")?
    .run()
}

If you try to get localhost:8080/blocking and then get localhost:8080, you will be able to see that you won't get any response until the blocking endpoint has returned.

With just a slight change we could get rid of this issue:

fn index_async_non_blocking() -> impl Future<Item = impl Responder, Error = Error> {
    futurify::wrap(|| {
        std::thread::sleep(Duration::from_secs(5));
        "Hello blocking world"
    })
}

fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/", web::get().to_async(index_async))
            .route("/blocking", web::get().to_async(index_async_blocking))
            .route("/non-blocking", web::get().to_async(index_async_non_blocking))
    })
    .workers(1)
    .bind("localhost:8080")?
    .run()
}

Just wrap a closure with futurify::wrap and you'll get a futures 0.1 future ready to be polled.