summaryrefslogtreecommitdiffstats
path: root/vendor/crossbeam-epoch/src/default.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--vendor/crossbeam-epoch/src/default.rs85
1 files changed, 85 insertions, 0 deletions
diff --git a/vendor/crossbeam-epoch/src/default.rs b/vendor/crossbeam-epoch/src/default.rs
new file mode 100644
index 000000000..c2b4852a4
--- /dev/null
+++ b/vendor/crossbeam-epoch/src/default.rs
@@ -0,0 +1,85 @@
+//! 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 once_cell::sync::Lazy;
+
+/// The global data for the default garbage collector.
+#[cfg(not(crossbeam_loom))]
+static COLLECTOR: Lazy<Collector> = Lazy::new(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();
+}
+
+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();
+ }
+}