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

executor::spawn() in futures-preview 0.3 #1421

Open
ebkalderon opened this issue Jan 16, 2019 · 10 comments
Open

executor::spawn() in futures-preview 0.3 #1421

ebkalderon opened this issue Jan 16, 2019 · 10 comments
Labels
A-executor Area: futures::executor C-feature-request

Comments

@ebkalderon
Copy link
Contributor

I noticed that futures-preview 0.3.0 provides its own default global threadpool, similar to tokio 0.1, exposed through the executor::block_on() and executor::block_on_stream() functions. Would it be possible to add an executor::spawn() function for spawning futures on the pool as well?

@ebkalderon ebkalderon changed the title executor::spawn() in futures-preview 0.3.0 executor::spawn() in futures-preview 0.3 Jan 16, 2019
@ebkalderon
Copy link
Contributor Author

I would be interested in preparing a PR for this, but I might need a bit of mentoring. I've tried adding an fn spawn() to futures-executor/src/local_pool.rs, but I can't seem to spawn anything from GLOBAL_POOL as Spawn::spawn_obj() and SpawnExt::spawn() both require &mut self. How should I proceed from here?

@ebkalderon
Copy link
Contributor Author

Using tokio-executor as a reference, the default executor is stored in a thread-local Cell which allows the executor to be borrowed mutably at runtime so that spawn() can be called on it. Not sure if a similar approach can be taken here with GLOBAL_POOL.

Another tangential point of interest is that the global block_on_stream() appears to not use GLOBAL_POOL, but rather it creates a new LocalPool every time Iterator::next() is called (source). Also, the global block_on() doesn't appear to use GLOBAL_POOL either, opting to use enter() through run_executor() (source). Are both of these intentional?

@ebkalderon
Copy link
Contributor Author

Pinging @Matthias247 and @cramertj. Is there any reason why block_on() was changed to no longer use the global pool in this commit? Is the GLOBAL_POOL even used anywhere? I can't find any way to spawn tasks onto the same pool used by block_on().

@Matthias247
Copy link
Contributor

@ebkalderon The comment change in that commit might be misleading, and change it from "incorrect" to "slightly less incorrect". block_on didn't use a GLOBAL_POOL or any other kind of global executor before. It set up a LocalPool, spawned the future in it, and run it to completion. This however had some overhead when we only want to run a single future, since we can do this completely without an executor, and just driving the future on the stack to completion. That is what the change does. After the change there is no thread-local executor either, only the Waker that is passed to the Future uses the thread handle to unblock the executor when necessary.

Regarding the original question: Spawning futures on LocalPool should be already possible. Check the spawner() method on it. If you require that functionality you need to use LocalPool::run_until instead of block_on, but block_on is simply there for more trivial use-cases.

@Matthias247
Copy link
Contributor

Btw: I figured out through this issue that GLOBAL_POOL is actually not used anywhere anymore, and should be removed.

@ebkalderon
Copy link
Contributor Author

@Matthias247 Thanks for clearing up a few things! I already noticed that it's already possible to spawn futures on a LocalPool, but I can't seem to find a way to create a global executor::spawn() function that spawns futures onto the LocalPool used by executor::block_on().

@Matthias247
Copy link
Contributor

block_on doesn't use LocalPool. It executes the future on the stack. If you need spawning functionality, create and use a LocalPool explicitly.

@ebkalderon
Copy link
Contributor Author

ebkalderon commented Jan 28, 2019

That's a shame. So if I have a future that needs to spawn a task from within itself, I need to thread in a T: SpawnExt everywhere? Seems like a pretty big downgrade in ergonomics to me.

I'm working around this currently by using .compat() and tokio::run()/tokio::spawn() specifically for the sake of having an ergonomic global threadpool, but it would be very nice to have this natively available in futures 0.3.0.

@Nemo157
Copy link
Member

Nemo157 commented Jan 28, 2019

It's likely that there will be a crate providing a TLS based spawner for users that want this convenience, hopefully even a cross-executor one where libraries can use the convenient API and it just gets routed to whichever concrete executor is actually running. (EDIT: for prior art in a design like this see slog-scope)

That might be a good reason to not provide a concrete global threadpool here, IMO it would be better for the ecosystem for most users to use a crate dedicated to providing an abstract global spawner that futures-executor and tokio both hook their concrete implementations into (maybe this crate should be prototyped here though?).

@Nemo157
Copy link
Member

Nemo157 commented Apr 7, 2019

I've just thrown together a basic generic TLS based spawner just to make sure the idea works, I'll try and polish this up and put it onto crates.io sometime soon: https://github.com/Nemo157/futures-global-spawner/blob/master/tests/smoke.rs

@taiki-e taiki-e added the A-executor Area: futures::executor label Dec 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-executor Area: futures::executor C-feature-request
Projects
None yet
Development

No branches or pull requests

5 participants