qweruiop
qweruiop

Reputation: 3266

Why are spawned futures not executed by tokio_core::reactor::Core?

extern crate tokio; // 0.1.8

use tokio::prelude::*;

fn create_a_future(x: u8) -> Box<Future<Item = (), Error = ()>> {
    Box::new(futures::future::ok(2).and_then(|a| {
        println!("{}", a);
        Ok(())
    }))
}

fn main() {
    let mut eloop = tokio_core::reactor::Core::new().unwrap();
    let handle = eloop.handle();

    for x in 0..10 {
        let f = create_a_future(x);
        handle.spawn(f);
    }
}

I expect this to print to stdout, but it didn't happen. Am I using spawn in the wrong way?

Upvotes: 0

Views: 1025

Answers (1)

Shepmaster
Shepmaster

Reputation: 431379

As already mentioned in the comments, you are setting up a bunch of computation but never running any of it. Like iterators, you can think of futures as lazy. The compiler normally tells you about this when you directly create a future but never use it. Here, you are spawning the futures, so you don't get that warning, but nothing ever drives the Tokio reactor.

In many cases, you have a specific future you want to run, and you'd drive the reactor until that completes. In other cases, your run the reactor "forever", endlessly handling new work.

In this case, you can use Core::turn:

fn main() {
    let mut eloop = tokio_core::reactor::Core::new().unwrap();
    let handle = eloop.handle();

    for x in 0..10 {
        let f = create_a_future(x);
        handle.spawn(f);
    }

    eloop.run(None);
}

eloop.turn(None);

-> Box<Future<Item = (), Error = ()>>

You don't need to (and probably shouldn't) do this in modern Rust. It's preferred to return an anonymous type:

fn create_a_future() -> impl Future<Item = (), Error = ()> {
    futures::future::ok(2).and_then(|a| {
        println!("{}", a);
        Ok(())
    })
}
 tokio_core::reactor::Core

My understanding is that this level of Tokio is reserved for more complicated setups. Many people can just use tokio::run and tokio::spawn:

fn main() {
    tokio::run(futures::lazy(|| {
        for _ in 0..10 {
            tokio::spawn(create_a_future());
        }
        Ok(())
    }))
}

Upvotes: 1

Related Questions