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

rt: internally split Handle into two structs #4629

Merged
merged 2 commits into from Apr 20, 2022
Merged

Conversation

carllerche
Copy link
Member

Previously, runtime::Handle was a single struct composed of the
internal handles for each runtime component. This patch splits the
Handle struct into a HandleInner which contains everything
except the task scheduler handle. Now, HandleInner is passed to
the task scheduler during creation and the task scheduler is responsible
for storing it. Handle only needs to hold the scheduler handle and
can access the rest of the component handles by querying the task
scheduler.

The motivation for this change is it now enables the multi-threaded
scheduler to have direct access to the blocking spawner handle.
Previously, when spawning a new thread, the multi-threaded scheduler had
to access the blocking spawner by accessing a thread-local variable.
Now, in theory, the multi-threaded scheduler can use HandleInner
directly. However, this change hasn't been done in this PR yet.

Also, now the Handle struct is much smaller.

This change is intended to make it easier for the multi-threaded
scheduler to shutdown idle threads and respawn them on demand.

Previously, `runtime::Handle` was a single struct composed of the
internal handles for each runtime component. This patch splits the
`Handle` struct into a `HandleInner` which contains everything
**except** the task scheduler handle. Now, `HandleInner` is passed to
the task scheduler during creation and the task scheduler is responsible
for storing it. `Handle` only  needs to hold the scheduler handle and
can access the rest of the component handles by querying the task
scheduler.

The motivation for this change is it now enables the multi-threaded
scheduler to have direct access to the blocking spawner handle.
Previously, when spawning a new thread, the multi-threaded scheduler had
to access the blocking spawner by accessing a thread-local variable.
Now, in theory, the multi-threaded scheduler can use `HandleInner`
directly. However, this change hasn't been done in this PR yet.

Also, now the `Handle` struct is much smaller.

This change is intended to make it easier for the multi-threaded
scheduler to shutdown idle threads and respawn them on demand.
@carllerche carllerche added C-maintenance Category: PRs that clean code up or issues documenting cleanup. A-tokio Area: The main tokio crate M-runtime Module: tokio/runtime R-loom Run loom tests on this PR labels Apr 20, 2022
@@ -220,7 +220,7 @@ impl fmt::Debug for BlockingPool {
// ===== impl Spawner =====

impl Spawner {
pub(crate) fn spawn(&self, task: Task, rt: &Handle) -> Result<(), ()> {
pub(crate) fn spawn(&self, task: Task, rt: &dyn ToHandle) -> Result<(), ()> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dyn because it isn't really performance critical so 🤷 less code gen.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

less codegen is good, but there's only two types that implement this, and a trait object ptr is an extra word on the stack vs a &impl ToHandle...honestly hard to say which is better, i guess. seems fine!

Copy link
Member

@hawkw hawkw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall, this seems fine to me! i left some nitpicky comments you can feel free to disregard.

i'm not the biggest fan of the HandleInner name, but i'm not sure if there's anything better --- i suggested Resources, since it's mostly resource drivers, but i'm not sure if that's a big improvement 🤷‍♀️

tokio/src/runtime/handle.rs Show resolved Hide resolved
tokio/src/runtime/handle.rs Show resolved Hide resolved
tokio/src/runtime/basic_scheduler.rs Show resolved Hide resolved
@@ -220,7 +220,7 @@ impl fmt::Debug for BlockingPool {
// ===== impl Spawner =====

impl Spawner {
pub(crate) fn spawn(&self, task: Task, rt: &Handle) -> Result<(), ()> {
pub(crate) fn spawn(&self, task: Task, rt: &dyn ToHandle) -> Result<(), ()> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

less codegen is good, but there's only two types that implement this, and a trait object ptr is an extra word on the stack vs a &impl ToHandle...honestly hard to say which is better, i guess. seems fine!

Copy link
Contributor

@Darksonn Darksonn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine.

@carllerche carllerche merged commit 911a0ef into master Apr 20, 2022
@carllerche carllerche deleted the misc-rt-refactor branch April 20, 2022 19:56
carllerche added a commit that referenced this pull request Sep 13, 2022
In an earlier PR (#4629), driver handles were moved into the scheduler
handle (`Spawner`). This was done to let the multi-threaded scheduler
have direct access to the thread pool spawner.

However, we are now working on a greater decoupling of the runtime
internals. All drivers and schedulers will be peers, stored in a single
thread-local variable, and the scheduler will be passed the full
runtime::Handle. This will achieve the original goal of giving the
scheduler access to the thread-pool while also (hopefully) simplifying
other aspects of the code.
carllerche added a commit that referenced this pull request Sep 13, 2022
In an earlier PR (#4629), driver handles were moved into the scheduler
handle (`Spawner`). This was done to let the multi-threaded scheduler
have direct access to the thread pool spawner.

However, we are now working on a greater decoupling of the runtime
internals. All drivers and schedulers will be peers, stored in a single
thread-local variable, and the scheduler will be passed the full
runtime::Handle. This will achieve the original goal of giving the
scheduler access to the thread-pool while also (hopefully) simplifying
other aspects of the code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate C-maintenance Category: PRs that clean code up or issues documenting cleanup. M-runtime Module: tokio/runtime R-loom Run loom tests on this PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants