pub trait EdgeVisitor {
fn strong(&mut self, edge: EdgeId, target: ManagedId);
fn weak(&mut self, edge: EdgeId, target: ManagedId);
fn ephemeron(&mut self, edge: EdgeId, key: ManagedId, value: ManagedId);
}
pub trait ManagedObject {
fn trace_edges(&self, visitor: &mut dyn EdgeVisitor);
fn clear_weak_edge(&mut self, edge: EdgeId, expected: ManagedId) -> bool;
fn clear_ephemeron_edge(
&mut self,
_edge: EdgeId,
_expected_key: ManagedId,
_expected_value: ManagedId,
) -> bool {
false
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct HardCappedRetainPolicy {
max_objects: usize,
}
impl HardCappedRetainPolicy {
pub fn new(max_objects: usize) -> Result<Self, ArenaError> {
if max_objects == 0 {
return Err(ArenaError::InvalidCap);
}
Ok(Self { max_objects })
}
pub const fn max_objects(self) -> usize {
self.max_objects
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ArenaError {
InvalidCap,
CapacityExceeded {
cap: usize,
},
IdentityExhausted,
StaleHandle(ManagedId),
StaleRoot(RootId),
ObjectRooted(ManagedId),
MutationEpochChanged {
expected: u64,
actual: u64,
},
}
impl fmt::Display for ArenaError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidCap => f.write_str("managed arena cap must be non-zero"),
Self::CapacityExceeded { cap } => write!(f, "managed arena hard cap {cap} reached"),
Self::IdentityExhausted => f.write_str("managed arena identity space exhausted"),
Self::StaleHandle(id) => write!(f, "stale managed handle {}", id.0),
Self::StaleRoot(id) => write!(f, "stale managed root {}", id.0),
Self::ObjectRooted(id) => write!(f, "managed object {} is rooted", id.0),
Self::MutationEpochChanged { expected, actual } => write!(
f,
"managed arena mutation epoch changed from {expected} to {actual}"
),
}
}
}
impl Error for ArenaError {}
pub struct TraceSnapshot<'a, T> {
roots: Vec<ManagedId>,
kept_alive: Vec<ManagedId>,
objects: &'a BTreeMap<ManagedId, T>,
mutation_epoch: u64,
}
impl<T: ManagedObject> TraceSnapshot<'_, T> {
pub const fn mutation_epoch(&self) -> u64 {
self.mutation_epoch
}
pub fn roots(&self) -> impl ExactSizeIterator<Item = ManagedId> + '_ {
self.roots.iter().copied()
}
pub fn kept_alive(&self) -> impl ExactSizeIterator<Item = ManagedId> + '_ {
self.kept_alive.iter().copied()
}
pub fn objects(&self) -> impl ExactSizeIterator<Item = ManagedId> + '_ {
self.objects.keys().copied()
}
pub fn visit_edges(
&self,
owner: ManagedId,
visitor: &mut dyn EdgeVisitor,
) -> Result<(), ArenaError> {
self.objects
.get(&owner)
.ok_or(ArenaError::StaleHandle(owner))?
.trace_edges(visitor);
Ok(())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SafepointReceipt {
pub sequence: u64,
pub roots: Vec<ManagedId>,
pub objects: Vec<ManagedId>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RoleProjectionReceipt<L> {
pub safepoint: SafepointReceipt,
pub mutation_epoch: u64,
pub roles: Vec<(ManagedId, L)>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RoleProjectionError {
Limit {
limit: usize,
required: usize,
},
Arena(ArenaError),
}
impl fmt::Display for RoleProjectionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Limit { limit, required } => {
write!(f, "role projection limit {limit} requires {required}")
}
Self::Arena(error) => error.fmt(f),
}
}
}
impl Error for RoleProjectionError {}
impl From<ArenaError> for RoleProjectionError {
fn from(error: ArenaError) -> Self {
Self::Arena(error)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TeardownReceipt {
pub objects: Vec<ManagedId>,
pub roots: Vec<RootId>,
}
pub struct CollectionMutationReceipt {
pub cleared_weak: Vec<(ManagedId, EdgeId)>,
pub cleared_ephemerons: Vec<(ManagedId, EdgeId)>,
pub swept: Vec<ManagedId>,
}