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

[tracking] spawning non-Send tasks #457

Open
yoshuawuyts opened this issue Nov 5, 2019 · 6 comments
Open

[tracking] spawning non-Send tasks #457

yoshuawuyts opened this issue Nov 5, 2019 · 6 comments
Labels
api design Open design questions

Comments

@yoshuawuyts
Copy link
Contributor

In #251 we discussed the option of adding a task::spawn_local method, similar to @alexcrichton's design of spawn_local in wasm-bindgen-futures. This is a tracking issue for that design to get feedback on whether people would want this, and how we would go about implementing this.

I'd imagine we would introduce a new API; task::spawn_local which takes a non-Send Future, and ensures it's polled to completion on the current thread. This would interact seamlessly with task::yield_now out of the box.

Example

use async_std::task;

task::spawn(async move {
    task::sleep(Duration::from_secs(1)).await;

    // The async code in this block will never be moved between threads.
    task::spawn_local(async {
        task::sleep(Duration::from_secs(1)).await;
    }).await;
}).await;

Note: task::sleep does implement Send, but it was an easy example to use.

@oblique
Copy link

oblique commented Dec 1, 2019

tokio 0.2.2 added spawn_local API. Their implementation is interesting: https://docs.rs/tokio/0.2.2/tokio/task/struct.LocalSet.html

Example:

use std::rc::Rc;
use tokio::task;

let unsend_data = Rc::new("my unsend data...");

let mut rt = Runtime::new().unwrap();
// Construct a local task set that can run `!Send` futures.
let local = task::LocalSet::new();

// Run the local task group.
local.block_on(&mut rt, async move {
    let unsend_data = unsend_data.clone();
    // `spawn_local` ensures that the future is spawned on the local
    // task group.
    task::spawn_local(async move {
        println!("{}", unsend_data);
        // ...
    }).await.unwrap();
});

@skade
Copy link
Collaborator

skade commented Dec 3, 2019

I'm not sure if I like that API. That seems to push the task group into a global? What happens when two local groups nest?

@oblique
Copy link

oblique commented Dec 3, 2019

I didn't experiment a lot with it, but as I understood you can not have nested groups, because a group is scheduled by block_on.

@jimblandy
Copy link
Contributor

jimblandy commented Jun 15, 2020

I'd like to put in a vote for this. As I said on Discord:

Aside from being handy for non-Send futures, I found it helpful in writing an explanation of how asynchronous programming works, because it lets me show the single-threaded case before introducing thread pools. The point of async is to let threads not get pinned down by blocking I/O, and it's easier to make a clear demonstration of how that works without having threads complicate the picture. The reader can see how one thread's resources are now serving any number of different async tasks. Then the thread pool can be presented as an optimization. "Oh, by the way, you can also just spawn stuff onto a thread pool. This is mostly how it's done."

@ghost
Copy link

ghost commented Jun 22, 2020

There is now unstable function spawn_local(): https://docs.rs/async-std/1.6.2/async_std/task/fn.spawn_local.html

It is unfortunately not marked as unstable in docs because this:

    #[cfg(feature = "default")]
    pub use spawn_local::spawn_local;

needs to be changed to:

    #[cfg(feature = "default")]
    #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
    pub use spawn_local::spawn_local;

@jimblandy
Copy link
Contributor

Right - I'm saying, I would be delighted if this were stabilized. :)

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

No branches or pull requests

4 participants