Skip to content

Commit

Permalink
Rollup merge of rust-lang#91828 - oxalica:feat/waker-getters, r=dtolnay
Browse files Browse the repository at this point in the history
Implement `RawWaker` and `Waker` getters for underlying pointers

implement rust-lang#87021

New APIs:
- `RawWaker::data(&self) -> *const ()`
- `RawWaker::vtable(&self) -> &'static RawWakerVTable`
- ~`Waker::as_raw_waker(&self) -> &RawWaker`~ `Waker::as_raw(&self) -> &RawWaker`

This third one is an auxiliary function to make the two APIs above more useful. Since we can only get `&Waker` in `Future::poll`, without this, we need to `transmute` it into `&RawWaker` (relying on `repr(transparent)`) in order to access its data/vtable pointers.

~Not sure if it should be named `as_raw` or `as_raw_waker`. Seems we always use `as_<something-raw>` instead of just `as_raw`. But `as_raw_waker` seems not quite consistent with `Waker::from_raw`.~ As suggested in rust-lang#91828 (comment), use `as_raw`.
  • Loading branch information
matthiaskrgr authored Jan 31, 2022
2 parents a937dd5 + bae0da8 commit 2d658e9
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 0 deletions.
24 changes: 24 additions & 0 deletions library/core/src/task/wake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,22 @@ impl RawWaker {
pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker {
RawWaker { data, vtable }
}

/// Get the `data` pointer used to create this `RawWaker`.
#[inline]
#[must_use]
#[unstable(feature = "waker_getters", issue = "87021")]
pub fn data(&self) -> *const () {
self.data
}

/// Get the `vtable` pointer used to create this `RawWaker`.
#[inline]
#[must_use]
#[unstable(feature = "waker_getters", issue = "87021")]
pub fn vtable(&self) -> &'static RawWakerVTable {
self.vtable
}
}

/// A virtual function pointer table (vtable) that specifies the behavior
Expand Down Expand Up @@ -260,6 +276,14 @@ impl Waker {
pub unsafe fn from_raw(waker: RawWaker) -> Waker {
Waker { waker }
}

/// Get a reference to the underlying [`RawWaker`].
#[inline]
#[must_use]
#[unstable(feature = "waker_getters", issue = "87021")]
pub fn as_raw(&self) -> &RawWaker {
&self.waker
}
}

#[stable(feature = "futures_api", since = "1.36.0")]
Expand Down
2 changes: 2 additions & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
#![feature(unzip_option)]
#![feature(const_array_from_ref)]
#![feature(const_slice_from_ref)]
#![feature(waker_getters)]
#![deny(unsafe_op_in_unsafe_fn)]

extern crate test;
Expand Down Expand Up @@ -131,3 +132,4 @@ mod task;
mod time;
mod tuple;
mod unicode;
mod waker;
22 changes: 22 additions & 0 deletions library/core/tests/waker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use std::ptr;
use std::task::{RawWaker, RawWakerVTable, Waker};

#[test]
fn test_waker_getters() {
let raw_waker = RawWaker::new(42usize as *mut (), &WAKER_VTABLE);
assert_eq!(raw_waker.data() as usize, 42);
assert!(ptr::eq(raw_waker.vtable(), &WAKER_VTABLE));

let waker = unsafe { Waker::from_raw(raw_waker) };
let waker2 = waker.clone();
let raw_waker2 = waker2.as_raw();
assert_eq!(raw_waker2.data() as usize, 43);
assert!(ptr::eq(raw_waker2.vtable(), &WAKER_VTABLE));
}

static WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
|data| RawWaker::new((data as usize + 1) as *mut (), &WAKER_VTABLE),
|_| {},
|_| {},
|_| {},
);

0 comments on commit 2d658e9

Please sign in to comment.