Skip to content

Commit bf722ca

Browse files
authored
Rollup merge of rust-lang#146057 - Ddystopia:waker-fn, r=dtolnay
feat: add `from_fn_ptr` to `Waker` and `LocalWaker` Closes: rust-lang#146055
2 parents 790270b + 75835fb commit bf722ca

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

library/core/src/task/wake.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,28 @@ impl Waker {
584584
pub fn vtable(&self) -> &'static RawWakerVTable {
585585
self.waker.vtable
586586
}
587+
588+
/// Constructs a `Waker` from a function pointer.
589+
#[inline]
590+
#[must_use]
591+
#[unstable(feature = "waker_from_fn_ptr", issue = "148457")]
592+
pub const fn from_fn_ptr(f: fn()) -> Self {
593+
// SAFETY: Unsafe is used for transmutes, pointer came from `fn()` so it
594+
// is sound to transmute it back to `fn()`.
595+
static VTABLE: RawWakerVTable = unsafe {
596+
RawWakerVTable::new(
597+
|this| RawWaker::new(this, &VTABLE),
598+
|this| transmute::<*const (), fn()>(this)(),
599+
|this| transmute::<*const (), fn()>(this)(),
600+
|_| {},
601+
)
602+
};
603+
let raw = RawWaker::new(f as *const (), &VTABLE);
604+
605+
// SAFETY: `clone` is just a copy, `drop` is a no-op while `wake` and
606+
// `wake_by_ref` just call the function pointer.
607+
unsafe { Self::from_raw(raw) }
608+
}
587609
}
588610

589611
#[stable(feature = "futures_api", since = "1.36.0")]
@@ -879,6 +901,28 @@ impl LocalWaker {
879901
pub fn vtable(&self) -> &'static RawWakerVTable {
880902
self.waker.vtable
881903
}
904+
905+
/// Constructs a `LocalWaker` from a function pointer.
906+
#[inline]
907+
#[must_use]
908+
#[unstable(feature = "waker_from_fn_ptr", issue = "148457")]
909+
pub const fn from_fn_ptr(f: fn()) -> Self {
910+
// SAFETY: Unsafe is used for transmutes, pointer came from `fn()` so it
911+
// is sound to transmute it back to `fn()`.
912+
static VTABLE: RawWakerVTable = unsafe {
913+
RawWakerVTable::new(
914+
|this| RawWaker::new(this, &VTABLE),
915+
|this| transmute::<*const (), fn()>(this)(),
916+
|this| transmute::<*const (), fn()>(this)(),
917+
|_| {},
918+
)
919+
};
920+
let raw = RawWaker::new(f as *const (), &VTABLE);
921+
922+
// SAFETY: `clone` is just a copy, `drop` is a no-op while `wake` and
923+
// `wake_by_ref` just call the function pointer.
924+
unsafe { Self::from_raw(raw) }
925+
}
882926
}
883927
#[unstable(feature = "local_waker", issue = "118959")]
884928
impl Clone for LocalWaker {

0 commit comments

Comments
 (0)