Coverage Report

Created: 2026-07-13 08:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/crossbeam-epoch-0.9.18/src/deferred.rs
Line
Count
Source
1
use alloc::boxed::Box;
2
use core::fmt;
3
use core::marker::PhantomData;
4
use core::mem::{self, MaybeUninit};
5
use core::ptr;
6
7
/// Number of words a piece of `Data` can hold.
8
///
9
/// Three words should be enough for the majority of cases. For example, you can fit inside it the
10
/// function pointer together with a fat pointer representing an object that needs to be destroyed.
11
const DATA_WORDS: usize = 3;
12
13
/// Some space to keep a `FnOnce()` object on the stack.
14
type Data = [usize; DATA_WORDS];
15
16
/// A `FnOnce()` that is stored inline if small, or otherwise boxed on the heap.
17
///
18
/// This is a handy way of keeping an unsized `FnOnce()` within a sized structure.
19
pub(crate) struct Deferred {
20
    call: unsafe fn(*mut u8),
21
    data: MaybeUninit<Data>,
22
    _marker: PhantomData<*mut ()>, // !Send + !Sync
23
}
24
25
impl fmt::Debug for Deferred {
26
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
27
0
        f.pad("Deferred { .. }")
28
0
    }
29
}
30
31
impl Deferred {
32
    pub(crate) const NO_OP: Self = {
33
0
        fn no_op_call(_raw: *mut u8) {}
34
        Self {
35
            call: no_op_call,
36
            data: MaybeUninit::uninit(),
37
            _marker: PhantomData,
38
        }
39
    };
40
41
    /// Constructs a new `Deferred` from a `FnOnce()`.
42
2.50M
    pub(crate) fn new<F: FnOnce()>(f: F) -> Self {
43
2.50M
        let size = mem::size_of::<F>();
44
2.50M
        let align = mem::align_of::<F>();
45
46
        unsafe {
47
2.50M
            if size <= mem::size_of::<Data>() && align <= mem::align_of::<Data>() {
48
2.50M
                let mut data = MaybeUninit::<Data>::uninit();
49
2.50M
                ptr::write(data.as_mut_ptr().cast::<F>(), f);
50
51
2.50M
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
2.50M
                    let f: F = ptr::read(raw.cast::<F>());
53
2.50M
                    f();
54
2.50M
                }
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_deque::deque::Worker<async_task::runnable::Runnable>>::resize::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, arc_swap::ArcSwapAny<alloc::sync::Arc<bytes::bytes::Bytes>>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, surrealmx::versions::Versions>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
<crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Merge>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Line
Count
Source
51
90.0k
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
90.0k
                    let f: F = ptr::read(raw.cast::<F>());
53
90.0k
                    f();
54
90.0k
                }
<crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Commit>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Line
Count
Source
51
2.40k
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
2.40k
                    let f: F = ptr::read(raw.cast::<F>());
53
2.40k
                    f();
54
2.40k
                }
<crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<core::sync::atomic::AtomicU64>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Line
Count
Source
51
716k
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
716k
                    let f: F = ptr::read(raw.cast::<F>());
53
716k
                    f();
54
716k
                }
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, arc_swap::ArcSwapAny<alloc::sync::Arc<bytes::bytes::Bytes>>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, surrealmx::versions::Versions>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Merge>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Commit>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<core::sync::atomic::AtomicU64>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_deque::deque::Worker<rayon_core::job::JobRef>>::resize::{closure#0}, ()>::{closure#0}>
<crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_epoch::guard::Guard>::defer_destroy<crossbeam_epoch::sync::queue::Node<crossbeam_epoch::internal::SealedBag>>::{closure#0}, crossbeam_epoch::atomic::Owned<crossbeam_epoch::sync::queue::Node<crossbeam_epoch::internal::SealedBag>>>::{closure#0}>
Line
Count
Source
51
857k
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
857k
                    let f: F = ptr::read(raw.cast::<F>());
53
857k
                    f();
54
857k
                }
<crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_epoch::guard::Guard>::defer_destroy<crossbeam_epoch::internal::Local>::{closure#0}, crossbeam_epoch::atomic::Owned<crossbeam_epoch::internal::Local>>::{closure#0}>
Line
Count
Source
51
841k
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
841k
                    let f: F = ptr::read(raw.cast::<F>());
53
841k
                    f();
54
841k
                }
55
56
2.50M
                Deferred {
57
2.50M
                    call: call::<F>,
58
2.50M
                    data,
59
2.50M
                    _marker: PhantomData,
60
2.50M
                }
61
            } else {
62
0
                let b: Box<F> = Box::new(f);
63
0
                let mut data = MaybeUninit::<Data>::uninit();
64
0
                ptr::write(data.as_mut_ptr().cast::<Box<F>>(), b);
65
66
0
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
67
                    // It's safe to cast `raw` from `*mut u8` to `*mut Box<F>`, because `raw` is
68
                    // originally derived from `*mut Box<F>`.
69
0
                    let b: Box<F> = ptr::read(raw.cast::<Box<F>>());
70
0
                    (*b)();
71
0
                }
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_deque::deque::Worker<async_task::runnable::Runnable>>::resize::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, arc_swap::ArcSwapAny<alloc::sync::Arc<bytes::bytes::Bytes>>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, surrealmx::versions::Versions>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Merge>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Commit>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<core::sync::atomic::AtomicU64>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, arc_swap::ArcSwapAny<alloc::sync::Arc<bytes::bytes::Bytes>>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, surrealmx::versions::Versions>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Merge>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Commit>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<core::sync::atomic::AtomicU64>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_deque::deque::Worker<rayon_core::job::JobRef>>::resize::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_epoch::guard::Guard>::defer_destroy<crossbeam_epoch::sync::queue::Node<crossbeam_epoch::internal::SealedBag>>::{closure#0}, crossbeam_epoch::atomic::Owned<crossbeam_epoch::sync::queue::Node<crossbeam_epoch::internal::SealedBag>>>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::call::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_epoch::guard::Guard>::defer_destroy<crossbeam_epoch::internal::Local>::{closure#0}, crossbeam_epoch::atomic::Owned<crossbeam_epoch::internal::Local>>::{closure#0}>
72
73
0
                Deferred {
74
0
                    call: call::<F>,
75
0
                    data,
76
0
                    _marker: PhantomData,
77
0
                }
78
            }
79
        }
80
2.50M
    }
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_deque::deque::Worker<async_task::runnable::Runnable>>::resize::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, arc_swap::ArcSwapAny<alloc::sync::Arc<bytes::bytes::Bytes>>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, surrealmx::versions::Versions>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
<crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Merge>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Line
Count
Source
42
90.0k
    pub(crate) fn new<F: FnOnce()>(f: F) -> Self {
43
90.0k
        let size = mem::size_of::<F>();
44
90.0k
        let align = mem::align_of::<F>();
45
46
        unsafe {
47
90.0k
            if size <= mem::size_of::<Data>() && align <= mem::align_of::<Data>() {
48
90.0k
                let mut data = MaybeUninit::<Data>::uninit();
49
90.0k
                ptr::write(data.as_mut_ptr().cast::<F>(), f);
50
51
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
                    let f: F = ptr::read(raw.cast::<F>());
53
                    f();
54
                }
55
56
90.0k
                Deferred {
57
90.0k
                    call: call::<F>,
58
90.0k
                    data,
59
90.0k
                    _marker: PhantomData,
60
90.0k
                }
61
            } else {
62
0
                let b: Box<F> = Box::new(f);
63
0
                let mut data = MaybeUninit::<Data>::uninit();
64
0
                ptr::write(data.as_mut_ptr().cast::<Box<F>>(), b);
65
66
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
67
                    // It's safe to cast `raw` from `*mut u8` to `*mut Box<F>`, because `raw` is
68
                    // originally derived from `*mut Box<F>`.
69
                    let b: Box<F> = ptr::read(raw.cast::<Box<F>>());
70
                    (*b)();
71
                }
72
73
0
                Deferred {
74
0
                    call: call::<F>,
75
0
                    data,
76
0
                    _marker: PhantomData,
77
0
                }
78
            }
79
        }
80
90.0k
    }
<crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Commit>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Line
Count
Source
42
2.40k
    pub(crate) fn new<F: FnOnce()>(f: F) -> Self {
43
2.40k
        let size = mem::size_of::<F>();
44
2.40k
        let align = mem::align_of::<F>();
45
46
        unsafe {
47
2.40k
            if size <= mem::size_of::<Data>() && align <= mem::align_of::<Data>() {
48
2.40k
                let mut data = MaybeUninit::<Data>::uninit();
49
2.40k
                ptr::write(data.as_mut_ptr().cast::<F>(), f);
50
51
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
                    let f: F = ptr::read(raw.cast::<F>());
53
                    f();
54
                }
55
56
2.40k
                Deferred {
57
2.40k
                    call: call::<F>,
58
2.40k
                    data,
59
2.40k
                    _marker: PhantomData,
60
2.40k
                }
61
            } else {
62
0
                let b: Box<F> = Box::new(f);
63
0
                let mut data = MaybeUninit::<Data>::uninit();
64
0
                ptr::write(data.as_mut_ptr().cast::<Box<F>>(), b);
65
66
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
67
                    // It's safe to cast `raw` from `*mut u8` to `*mut Box<F>`, because `raw` is
68
                    // originally derived from `*mut Box<F>`.
69
                    let b: Box<F> = ptr::read(raw.cast::<Box<F>>());
70
                    (*b)();
71
                }
72
73
0
                Deferred {
74
0
                    call: call::<F>,
75
0
                    data,
76
0
                    _marker: PhantomData,
77
0
                }
78
            }
79
        }
80
2.40k
    }
<crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<core::sync::atomic::AtomicU64>>>::decrement_with_pin<crossbeam_epoch::default::pin>::{closure#0}, ()>::{closure#0}>
Line
Count
Source
42
716k
    pub(crate) fn new<F: FnOnce()>(f: F) -> Self {
43
716k
        let size = mem::size_of::<F>();
44
716k
        let align = mem::align_of::<F>();
45
46
        unsafe {
47
716k
            if size <= mem::size_of::<Data>() && align <= mem::align_of::<Data>() {
48
716k
                let mut data = MaybeUninit::<Data>::uninit();
49
716k
                ptr::write(data.as_mut_ptr().cast::<F>(), f);
50
51
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
                    let f: F = ptr::read(raw.cast::<F>());
53
                    f();
54
                }
55
56
716k
                Deferred {
57
716k
                    call: call::<F>,
58
716k
                    data,
59
716k
                    _marker: PhantomData,
60
716k
                }
61
            } else {
62
0
                let b: Box<F> = Box::new(f);
63
0
                let mut data = MaybeUninit::<Data>::uninit();
64
0
                ptr::write(data.as_mut_ptr().cast::<Box<F>>(), b);
65
66
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
67
                    // It's safe to cast `raw` from `*mut u8` to `*mut Box<F>`, because `raw` is
68
                    // originally derived from `*mut Box<F>`.
69
                    let b: Box<F> = ptr::read(raw.cast::<Box<F>>());
70
                    (*b)();
71
                }
72
73
0
                Deferred {
74
0
                    call: call::<F>,
75
0
                    data,
76
0
                    _marker: PhantomData,
77
0
                }
78
            }
79
        }
80
716k
    }
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, arc_swap::ArcSwapAny<alloc::sync::Arc<bytes::bytes::Bytes>>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<bytes::bytes::Bytes, lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, surrealmx::versions::Versions>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Merge>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<surrealmx::queue::Commit>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_skiplist::base::Node<u64, alloc::sync::Arc<core::sync::atomic::AtomicU64>>>::decrement::{closure#0}, ()>::{closure#0}>
Unexecuted instantiation: <crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_deque::deque::Worker<rayon_core::job::JobRef>>::resize::{closure#0}, ()>::{closure#0}>
<crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_epoch::guard::Guard>::defer_destroy<crossbeam_epoch::sync::queue::Node<crossbeam_epoch::internal::SealedBag>>::{closure#0}, crossbeam_epoch::atomic::Owned<crossbeam_epoch::sync::queue::Node<crossbeam_epoch::internal::SealedBag>>>::{closure#0}>
Line
Count
Source
42
857k
    pub(crate) fn new<F: FnOnce()>(f: F) -> Self {
43
857k
        let size = mem::size_of::<F>();
44
857k
        let align = mem::align_of::<F>();
45
46
        unsafe {
47
857k
            if size <= mem::size_of::<Data>() && align <= mem::align_of::<Data>() {
48
857k
                let mut data = MaybeUninit::<Data>::uninit();
49
857k
                ptr::write(data.as_mut_ptr().cast::<F>(), f);
50
51
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
                    let f: F = ptr::read(raw.cast::<F>());
53
                    f();
54
                }
55
56
857k
                Deferred {
57
857k
                    call: call::<F>,
58
857k
                    data,
59
857k
                    _marker: PhantomData,
60
857k
                }
61
            } else {
62
0
                let b: Box<F> = Box::new(f);
63
0
                let mut data = MaybeUninit::<Data>::uninit();
64
0
                ptr::write(data.as_mut_ptr().cast::<Box<F>>(), b);
65
66
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
67
                    // It's safe to cast `raw` from `*mut u8` to `*mut Box<F>`, because `raw` is
68
                    // originally derived from `*mut Box<F>`.
69
                    let b: Box<F> = ptr::read(raw.cast::<Box<F>>());
70
                    (*b)();
71
                }
72
73
0
                Deferred {
74
0
                    call: call::<F>,
75
0
                    data,
76
0
                    _marker: PhantomData,
77
0
                }
78
            }
79
        }
80
857k
    }
<crossbeam_epoch::deferred::Deferred>::new::<<crossbeam_epoch::guard::Guard>::defer_unchecked<<crossbeam_epoch::guard::Guard>::defer_destroy<crossbeam_epoch::internal::Local>::{closure#0}, crossbeam_epoch::atomic::Owned<crossbeam_epoch::internal::Local>>::{closure#0}>
Line
Count
Source
42
841k
    pub(crate) fn new<F: FnOnce()>(f: F) -> Self {
43
841k
        let size = mem::size_of::<F>();
44
841k
        let align = mem::align_of::<F>();
45
46
        unsafe {
47
841k
            if size <= mem::size_of::<Data>() && align <= mem::align_of::<Data>() {
48
841k
                let mut data = MaybeUninit::<Data>::uninit();
49
841k
                ptr::write(data.as_mut_ptr().cast::<F>(), f);
50
51
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
                    let f: F = ptr::read(raw.cast::<F>());
53
                    f();
54
                }
55
56
841k
                Deferred {
57
841k
                    call: call::<F>,
58
841k
                    data,
59
841k
                    _marker: PhantomData,
60
841k
                }
61
            } else {
62
0
                let b: Box<F> = Box::new(f);
63
0
                let mut data = MaybeUninit::<Data>::uninit();
64
0
                ptr::write(data.as_mut_ptr().cast::<Box<F>>(), b);
65
66
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
67
                    // It's safe to cast `raw` from `*mut u8` to `*mut Box<F>`, because `raw` is
68
                    // originally derived from `*mut Box<F>`.
69
                    let b: Box<F> = ptr::read(raw.cast::<Box<F>>());
70
                    (*b)();
71
                }
72
73
0
                Deferred {
74
0
                    call: call::<F>,
75
0
                    data,
76
0
                    _marker: PhantomData,
77
0
                }
78
            }
79
        }
80
841k
    }
81
82
    /// Calls the function.
83
    #[inline]
84
2.50M
    pub(crate) fn call(mut self) {
85
2.50M
        let call = self.call;
86
2.50M
        unsafe { call(self.data.as_mut_ptr().cast::<u8>()) };
87
2.50M
    }
88
}
89
90
#[cfg(all(test, not(crossbeam_loom)))]
91
mod tests {
92
    use super::Deferred;
93
    use std::cell::Cell;
94
    use std::convert::identity;
95
96
    #[test]
97
    fn on_stack() {
98
        let fired = &Cell::new(false);
99
        let a = [0usize; 1];
100
101
        let d = Deferred::new(move || {
102
            let _ = identity(a);
103
            fired.set(true);
104
        });
105
106
        assert!(!fired.get());
107
        d.call();
108
        assert!(fired.get());
109
    }
110
111
    #[test]
112
    fn on_heap() {
113
        let fired = &Cell::new(false);
114
        let a = [0usize; 10];
115
116
        let d = Deferred::new(move || {
117
            let _ = identity(a);
118
            fired.set(true);
119
        });
120
121
        assert!(!fired.get());
122
        d.call();
123
        assert!(fired.get());
124
    }
125
126
    #[test]
127
    fn string() {
128
        let a = "hello".to_string();
129
        let d = Deferred::new(move || assert_eq!(a, "hello"));
130
        d.call();
131
    }
132
133
    #[test]
134
    fn boxed_slice_i32() {
135
        let a: Box<[i32]> = vec![2, 3, 5, 7].into_boxed_slice();
136
        let d = Deferred::new(move || assert_eq!(*a, [2, 3, 5, 7]));
137
        d.call();
138
    }
139
140
    #[test]
141
    fn long_slice_usize() {
142
        let a: [usize; 5] = [2, 3, 5, 7, 11];
143
        let d = Deferred::new(move || assert_eq!(a, [2, 3, 5, 7, 11]));
144
        d.call();
145
    }
146
}