crossbeam_epoch/
default.rs

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
7use crate::collector::{Collector, LocalHandle};
8use crate::guard::Guard;
9use crate::primitive::{lazy_static, thread_local};
10
11lazy_static! {
12    /// The global data for the default garbage collector.
13    static ref COLLECTOR: Collector = Collector::new();
14}
15
16thread_local! {
17    /// The per-thread participant for the default garbage collector.
18    static HANDLE: LocalHandle = COLLECTOR.register();
19}
20
21/// Pins the current thread.
22#[inline]
23pub fn pin() -> Guard {
24    with_handle(|handle| handle.pin())
25}
26
27/// Returns `true` if the current thread is pinned.
28#[inline]
29pub fn is_pinned() -> bool {
30    with_handle(|handle| handle.is_pinned())
31}
32
33/// Returns the default global collector.
34pub fn default_collector() -> &'static Collector {
35    &COLLECTOR
36}
37
38#[inline]
39fn with_handle<F, R>(mut f: F) -> R
40where
41    F: FnMut(&LocalHandle) -> R,
42{
43    HANDLE
44        .try_with(|h| f(h))
45        .unwrap_or_else(|_| f(&COLLECTOR.register()))
46}
47
48#[cfg(all(test, not(crossbeam_loom)))]
49mod tests {
50    use crossbeam_utils::thread;
51
52    #[test]
53    fn pin_while_exiting() {
54        struct Foo;
55
56        impl Drop for Foo {
57            fn drop(&mut self) {
58                // Pin after `HANDLE` has been dropped. This must not panic.
59                super::pin();
60            }
61        }
62
63        thread_local! {
64            static FOO: Foo = Foo;
65        }
66
67        thread::scope(|scope| {
68            scope.spawn(|_| {
69                // Initialize `FOO` and then `HANDLE`.
70                FOO.with(|_| ());
71                super::pin();
72                // At thread exit, `HANDLE` gets dropped first and `FOO` second.
73            });
74        })
75        .unwrap();
76    }
77}