use core::cell::{Ref, RefCell};
use core::fmt;
use core::num::NonZeroUsize;
use alloc::rc::{Rc, Weak};
use crate::tree::{
HierarchyEditGrantError, HierarchyEditProhibitionError, LockAggregatorForNode, Tree, TreeCore,
};
enum MembershipCore<T> {
Weak {
tree_core: Weak<TreeCore<T>>,
},
Strong {
tree_core: Rc<TreeCore<T>>,
tree_refcount: NonZeroUsize,
lock_aggregator: LockAggregatorForNode,
},
}
impl<T: fmt::Debug> fmt::Debug for MembershipCore<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Weak { .. } => write!(f, "Weak {{ .. }}"),
Self::Strong {
tree_refcount,
lock_aggregator,
..
} => f
.debug_struct("Strong")
.field("tree_refcount", &tree_refcount)
.field("lock_aggregator", &lock_aggregator)
.finish_non_exhaustive(),
}
}
}
#[derive(Debug)]
pub(crate) struct Membership<T> {
inner: Rc<RefCell<MembershipCore<T>>>,
}
impl<T> Drop for Membership<T> {
fn drop(&mut self) {
let mut membership_core = self
.inner
.try_borrow_mut()
.expect("[consistency] membership core should never borrowed nestedly");
match &mut *membership_core {
MembershipCore::Weak { .. } => unreachable!("[validity] `self` has a strong reference"),
MembershipCore::Strong {
tree_core,
tree_refcount,
..
} => {
let decremented = NonZeroUsize::new(tree_refcount.get() - 1);
match decremented {
Some(new_count) => *tree_refcount = new_count,
None => {
let weak_core = Rc::downgrade(tree_core);
*membership_core = MembershipCore::Weak {
tree_core: weak_core,
};
}
}
}
};
}
}
impl<T> Clone for Membership<T> {
#[inline]
fn clone(&self) -> Self {
let mut membership_core = self
.inner
.try_borrow_mut()
.expect("[consistency] membership core should never borrowed nestedly");
match &mut *membership_core {
MembershipCore::Weak { .. } => unreachable!("[validity] `self` has a strong reference"),
MembershipCore::Strong { tree_refcount, .. } => {
let incremented = NonZeroUsize::new(tree_refcount.get().wrapping_add(1))
.expect("[consistency] the memory cannot have `usize::MAX` references");
*tree_refcount = incremented;
}
}
Self {
inner: self.inner.clone(),
}
}
}
impl<T> Membership<T> {
#[inline]
#[must_use]
pub(crate) fn tree_core(&self) -> Rc<TreeCore<T>> {
self.tree_core_ref().clone()
}
#[must_use]
pub(crate) fn tree_core_ref(&self) -> Ref<'_, Rc<TreeCore<T>>> {
let membership_core = self
.inner
.try_borrow()
.expect("[consistency] membership core should never borrowed nestedly");
Ref::map(membership_core, |membership_core| match &*membership_core {
MembershipCore::Weak { .. } => unreachable!("[validity] `self` has a strong reference"),
MembershipCore::Strong { tree_core, .. } => tree_core,
})
}
#[inline]
#[must_use]
pub(crate) fn downgrade(&self) -> WeakMembership<T> {
WeakMembership {
inner: self.inner.clone(),
}
}
#[must_use]
pub(crate) fn create_new_membership(tree_core: Rc<TreeCore<T>>) -> Self {
let tree_refcount = NonZeroUsize::new(1).expect("[consistency] 1 is nonzero");
let membership = MembershipCore::Strong {
tree_core,
tree_refcount,
lock_aggregator: Default::default(),
};
Membership {
inner: Rc::new(RefCell::new(membership)),
}
}
#[inline]
#[must_use]
pub(crate) fn ptr_eq_weak(&self, other: &WeakMembership<T>) -> bool {
Rc::ptr_eq(&self.inner, &other.inner)
}
#[inline]
#[must_use]
pub(crate) fn belongs_to(&self, tree: &Tree<T>) -> bool {
tree.ptr_eq_core(&*self.tree_core_ref())
}
#[must_use]
pub(crate) fn belongs_to_same_tree(&self, other: &Self) -> bool {
let self_ptr = Rc::as_ptr(&*self.tree_core_ref());
let other_ptr = Rc::as_ptr(&*other.tree_core_ref());
self_ptr == other_ptr
}
fn decrement_edit_lock_count(&self) {
let mut membership_core = self
.inner
.try_borrow_mut()
.expect("[consistency] `Membership::inner` should never borrowed nestedly");
match &mut *membership_core {
MembershipCore::Weak { .. } => unreachable!("[validity] `self` has a strong reference"),
MembershipCore::Strong {
tree_core,
lock_aggregator,
..
} => {
lock_aggregator.decrement_count(tree_core);
}
}
}
fn increment_nonzero_edit_lock_count(&self) {
let mut membership_core = self
.inner
.try_borrow_mut()
.expect("[consistency] `Membership::inner` should never borrowed nestedly");
match &mut *membership_core {
MembershipCore::Weak { .. } => unreachable!("[validity] `self` has a strong reference"),
MembershipCore::Strong {
lock_aggregator, ..
} => lock_aggregator.increment_nonzero_count(),
}
}
pub(crate) fn acquire_edit_prohibition(&self) -> Result<(), HierarchyEditProhibitionError> {
let mut membership_core = self
.inner
.try_borrow_mut()
.expect("[consistency] `Membership::inner` should never borrowed nestedly");
match &mut *membership_core {
MembershipCore::Weak { .. } => unreachable!("[validity] `self` has a strong reference"),
MembershipCore::Strong {
tree_core,
lock_aggregator,
..
} => lock_aggregator.acquire_edit_prohibition(tree_core),
}
}
pub(crate) fn acquire_edit_grant(&self) -> Result<(), HierarchyEditGrantError> {
let mut membership_core = self
.inner
.try_borrow_mut()
.expect("[consistency] `Membership::inner` should never borrowed nestedly");
match &mut *membership_core {
MembershipCore::Weak { .. } => unreachable!("[validity] `self` has a strong reference"),
MembershipCore::Strong {
tree_core,
lock_aggregator,
..
} => lock_aggregator.acquire_edit_grant(tree_core),
}
}
}
#[derive(Debug)]
pub(crate) struct WeakMembership<T> {
inner: Rc<RefCell<MembershipCore<T>>>,
}
impl<T> Clone for WeakMembership<T> {
#[inline]
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<T> WeakMembership<T> {
#[inline]
#[must_use]
pub(crate) fn new() -> Self {
Self {
inner: Rc::new(RefCell::new(MembershipCore::Weak {
tree_core: Weak::new(),
})),
}
}
#[must_use]
pub(crate) fn initialize_membership(self, tree_core: Rc<TreeCore<T>>) -> Membership<T> {
let mut inner = self
.inner
.try_borrow_mut()
.expect("[consistency] membership core should not yet be borrowed elsewhere");
match &*inner {
MembershipCore::Weak { tree_core } if Weak::ptr_eq(tree_core, &Weak::new()) => {}
_ => panic!("[precondition] weak membership should not be initialized twice"),
}
debug_assert!(matches!(&*inner, MembershipCore::Weak { .. }));
let tree_refcount = NonZeroUsize::new(1).expect("[validity] 1 is nonzero");
*inner = MembershipCore::Strong {
tree_core,
tree_refcount,
lock_aggregator: Default::default(),
};
drop(inner);
Membership { inner: self.inner }
}
#[must_use]
pub(crate) fn upgrade(&self) -> Option<Membership<T>> {
let mut membership_core = self
.inner
.try_borrow_mut()
.expect("[consistency] membership core should never borrowed nestedly");
match &mut *membership_core {
MembershipCore::Weak { tree_core } => {
let tree_refcount = NonZeroUsize::new(1).expect("[consistency] 1 is nonzero");
let tree_core = tree_core.upgrade()?;
*membership_core = MembershipCore::Strong {
tree_core,
tree_refcount,
lock_aggregator: Default::default(),
};
}
MembershipCore::Strong { tree_refcount, .. } => {
let incremented = NonZeroUsize::new(tree_refcount.get().wrapping_add(1))
.expect("[consistency] the memory cannot have `usize::MAX` references");
*tree_refcount = incremented;
}
}
Some(Membership {
inner: self.inner.clone(),
})
}
#[must_use]
pub(crate) fn ptr_eq_tree_core(&self, other_tree_core: &Rc<TreeCore<T>>) -> bool {
let membership_core = self
.inner
.try_borrow()
.expect("[consistency] membership core should never borrowed nestedly");
let ptr = match &*membership_core {
MembershipCore::Weak { tree_core } => tree_core.as_ptr(),
MembershipCore::Strong { tree_core, .. } => Rc::as_ptr(tree_core),
};
ptr == Rc::as_ptr(other_tree_core)
}
}
impl<T> WeakMembership<T> {
pub(crate) fn set_tree_core(&self, new_tree_core: &Rc<TreeCore<T>>) -> Result<(), ()> {
let mut inner = self
.inner
.try_borrow_mut()
.expect("[consistency] `WeakMembership::inner` should never borrowed nestedly");
match &mut *inner {
MembershipCore::Weak { tree_core } => *tree_core = Rc::downgrade(new_tree_core),
MembershipCore::Strong {
tree_core,
lock_aggregator,
..
} => {
if lock_aggregator.has_lock() {
tree_core.transfer_single_lock_to(new_tree_core)?;
}
*tree_core = new_tree_core.clone();
}
}
Ok(())
}
}
#[derive(Debug)]
pub(crate) struct MembershipWithEditProhibition<T> {
inner: Membership<T>,
}
impl<T> Drop for MembershipWithEditProhibition<T> {
#[inline]
fn drop(&mut self) {
self.inner.decrement_edit_lock_count();
}
}
impl<T> Clone for MembershipWithEditProhibition<T> {
#[inline]
fn clone(&self) -> Self {
self.inner.increment_nonzero_edit_lock_count();
Self {
inner: self.inner.clone(),
}
}
}
impl<T> MembershipWithEditProhibition<T> {
#[inline]
pub(crate) fn new(inner: Membership<T>) -> Result<Self, HierarchyEditProhibitionError> {
inner.acquire_edit_prohibition()?;
Ok(Self { inner })
}
#[inline]
#[must_use]
pub(crate) fn as_inner(&self) -> &Membership<T> {
&self.inner
}
#[inline]
#[must_use]
pub(crate) fn belongs_to_same_tree(&self, other: &Self) -> bool {
self.inner.belongs_to_same_tree(&other.inner)
}
}
impl<T> AsRef<Membership<T>> for MembershipWithEditProhibition<T> {
#[inline]
fn as_ref(&self) -> &Membership<T> {
&self.inner
}
}
#[derive(Debug)]
pub(crate) struct MembershipWithEditGrant<T> {
inner: Membership<T>,
}
impl<T> Drop for MembershipWithEditGrant<T> {
#[inline]
fn drop(&mut self) {
self.inner.decrement_edit_lock_count();
}
}
impl<T> Clone for MembershipWithEditGrant<T> {
#[inline]
fn clone(&self) -> Self {
self.inner.increment_nonzero_edit_lock_count();
Self {
inner: self.inner.clone(),
}
}
}
impl<T> MembershipWithEditGrant<T> {
pub(crate) fn new(inner: Membership<T>) -> Result<Self, HierarchyEditGrantError> {
inner.acquire_edit_grant()?;
Ok(Self { inner })
}
#[inline]
#[must_use]
pub(crate) fn as_inner(&self) -> &Membership<T> {
&self.inner
}
#[inline]
#[must_use]
pub(crate) fn belongs_to_same_tree(&self, other: &Self) -> bool {
self.inner.belongs_to_same_tree(&other.inner)
}
}
impl<T> AsRef<Membership<T>> for MembershipWithEditGrant<T> {
#[inline]
fn as_ref(&self) -> &Membership<T> {
&self.inner
}
}