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?
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?
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?
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().
@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.
Btw: I figured out through this issue that GLOBAL_POOL is actually not used anywhere anymore, and should be removed.
@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().
block_on doesn't use LocalPool. It executes the future on the stack. If you need spawning functionality, create and use a LocalPool explicitly.
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.
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?).
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
Most helpful comment
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