Coverage Report

Created: 2026-09-01 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/crossbeam-epoch-0.9.20/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
155k
    pub(crate) fn new<F: FnOnce()>(f: F) -> Self {
43
155k
        let size = mem::size_of::<F>();
44
155k
        let align = mem::align_of::<F>();
45
46
        unsafe {
47
155k
            if size <= mem::size_of::<Data>() && align <= mem::align_of::<Data>() {
48
155k
                let mut data = MaybeUninit::<Data>::uninit();
49
155k
                ptr::write(data.as_mut_ptr().cast::<F>(), f);
50
51
155k
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
155k
                    let f: F = ptr::read(raw.cast::<F>());
53
155k
                    f();
54
155k
                }
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
77.8k
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
77.8k
                    let f: F = ptr::read(raw.cast::<F>());
53
77.8k
                    f();
54
77.8k
                }
<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
77.8k
                unsafe fn call<F: FnOnce()>(raw: *mut u8) {
52
77.8k
                    let f: F = ptr::read(raw.cast::<F>());
53
77.8k
                    f();
54
77.8k
                }
55
56
155k
                Deferred {
57
155k
                    call: call::<F>,
58
155k
                    data,
59
155k
                    _marker: PhantomData,
60
155k
                }
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<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
155k
    }
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
77.9k
    pub(crate) fn new<F: FnOnce()>(f: F) -> Self {
43
77.9k
        let size = mem::size_of::<F>();
44
77.9k
        let align = mem::align_of::<F>();
45
46
        unsafe {
47
77.9k
            if size <= mem::size_of::<Data>() && align <= mem::align_of::<Data>() {
48
77.9k
                let mut data = MaybeUninit::<Data>::uninit();
49
77.9k
                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
77.9k
                Deferred {
57
77.9k
                    call: call::<F>,
58
77.9k
                    data,
59
77.9k
                    _marker: PhantomData,
60
77.9k
                }
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
77.9k
    }
<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
77.9k
    pub(crate) fn new<F: FnOnce()>(f: F) -> Self {
43
77.9k
        let size = mem::size_of::<F>();
44
77.9k
        let align = mem::align_of::<F>();
45
46
        unsafe {
47
77.9k
            if size <= mem::size_of::<Data>() && align <= mem::align_of::<Data>() {
48
77.9k
                let mut data = MaybeUninit::<Data>::uninit();
49
77.9k
                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
77.9k
                Deferred {
57
77.9k
                    call: call::<F>,
58
77.9k
                    data,
59
77.9k
                    _marker: PhantomData,
60
77.9k
                }
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
77.9k
    }
81
82
    /// Calls the function.
83
    #[inline]
84
155k
    pub(crate) fn call(mut self) {
85
155k
        let call = self.call;
86
155k
        unsafe { call(self.data.as_mut_ptr().cast::<u8>()) };
87
155k
    }
88
}
89
90
#[cfg(all(test, not(crossbeam_loom)))]
91
mod tests {
92
    use super::Deferred;
93
    use std::boxed::Box;
94
    use std::cell::Cell;
95
    use std::convert::identity;
96
    use std::string::ToString;
97
    use std::vec;
98
99
    #[test]
100
    fn on_stack() {
101
        let fired = &Cell::new(false);
102
        let a = [0usize; 1];
103
104
        let d = Deferred::new(move || {
105
            let _ = identity(a);
106
            fired.set(true);
107
        });
108
109
        assert!(!fired.get());
110
        d.call();
111
        assert!(fired.get());
112
    }
113
114
    #[test]
115
    fn on_heap() {
116
        let fired = &Cell::new(false);
117
        let a = [0usize; 10];
118
119
        let d = Deferred::new(move || {
120
            let _ = identity(a);
121
            fired.set(true);
122
        });
123
124
        assert!(!fired.get());
125
        d.call();
126
        assert!(fired.get());
127
    }
128
129
    #[test]
130
    fn string() {
131
        let a = "hello".to_string();
132
        let d = Deferred::new(move || assert_eq!(a, "hello"));
133
        d.call();
134
    }
135
136
    #[test]
137
    fn boxed_slice_i32() {
138
        let a: Box<[i32]> = vec![2, 3, 5, 7].into_boxed_slice();
139
        let d = Deferred::new(move || assert_eq!(*a, [2, 3, 5, 7]));
140
        d.call();
141
    }
142
143
    #[test]
144
    fn long_slice_usize() {
145
        let a: [usize; 5] = [2, 3, 5, 7, 11];
146
        let d = Deferred::new(move || assert_eq!(a, [2, 3, 5, 7, 11]));
147
        d.call();
148
    }
149
}