use alloc::boxed::Box; use core::fmt; use core::marker::PhantomData; use core::mem::{self, MaybeUninit}; use core::ptr;
/// Number of words a piece of `Data` can hold. /// /// Three words should be enough for the majority of cases. For example, you can fit inside it the /// function pointer together with a fat pointer representing an object that needs to be destroyed. const DATA_WORDS: usize = 3;
/// Some space to keep a `FnOnce()` object on the stack. type Data = [usize; DATA_WORDS];
/// A `FnOnce()` that is stored inline if small, or otherwise boxed on the heap. /// /// This is a handy way of keeping an unsized `FnOnce()` within a sized structure. pub(crate) struct Deferred {
call: unsafe fn(*mut u8),
data: MaybeUninit<Data>,
_marker: PhantomData<*mut ()>, // !Send + !Sync
}
/// Constructs a new `Deferred` from a `FnOnce()`. pub(crate) fn new<F: FnOnce()>(f: F) -> Self { let size = mem::size_of::<F>(); let align = mem::align_of::<F>();
unsafe { if size <= mem::size_of::<Data>() && align <= mem::align_of::<Data>() { letmut data = MaybeUninit::<Data>::uninit();
ptr::write(data.as_mut_ptr().cast::<F>(), f);
unsafe fn call<F: FnOnce()>(raw: *mut u8) { let f: F = ptr::read(raw.cast::<F>());
f();
}
unsafe fn call<F: FnOnce()>(raw: *mut u8) { // It's safe to cast `raw` from `*mut u8` to `*mut Box<F>`, because `raw` is // originally derived from `*mut Box<F>`. let b: Box<F> = ptr::read(raw.cast::<Box<F>>());
(*b)();
}
/// Calls the function. #[inline] pub(crate) fn call(mutself) { let call = self.call; unsafe { call(self.data.as_mut_ptr().cast::<u8>()) };
}
}
#[cfg(all(test, not(crossbeam_loom)))] mod tests { usesuper::Deferred; use std::boxed::Box; use std::cell::Cell; use std::convert::identity; use std::string::ToString; use std::vec;
#[test]
fn on_stack() { let fired = &Cell::new(false); let a = [0usize; 1];
let d = Deferred::new(move || { let _ = identity(a);
fired.set(true);
});
#[test]
fn string() { let a = "hello".to_string(); let d = Deferred::new(move || assert_eq!(a, "hello"));
d.call();
}
#[test]
fn boxed_slice_i32() { let a: Box<[i32]> = vec![2, 3, 5, 7].into_boxed_slice(); let d = Deferred::new(move || assert_eq!(*a, [2, 3, 5, 7]));
d.call();
}
#[test]
fn long_slice_usize() { let a: [usize; 5] = [2, 3, 5, 7, 11]; let d = Deferred::new(move || assert_eq!(a, [2, 3, 5, 7, 11]));
d.call();
}
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.8Bemerkung:
(vorverarbeitet am 2026-10-11)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.