/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 | | } |