use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicU64, Ordering};
use std::sync::Arc;
use crate::collector::alloc::GcAllocation;
use crate::concurrency::lockout::{Lockout, LockoutProvider};
use crate::Scan;
#[derive(Debug)]
pub struct GcData {
pub(crate) lockout: Lockout,
pub(crate) deallocated: AtomicBool,
pub(crate) last_marked: AtomicU64,
pub(crate) underlying_allocation: GcAllocation,
}
impl LockoutProvider for Arc<GcData> {
fn provide(&self) -> &Lockout {
&self.lockout
}
}
impl GcData {
pub fn scan_ptr(&self) -> *const dyn Scan {
self.underlying_allocation.scan_ptr
}
}
#[derive(Debug)]
pub struct GcHandle {
pub(crate) underlying_data: UnderlyingData,
pub(crate) last_non_rooted: AtomicU64,
}
#[derive(Debug)]
pub enum UnderlyingData {
Fixed(Arc<GcData>),
DynamicForAtomic(Arc<AtomicPtr<GcData>>),
}
impl UnderlyingData {
#[inline]
pub unsafe fn with_data<F: FnOnce(&GcData)>(&self, f: F) {
match self {
Self::Fixed(data) => f(&*data),
Self::DynamicForAtomic(ptr) => {
let arc_ptr = ptr.load(Ordering::Relaxed);
f(&*arc_ptr)
}
}
}
}