-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Tracking Issue for waker_getters
#96992
Comments
Maybe we could stabilize this? Note sure what I could do next. @rust-lang/libs-api |
I am concerned about |
It returns |
Then I'm afraid that I don't understand how |
It's effectively
In case of passing through FFI, we need do Note that the Footnotes
|
I feel that a better story is needed for getting a impl Waker {
unsafe fn with_raw<T>(raw: &RawWaker, f: impl FnOnce(&Waker) -> T) -> T;
} Also I do think that we should add |
This API seems to be the only choice since we cannot let temporary Also this API is more like a helper, which is able to be implemented outside std ( |
I think it should be inlcuded as the counterpart to For tokio, it seems to only be used here. It should be easy to refactor that to use |
@Amanieu impl Waker {
pub unsafe fn from_raw_ref(raw: &RawWaker) -> &Waker { transmute(raw) }
} |
Didn't realize |
Because The problem with |
To add another use case is storing the waker atomically. You can split the data and vtable into two
@wishawa wote that |
I think it might be natural to think that a I can imagine as situation where you might want to check if the current In order to do this, I could verify that (in a similar respect to |
Hi, now that Note that since the vtable isn't repr(c), and the functions use the default calling convention, access to the vtable but not the functions in contains is not sufficient: I'd need accessors to at least one of the wakes, clone and drop. As a second point, is there a good reason why the function pointers use the (unstable) rust calling convention? This means the function pointers couldn't be passed across ffi even if they were accessible... Anything I could do to help with the process? |
Hi again, I've started a new RFC (rust-lang/rfcs#3404) which, while orthogonal code-wise, has the same end-purpose of allowing the safe passage of wakers across the FFI. A key issue that I just wanted this stated somewhere to avoid stabilizing accessors that would prevent the vtable from being made truly FFI-safe without breaks in the accessors API. For example, an eventual |
We ended up doing the exact same thing. These getters allow us to provide executor-specific extensions on Most async-runtimes have global executors that you use to spawn tasks. But with Without this you need a lookup-tree to get your internal state from a public |
One way to construct a value within a function and return its reference is to have its memory location passed in. It's a little gross, but for example: impl Waker {
unsafe fn from_raw<'a, 'b: 'a>(
raw: &'b RawWaker,
output_mem: &'a mut MaybeUninit<Waker>,
) -> &'a Waker {
// MaybeUninit doesn't drop
output_mem.write(Waker::from_raw(RawWaker::new(raw.data(), raw.vtable())));
output_mem.assume_init_ref()
}
} EDIT: fixed the code |
Would it make sense to have the API look like this? // core::task
impl RawWaker {
pub fn data(&self) -> *const ();
pub fn vtable(&self) -> &'static RawWakerVTable;
}
impl Waker {
pub unsafe fn clone_from_raw(waker: &RawWaker) -> Waker;
pub fn as_raw(&self) -> &RawWaker;
pub fn into_raw(self) -> RawWaker;
} Or a slightly different take: // core::task
impl RawWaker {
pub fn data(&self) -> *const ();
pub fn vtable(&self) -> &'static RawWakerVTable;
}
impl Waker {
// Maybe named something different?
pub fn raw_with<T>(&self, f: impl FnOnce(&RawWaker) -> T) -> T;
pub fn into_raw(self) -> RawWaker;
} |
My issue with this feature is that it's not really usable with impl<W: Wake + Send + Sync + 'static> TryFrom<Waker> for Arc<W> {/*...*/}
impl<'a, W: Wake + Send + Sync + 'static> TryFrom<&'a, Waker> for &'a Arc<W> {/*...*/} (for the symmetry with the already existing |
…ng_issue_number, r=workingjubilee fix `waker_getters` tracking issue number The feature currently links to the closed issue rust-lang#87021. Make it link to the tracking issue rust-lang#96992 instead.
Rollup merge of rust-lang#118873 - lukas-code:fix_waker_getter_tracking_issue_number, r=workingjubilee fix `waker_getters` tracking issue number The feature currently links to the closed issue rust-lang#87021. Make it link to the tracking issue rust-lang#96992 instead.
What's left to move forward with this? It would enable |
(NOT A CONTRIBUTION) This would be a useful API & I'd like to see it stabilized. I don't think any of the discussion on this issue should be blocking on stabilizing the APIs already under this feature. My motivation is for a tightly bound executor/reactor: I want to check in the reactor if a registered waker has the vtable for "my" executor, so that I can avoid making the virtual wake call and directly re-enqueue the task. I don't need to pass the Waker through FFI, I don't need to get a waker back from a RawWaker, these are not necessary features for this API to be useful.
I don't think the conversion from &RawWaker to &Waker is needed for this API to be useful, but I also find it extremely hard to imagine Waker ever gaining any other fields. We added Context specifically to have a place to add fields that wasn't Waker. I think T-libs should guarantee the layout of Waker. |
@rust-lang/libs-api: I propose that we stabilize the following 3 accessors, which have been available since Rust 1.60-nightly (2 years). // core::task
impl RawWaker {
pub fn data(&self) -> *const ();
pub fn vtable(&self) -> &'static RawWakerVTable;
}
impl Waker {
pub fn as_raw(&self) -> &RawWaker;
} The use case is described succinctly and convincingly in #96992 (comment).
Here is code in fn task_from_waker(waker: &Waker) -> TaskRef {
///🤞
struct WakerHack {
data: *const (),
vtable: &'static RawWakerVTable,
}
let hack: &WakerHack = unsafe { mem::transmute(waker) };
if hack.vtable != &VTABLE {
panic!("Found waker not created by the Embassy executor. `embassy_time::Timer` only works with the Embassy executor.");
}
unsafe { TaskRef::from_ptr(hack.data as *const TaskHeader) }
} By making stable accessors available, this would be: fn task_from_waker(waker: &Waker) -> TaskRef {
let raw_waker = waker.as_raw(); // <--
if raw_waker.vtable() != &VTABLE { // <--
panic!("...");
}
let ptr = raw_waker.data(); // <--
unsafe { TaskRef::from_ptr(ptr as *const TaskHeader) }
} The importance of this use case is reinforced by #96992 (comment), and #96992 (comment). AlternativesI would be open to considering making public fields on // core::task
pub struct RawWaker {
pub data: *const (),
pub vtable: &'static RawWakerVTable,
}
impl RawWaker {
pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self; // (already stable)
} Or, move the accessors to // core::task
pub struct Waker {
data: *const (),
vtable: &'static RawWakerVTable,
}
impl Waker {
pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self;
pub fn data(&self) -> *const ();
pub fn vtable(&self) -> &'static RawWakerVTable;
#[deprecated]
pub unsafe fn from_raw(waker: RawWaker) -> Self;
} |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
I... realize that this stabilization process has gone on for a while, so totally understand if you don't want to bother with re-doing it, but: Given that (A very hypothetical example: if the I'd also like to add, if you don't want to commit to a specific number of fields in |
It looks like there was a vote to merge, but this issue isn't a PR and it remains open. What's next here? |
As I have already mentioned, this feature is not really usable with Could it be possible to add the following implementation? impl<W: Wake + Send + Sync + 'static> Arc<W> {
const fn waker_vtable() -> &'static RawWakerVTable { ... }
} It would allow to match the vtable returned by |
Does |
Yes it works, but it requires to already have an allocated The goal is to compare the vtable of a random waker to know if I can cast its data pointer to my own waker implementation. I don't want to rely for this comparison on a lazily allocated waker to get its vtable (especially as this lazy waker may requires some parameters random to be initialized). In short, this is unusable. |
Since rust-lang/rust#96992 has stalled, to prevent potential unsoundness caused by transmuting to &WakerHack, we can use nightly waker_getters APIs by gating it behind nightly feature in embassy-executor without waiting for it to be stablized.
If I understand correctly, the FCP has happened and ended with a disposition to merge. Is there some reason why the FCP checkbox in the first comment is still unticked? In terms of the stabilization PR, is that just waiting for someone to do it, or is there some missing prerequisite? |
This is just waiting for someone to submit a stabilization PR. |
Submitted a stabilization PR: #129919 |
Per the `waker_getters` FCP: rust-lang#96992 (comment)
Per the `waker_getters` FCP: rust-lang#96992 (comment) Docs largely copied from `RawWaker::new`.
Rollup merge of rust-lang#129919 - kevinmehall:waker-getters, r=dtolnay Stabilize `waker_getters` Tracking issue: rust-lang#96992 FCP completed on the tracking issue a while ago. It's not clear whether the libs-api team wanted the `RawWaker` methods moved to `Waker` or went back to the current API after further discussion. `@Amanieu` [wrote "This is just waiting for someone to submit a stabilization PR."](rust-lang#96992 (comment)) so I'm doing just that in hopes of nudging this along. Edit: Moved the `data` and `vtable` methods from `RawWaker` to `Waker` and added `Waker::new` per rust-lang#96992 (comment) ```rs impl Waker { pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self; pub fn data(&self) -> *const (); pub fn vtable(&self) -> &'static RawWakerVTable; } ``` Closes rust-lang#96992
Stabilize `waker_getters` Tracking issue: #96992 FCP completed on the tracking issue a while ago. It's not clear whether the libs-api team wanted the `RawWaker` methods moved to `Waker` or went back to the current API after further discussion. `@Amanieu` [wrote "This is just waiting for someone to submit a stabilization PR."](rust-lang/rust#96992 (comment)) so I'm doing just that in hopes of nudging this along. Edit: Moved the `data` and `vtable` methods from `RawWaker` to `Waker` and added `Waker::new` per rust-lang/rust#96992 (comment) ```rs impl Waker { pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self; pub fn data(&self) -> *const (); pub fn vtable(&self) -> &'static RawWakerVTable; } ``` Closes #96992
waker_getters have been stabilized for 1.83. See rust-lang/rust#96992.
Feature gate:
#![feature(waker_getters)]
This is a tracking issue for getters of data and vtable pointers for
RawWaker
, and the method to getRawWaker
fromWaker
.Public API
Steps / History
RawWaker
andWaker
getters for underlying pointers #91828waker_getters
#129919Unresolved Questions
fn into_raw(self) -> RawWaker
forWaker
? Feature: Provide getters of data and vtable pointer forRawWaker
? #87021 (comment)The text was updated successfully, but these errors were encountered: