rt: add optional per-task user data exposed to hooks - #7688
Open
LloydW93 wants to merge 8 commits into
Open
Conversation
In tokio-rs#7197 and tokio-rs#7306, improved capabilities of task hooks were discussed and an initial implementation provided. However, that involved quite wide-reaching changes, modifying every spawn site and introducing a global map to provide the full inheritance capabilities originally proposed. This is the first part of a more basic version where we only use the existing hooks and provide the capabilities for consumers to be able to implement more complex relationships if needed, just adding an optional user data ref to the task header. The additional data is 2*usize, and is not enough to result in the struct requiring more than one cache line. A user is now able to use their own global map to build inheritance capabilities if needed, and this would be made simpler by also exposing the current task user data to the on_task_spawn hook, which a followup will look to do.
…ast helpers It's nicer syntactically to be able to directly pass whatever type and have tokio deal with how the user data is stored, but it makes on_task_spawn have a horrible wrapper function, so just take that out to keep things simpler and nicer for now.
Darksonn
reviewed
Oct 20, 2025
ADD-SP
reviewed
Oct 20, 2025
Member
|
Yes, it's useful with an overview of the public API being added. |
scotchmist
reviewed
Oct 22, 2025
martin-g
reviewed
Oct 23, 2025
Addressing PR comments: - UserData is now `Send + Sync` when using `rt-multi-thread` - The runtime::Builder docs now signpost to the `task::Builder` API for setting user data on a per-task basis rather than through the global task spawn hook - Updated `task::Builder::data` to not consume self to align with `task::Builder::name` behaviour
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
In #7197 and #7306, improved capabilities of task hooks were discussed and an initial implementation provided. However, that involved quite wide-reaching changes, modifying every spawn site and introducing a global map to provide the full inheritance capabilities originally proposed.
This is the first part of a more basic version where we only use the existing hooks and provide the capabilities for consumers to be able to implement more complex relationships if needed, just adding an optional user data ref to the task header.
The additional data is 2*usize, and is not enough to result in the struct requiring more than one cache line.
A user is now able to use their own global map to build inheritance capabilities if needed, and this would be made simpler by also exposing the current task user data to the on_task_spawn hook, which a followup will look to do.
Motivation
See #7306. The intent is to allow persistence of context for across evaluations of task hooks, which is potentially also accessible by the task itself.
For example you may want to just know how many poll()s a task took, metrics of each poll duration (or between each poll duration), or to set some flag to track what a task was about to do (e.g. read some bytes from a socket) to identify what a task has become blocked on.
Solution
By adding a fat pointer for task metadata, consumers are able to attack a reference to data of an arbitrary type for a task, which we then expose in hooks. This metadata can be configured at task spawn time, also allowing consumers to maintain some shared reference between the hooks and the task's future itself to maintain knowledge of what is going on.