diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/futures-task/src/waker.rs | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/futures-task/src/waker.rs')
-rw-r--r-- | third_party/rust/futures-task/src/waker.rs | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/third_party/rust/futures-task/src/waker.rs b/third_party/rust/futures-task/src/waker.rs new file mode 100644 index 0000000000..79112569c5 --- /dev/null +++ b/third_party/rust/futures-task/src/waker.rs @@ -0,0 +1,59 @@ +use super::arc_wake::ArcWake; +use alloc::sync::Arc; +use core::mem; +use core::task::{RawWaker, RawWakerVTable, Waker}; + +pub(super) fn waker_vtable<W: ArcWake>() -> &'static RawWakerVTable { + &RawWakerVTable::new( + clone_arc_raw::<W>, + wake_arc_raw::<W>, + wake_by_ref_arc_raw::<W>, + drop_arc_raw::<W>, + ) +} + +/// Creates a [`Waker`] from an `Arc<impl ArcWake>`. +/// +/// The returned [`Waker`] will call +/// [`ArcWake.wake()`](ArcWake::wake) if awoken. +pub fn waker<W>(wake: Arc<W>) -> Waker +where + W: ArcWake + 'static, +{ + let ptr = Arc::into_raw(wake).cast::<()>(); + + unsafe { Waker::from_raw(RawWaker::new(ptr, waker_vtable::<W>())) } +} + +// FIXME: panics on Arc::clone / refcount changes could wreak havoc on the +// code here. We should guard against this by aborting. + +#[allow(clippy::redundant_clone)] // The clone here isn't actually redundant. +unsafe fn increase_refcount<T: ArcWake>(data: *const ()) { + // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop + let arc = mem::ManuallyDrop::new(Arc::<T>::from_raw(data.cast::<T>())); + // Now increase refcount, but don't drop new refcount either + let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); +} + +// used by `waker_ref` +unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker { + increase_refcount::<T>(data); + RawWaker::new(data, waker_vtable::<T>()) +} + +unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) { + let arc: Arc<T> = Arc::from_raw(data.cast::<T>()); + ArcWake::wake(arc); +} + +// used by `waker_ref` +unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) { + // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop + let arc = mem::ManuallyDrop::new(Arc::<T>::from_raw(data.cast::<T>())); + ArcWake::wake_by_ref(&arc); +} + +unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) { + drop(Arc::<T>::from_raw(data.cast::<T>())) +} |