aboutsummaryrefslogtreecommitdiff
path: root/vendor/crossbeam-epoch/src/default.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/crossbeam-epoch/src/default.rs')
-rw-r--r--vendor/crossbeam-epoch/src/default.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/vendor/crossbeam-epoch/src/default.rs b/vendor/crossbeam-epoch/src/default.rs
new file mode 100644
index 0000000..b42c1c7
--- /dev/null
+++ b/vendor/crossbeam-epoch/src/default.rs
@@ -0,0 +1,93 @@
+//! The default garbage collector.
+//!
+//! For each thread, a participant is lazily initialized on its first use, when the current thread
+//! is registered in the default collector. If initialized, the thread's participant will get
+//! destructed on thread exit, which in turn unregisters the thread.
+
+use crate::collector::{Collector, LocalHandle};
+use crate::guard::Guard;
+use crate::primitive::thread_local;
+#[cfg(not(crossbeam_loom))]
+use crate::sync::once_lock::OnceLock;
+
+fn collector() -> &'static Collector {
+ #[cfg(not(crossbeam_loom))]
+ {
+ /// The global data for the default garbage collector.
+ static COLLECTOR: OnceLock<Collector> = OnceLock::new();
+ COLLECTOR.get_or_init(Collector::new)
+ }
+ // FIXME: loom does not currently provide the equivalent of Lazy:
+ // https://github.com/tokio-rs/loom/issues/263
+ #[cfg(crossbeam_loom)]
+ {
+ loom::lazy_static! {
+ /// The global data for the default garbage collector.
+ static ref COLLECTOR: Collector = Collector::new();
+ }
+ &COLLECTOR
+ }
+}
+
+thread_local! {
+ /// The per-thread participant for the default garbage collector.
+ static HANDLE: LocalHandle = collector().register();
+}
+
+/// Pins the current thread.
+#[inline]
+pub fn pin() -> Guard {
+ with_handle(|handle| handle.pin())
+}
+
+/// Returns `true` if the current thread is pinned.
+#[inline]
+pub fn is_pinned() -> bool {
+ with_handle(|handle| handle.is_pinned())
+}
+
+/// Returns the default global collector.
+pub fn default_collector() -> &'static Collector {
+ collector()
+}
+
+#[inline]
+fn with_handle<F, R>(mut f: F) -> R
+where
+ F: FnMut(&LocalHandle) -> R,
+{
+ HANDLE
+ .try_with(|h| f(h))
+ .unwrap_or_else(|_| f(&collector().register()))
+}
+
+#[cfg(all(test, not(crossbeam_loom)))]
+mod tests {
+ use crossbeam_utils::thread;
+
+ #[test]
+ fn pin_while_exiting() {
+ struct Foo;
+
+ impl Drop for Foo {
+ fn drop(&mut self) {
+ // Pin after `HANDLE` has been dropped. This must not panic.
+ super::pin();
+ }
+ }
+
+ thread_local! {
+ static FOO: Foo = Foo;
+ }
+
+ thread::scope(|scope| {
+ scope.spawn(|_| {
+ // Initialize `FOO` and then `HANDLE`.
+ FOO.with(|_| ());
+ super::pin();
+ // At thread exit, `HANDLE` gets dropped first and `FOO` second.
+ });
+ })
+ .unwrap();
+ }
+}