Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

It's not clear how to use Executor instead of smol::spawn #223

Open
detly opened this issue Feb 8, 2021 · 1 comment
Open

It's not clear how to use Executor instead of smol::spawn #223

detly opened this issue Feb 8, 2021 · 1 comment

Comments

@detly
Copy link

detly commented Feb 8, 2021

Here's a demo of using spawn() to run some timeouts:

use ctrlc;
use smol::channel;
use smol::Timer;
use std::time::Duration;

async fn wait_for_signal<T>(receiver: &channel::Receiver<T>) {
    // Receive a message that indicates the Ctrl-C signal occurred.
    receiver.recv().await.ok();

    println!("Signal received");
}

async fn wait_for_timeout(seconds: u64, text: &str) {
    Timer::after(Duration::from_secs(seconds)).await;
    println!("Timeout: {}", text);
}

fn main() {
    // Set a handler that sends a message through a channel.
    let (sender, ctrl_c) = channel::unbounded();

    let handle = move || {
        sender.try_send(()).ok();
    };

    ctrlc::set_handler(handle).unwrap();

    println!("Waiting for Ctrl-C...");

    smol::block_on(async {
        smol::spawn(wait_for_timeout(4, "four")).detach();
        smol::spawn(wait_for_timeout(3, "three")).detach();
        smol::spawn(wait_for_timeout(2, "two")).detach();
        smol::spawn(wait_for_timeout(1, "one")).detach();
        wait_for_signal(&ctrl_c).await;
    })
}

It should print:

one
two
three
four

And exit (early, even) if you press Ctrl+C.

The docs for smol::spawn() say:

It is included in this library for convenience when writing unit tests and small programs, but it is otherwise more advisable to create your own Executor.

So I tried replacing smol::spawn with my own executor:

use std::time::Duration;

use ctrlc;
use smol::{channel, Executor, Timer};

async fn wait_for_signal<T>(receiver: &channel::Receiver<T>) {
    // Receive a message that indicates the Ctrl-C signal occurred.
    receiver.recv().await.ok();

    println!("Signal received");
}

async fn wait_for_timeout(seconds: u64, text: &str) {
    Timer::after(Duration::from_secs(seconds)).await;
    println!("Timeout: {}", text);
}

fn main() {
    // Set a handler that sends a message through a channel.
    let (sender, ctrl_c) = channel::unbounded();

    let handle = move || {
        sender.try_send(()).ok();
    };

    ctrlc::set_handler(handle).unwrap();

    println!("Waiting for Ctrl-C...");

    smol::block_on(async {
        let ex = Executor::new();
        ex.spawn(wait_for_timeout(4, "four")).detach();
        ex.spawn(wait_for_timeout(3, "three")).detach();
        ex.spawn(wait_for_timeout(2, "two")).detach();
        ex.spawn(wait_for_timeout(1, "one")).detach();
        wait_for_signal(&ctrl_c).await;
    })
}

Now nothing is printed. Ctrl+C still works. I assume there is something else I have to do to get the executor working, but it's not documented what. The docs for Executor use something called easy_parallel which isn't part of smol.

System: rustc 1.49, Ubuntu 20.10, smol 1.2.5.

@pkorotkov
Copy link

You just forgot to run the executor on the future with timeouts. This should work:

...
let ex = Executor::new();
smol::block_on(ex.run(async {
    ex.spawn(wait_for_timeout(4, "four")).detach();
    ex.spawn(wait_for_timeout(3, "three")).detach();
    ex.spawn(wait_for_timeout(2, "two")).detach();
    ex.spawn(wait_for_timeout(1, "one")).detach();
    wait_for_signal(&ctrl_c).await;
}))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants