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
Conversation
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.
@@ -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<(), ()> { |
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.
dyn
because it isn't really performance critical so 🤷 less code gen.
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.
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!
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 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 🤷♀️
@@ -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<(), ()> { |
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.
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!
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.
Seems fine.
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.
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.
Previously,
runtime::Handle
was a single struct composed of theinternal handles for each runtime component. This patch splits the
Handle
struct into aHandleInner
which contains everythingexcept the task scheduler handle. Now,
HandleInner
is passed tothe task scheduler during creation and the task scheduler is responsible
for storing it.
Handle
only needs to hold the scheduler handle andcan 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.