crossbeam_epoch/
default.rs1use crate::collector::{Collector, LocalHandle};
8use crate::guard::Guard;
9use crate::primitive::thread_local;
10#[cfg(not(crossbeam_loom))]
11use once_cell::sync::Lazy;
12
13#[cfg(not(crossbeam_loom))]
15static COLLECTOR: Lazy<Collector> = Lazy::new(Collector::new);
16#[cfg(crossbeam_loom)]
19loom::lazy_static! {
20 static ref COLLECTOR: Collector = Collector::new();
22}
23
24thread_local! {
25 static HANDLE: LocalHandle = COLLECTOR.register();
27}
28
29#[inline]
31pub fn pin() -> Guard {
32 with_handle(|handle| handle.pin())
33}
34
35#[inline]
37pub fn is_pinned() -> bool {
38 with_handle(|handle| handle.is_pinned())
39}
40
41pub fn default_collector() -> &'static Collector {
43 &COLLECTOR
44}
45
46#[inline]
47fn with_handle<F, R>(mut f: F) -> R
48where
49 F: FnMut(&LocalHandle) -> R,
50{
51 HANDLE
52 .try_with(|h| f(h))
53 .unwrap_or_else(|_| f(&COLLECTOR.register()))
54}
55
56#[cfg(all(test, not(crossbeam_loom)))]
57mod tests {
58 use crossbeam_utils::thread;
59
60 #[test]
61 fn pin_while_exiting() {
62 struct Foo;
63
64 impl Drop for Foo {
65 fn drop(&mut self) {
66 super::pin();
68 }
69 }
70
71 thread_local! {
72 static FOO: Foo = Foo;
73 }
74
75 thread::scope(|scope| {
76 scope.spawn(|_| {
77 FOO.with(|_| ());
79 super::pin();
80 });
82 })
83 .unwrap();
84 }
85}