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
runtime: merge multi & single threaded runtimes #1716
Conversation
Simplify Tokio's runtime construct by combining both Runtime variants into a single type. The execution style can be controlled by a configuration setting on `Builder`. The implication of this change is that there is no longer any way to spawn `!Send` futures. This, however, is a temporary limitation. A different strategy will be employed for supporting `!Send` futures. Included in this patch is a rework of `task::JoinHandle` to support using this type from both the thread-pool and current-thread executors.
@@ -103,7 +106,7 @@ impl<T: Future> Core<T> { | |||
self.stage = Stage::Consumed | |||
} | |||
|
|||
pub(super) fn poll<S>(&mut self, header: &Header<S>) -> Poll<T::Output> | |||
pub(super) fn poll<S>(&mut self, header: &Header) -> Poll<T::Output> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change worries me, almost to the point that it should be marked as unsafe
. Now, this basically allows doing an arbitrary pointer cast in safe code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it is any more unsafe than it was before, but I can mark it as such.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have a change in mind?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before you had to have a Header<S>
to go with the poll
. Now, you no longer need to have a Header<S>
to "prove" that you can use that S
(before the proof was also arguably pretty weak). It's tricky, because I also agree with you argument from Discord that unsafe fn
makes the whole function body an unsafe block, which isn't great. I think I'd be okay with this being discussed in a doc block for the fn instead.
let around_reactor_handles = reactor_handles.clone(); | ||
let around_timer_handles = timer_handles.clone(); | ||
// Blocking pool | ||
let blocking_pool = PoolWaiter::from(Pool::default()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem right. The ThreadPool
builder already creates a blocking pool, and stores a PoolWaiter
internally. With this you'll end up with two pools.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct. This was done intentionally as a transitional step. Fixing this "right" will take some restructuring of thread_pool
that i want to punt to a follow up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, seems fine as long as it'll be fixed before the next release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe leave a TODO:
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this looks good, though I left some notes about unsafety that I think should be documented better even if we're going to move things around later, and about what I believe to be a bug where a threadpool runtime ends up with two blocking pools.
@carllerche can you share details on the "different strategy for supporting |
We can write something like let mut rt = Runtime::new();
let local_tasks = LocalTaskSet::new();
local_tasks.spawn(async { ... });
rt.block_on(local_tasks); Not exactly that, but something like that should work. |
Maybe we can provide a |
## Motivation In earlier versions of `tokio`, the `current_thread::Runtime` type could be used to run `!Send` futures. However, PR #1716 merged the current-thread and threadpool runtimes into a single type, which can no longer run `!Send` futures. There is still a need in some cases to support futures that don't implement `Send`, and the `tokio-compat` crate requires this in order to provide APIs that existed in `tokio` 0.1. ## Solution This branch implements the API described by @carllerche in #1716 (comment). It adds a new `LocalSet` type and `spawn_local` function to `tokio::task`. The `LocalSet` type is used to group together a set of tasks which must run on the same thread and don't implement `Send`. These are available when a new "rt-util" feature flag is enabled. Currently, the local task set is run by passing it a reference to a `Runtime` and a future to `block_on`. In the future, we may also want to investigate allowing spawned futures to construct their own local task sets, which would be executed on the worker that the future is executing on. In order to implement the new API, I've made some internal changes to the `task` module and `Schedule` trait to support scheduling both `Send` and `!Send` futures. Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Simplify Tokio's runtime construct by combining both Runtime variants
into a single type. The execution style can be controlled by a
configuration setting on
Builder
.The implication of this change is that there is no longer any way to
spawn
!Send
futures. This, however, is a temporary limitation. Adifferent strategy will be employed for supporting
!Send
futures.Included in this patch is a rework of
task::JoinHandle
to supportusing this type from both the thread-pool and current-thread executors.