use core::ptr::NonNull;
use core::sync::atomic::{
self,
Ordering::{self, SeqCst},
};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, vec::Vec};
use crate::hazard::{Hazard, HazardList, Protected};
use crate::retired::{AbandonedBags, RetiredBag};
use crate::sanitize;
pub(crate) static GLOBAL: Global = Global::new();
#[derive(Debug)]
pub(crate) struct Global {
hazards: HazardList,
abandoned: AbandonedBags,
}
impl Global {
#[inline]
pub const fn new() -> Self {
Self { hazards: HazardList::new(), abandoned: AbandonedBags::new() }
}
#[inline]
pub fn get_hazard(&'static self, protect: Option<NonNull<()>>) -> &'static Hazard {
self.hazards.get_hazard(protect)
}
#[inline]
pub fn collect_protected_hazards(&'static self, vec: &mut Vec<Protected>, order: Ordering) {
debug_assert_eq!(order, SeqCst, "must only be called with `SeqCst`");
vec.clear();
atomic::fence(order);
for hazard in self.hazards.iter().fuse() {
if let Some(protected) = hazard.protected(sanitize::RELAXED_LOAD) {
vec.push(protected);
}
}
}
#[inline]
pub fn abandon_retired_bag(&'static self, bag: Box<RetiredBag>) {
debug_assert!(!bag.inner.is_empty());
self.abandoned.push(bag);
}
#[inline]
pub fn try_adopt_abandoned_records(&'static self) -> Option<Box<RetiredBag>> {
self.abandoned.take_and_merge()
}
}