Coverage Report

Created: 2025-11-24 07:30

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/default.rs
Line
Count
Source
1
//! The default garbage collector.
2
//!
3
//! For each thread, a participant is lazily initialized on its first use, when the current thread
4
//! is registered in the default collector.  If initialized, the thread's participant will get
5
//! destructed on thread exit, which in turn unregisters the thread.
6
7
use crate::collector::{Collector, LocalHandle};
8
use crate::guard::Guard;
9
use crate::primitive::thread_local;
10
#[cfg(not(crossbeam_loom))]
11
use crate::sync::once_lock::OnceLock;
12
13
64.1k
fn collector() -> &'static Collector {
14
    #[cfg(not(crossbeam_loom))]
15
    {
16
        /// The global data for the default garbage collector.
17
        static COLLECTOR: OnceLock<Collector> = OnceLock::new();
18
64.1k
        COLLECTOR.get_or_init(Collector::new)
19
    }
20
    // FIXME: loom does not currently provide the equivalent of Lazy:
21
    // https://github.com/tokio-rs/loom/issues/263
22
    #[cfg(crossbeam_loom)]
23
    {
24
        loom::lazy_static! {
25
            /// The global data for the default garbage collector.
26
            static ref COLLECTOR: Collector = Collector::new();
27
        }
28
        &COLLECTOR
29
    }
30
64.1k
}
31
32
thread_local! {
33
    /// The per-thread participant for the default garbage collector.
34
    static HANDLE: LocalHandle = collector().register();
35
}
36
37
/// Pins the current thread.
38
#[inline]
39
204M
pub fn pin() -> Guard {
40
204M
    with_handle(|handle| handle.pin())
crossbeam_epoch::default::pin::{closure#0}
Line
Count
Source
40
204M
    with_handle(|handle| handle.pin())
Unexecuted instantiation: crossbeam_epoch::default::pin::{closure#0}
41
204M
}
crossbeam_epoch::default::pin
Line
Count
Source
39
204M
pub fn pin() -> Guard {
40
204M
    with_handle(|handle| handle.pin())
41
204M
}
Unexecuted instantiation: crossbeam_epoch::default::pin
42
43
/// Returns `true` if the current thread is pinned.
44
#[inline]
45
204M
pub fn is_pinned() -> bool {
46
204M
    with_handle(|handle| handle.is_pinned())
crossbeam_epoch::default::is_pinned::{closure#0}
Line
Count
Source
46
204M
    with_handle(|handle| handle.is_pinned())
Unexecuted instantiation: crossbeam_epoch::default::is_pinned::{closure#0}
47
204M
}
crossbeam_epoch::default::is_pinned
Line
Count
Source
45
204M
pub fn is_pinned() -> bool {
46
204M
    with_handle(|handle| handle.is_pinned())
47
204M
}
Unexecuted instantiation: crossbeam_epoch::default::is_pinned
48
49
/// Returns the default global collector.
50
0
pub fn default_collector() -> &'static Collector {
51
0
    collector()
52
0
}
53
54
#[inline]
55
408M
fn with_handle<F, R>(mut f: F) -> R
56
408M
where
57
408M
    F: FnMut(&LocalHandle) -> R,
58
{
59
408M
    HANDLE
60
408M
        .try_with(|h| f(h))
crossbeam_epoch::default::with_handle::<crossbeam_epoch::default::pin::{closure#0}, crossbeam_epoch::guard::Guard>::{closure#0}
Line
Count
Source
60
204M
        .try_with(|h| f(h))
crossbeam_epoch::default::with_handle::<crossbeam_epoch::default::is_pinned::{closure#0}, bool>::{closure#0}
Line
Count
Source
60
204M
        .try_with(|h| f(h))
Unexecuted instantiation: crossbeam_epoch::default::with_handle::<_, _>::{closure#0}
61
408M
        .unwrap_or_else(|_| f(&collector().register()))
Unexecuted instantiation: crossbeam_epoch::default::with_handle::<crossbeam_epoch::default::pin::{closure#0}, crossbeam_epoch::guard::Guard>::{closure#1}
Unexecuted instantiation: crossbeam_epoch::default::with_handle::<crossbeam_epoch::default::is_pinned::{closure#0}, bool>::{closure#1}
Unexecuted instantiation: crossbeam_epoch::default::with_handle::<_, _>::{closure#1}
62
408M
}
crossbeam_epoch::default::with_handle::<crossbeam_epoch::default::pin::{closure#0}, crossbeam_epoch::guard::Guard>
Line
Count
Source
55
204M
fn with_handle<F, R>(mut f: F) -> R
56
204M
where
57
204M
    F: FnMut(&LocalHandle) -> R,
58
{
59
204M
    HANDLE
60
204M
        .try_with(|h| f(h))
61
204M
        .unwrap_or_else(|_| f(&collector().register()))
62
204M
}
crossbeam_epoch::default::with_handle::<crossbeam_epoch::default::is_pinned::{closure#0}, bool>
Line
Count
Source
55
204M
fn with_handle<F, R>(mut f: F) -> R
56
204M
where
57
204M
    F: FnMut(&LocalHandle) -> R,
58
{
59
204M
    HANDLE
60
204M
        .try_with(|h| f(h))
61
204M
        .unwrap_or_else(|_| f(&collector().register()))
62
204M
}
Unexecuted instantiation: crossbeam_epoch::default::with_handle::<_, _>
63
64
#[cfg(all(test, not(crossbeam_loom)))]
65
mod tests {
66
    use crossbeam_utils::thread;
67
68
    #[test]
69
    fn pin_while_exiting() {
70
        struct Foo;
71
72
        impl Drop for Foo {
73
            fn drop(&mut self) {
74
                // Pin after `HANDLE` has been dropped. This must not panic.
75
                super::pin();
76
            }
77
        }
78
79
        thread_local! {
80
            static FOO: Foo = const { Foo };
81
        }
82
83
        thread::scope(|scope| {
84
            scope.spawn(|_| {
85
                // Initialize `FOO` and then `HANDLE`.
86
                FOO.with(|_| ());
87
                super::pin();
88
                // At thread exit, `HANDLE` gets dropped first and `FOO` second.
89
            });
90
        })
91
        .unwrap();
92
    }
93
}