use core::cell::Cell;
use core::fmt;
use alloc::rc::{Rc, Weak};
use crate::node::Node;
use crate::tree::TreeCore;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct HierarchyEditProhibitionError;
impl fmt::Display for HierarchyEditProhibitionError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("edif of the tree hierarchy is already granted")
}
}
#[cfg(feature = "std")]
impl std::error::Error for HierarchyEditProhibitionError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct HierarchyEditGrantError;
impl fmt::Display for HierarchyEditGrantError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("edit of the tree hierarchy is already prohibited")
}
}
#[cfg(feature = "std")]
impl std::error::Error for HierarchyEditGrantError {}
#[derive(Default, Debug)]
pub struct HierarchyLockManager {
num_grants: Cell<isize>,
}
impl HierarchyLockManager {
#[inline]
pub(crate) fn ensure_prohibition_acquirable(
&self,
) -> Result<(), HierarchyEditProhibitionError> {
if self.num_grants.get() <= 0 {
Ok(())
} else {
Err(HierarchyEditProhibitionError)
}
}
#[inline]
pub(crate) fn ensure_grant_acquirable(&self) -> Result<(), HierarchyEditGrantError> {
if self.num_grants.get() >= 0 {
Ok(())
} else {
Err(HierarchyEditGrantError)
}
}
fn acquire_prohibition(&self) -> Result<(), HierarchyEditProhibitionError> {
let old_count = self.num_grants.get();
if old_count > 0 {
return Err(HierarchyEditProhibitionError);
}
let new_count = old_count
.checked_sub(1)
.unwrap_or_else(|| panic!("[precondition] too many hierarchy edit prohibitions"));
self.num_grants.set(new_count);
Ok(())
}
fn release_prohibition(&self) {
let old_count = self.num_grants.get();
if old_count >= 0 {
panic!("[consistency] attempt to release an edit prohibition while none are active");
}
self.num_grants.set(old_count + 1);
}
fn acquire_grant(&self) -> Result<(), HierarchyEditGrantError> {
let old_count = self.num_grants.get();
if old_count < 0 {
return Err(HierarchyEditGrantError);
}
let new_count = old_count
.checked_add(1)
.unwrap_or_else(|| panic!("[precondition] too many hierarchy edit grants"));
self.num_grants.set(new_count);
Ok(())
}
fn release_grant(&self) {
let old_count = self.num_grants.get();
if old_count <= 0 {
panic!("[consistency] attempt to release an edit grant while none are active");
}
self.num_grants.set(old_count - 1);
}
fn release_any_lock(&self) {
use core::cmp::Ordering;
match self.num_grants.get().cmp(&0) {
Ordering::Greater => {
let new_count = self.num_grants.get() - 1;
self.num_grants.set(new_count);
}
Ordering::Equal => panic!("[consistency] lock count should be nonzero"),
Ordering::Less => {
let new_count = self.num_grants.get() + 1;
self.num_grants.set(new_count);
}
}
}
pub(super) fn transfer_single_lock_to(&self, other: &Self) -> Result<(), ()> {
use core::cmp::Ordering;
match self.num_grants.get().cmp(&0) {
Ordering::Greater => {
other.acquire_grant().map_err(|_| ())?;
let new_count = self.num_grants.get() - 1;
self.num_grants.set(new_count);
}
Ordering::Equal => {}
Ordering::Less => {
other.acquire_prohibition().map_err(|_| ())?;
let new_count = self.num_grants.get() + 1;
self.num_grants.set(new_count);
}
}
Ok(())
}
}
pub struct HierarchyEditProhibition<T>(Weak<TreeCore<T>>);
impl<T> Drop for HierarchyEditProhibition<T> {
#[inline]
fn drop(&mut self) {
if let Some(tree_core) = Weak::upgrade(&self.0) {
tree_core.lock_manager.release_prohibition();
}
}
}
impl<T> HierarchyEditProhibition<T> {
pub(super) fn new(tree_core: &Rc<TreeCore<T>>) -> Result<Self, HierarchyEditProhibitionError> {
tree_core.lock_manager.acquire_prohibition()?;
Ok(HierarchyEditProhibition(Rc::downgrade(tree_core)))
}
pub fn try_clone(&self) -> Result<Self, HierarchyEditProhibitionError> {
if let Some(tree_core) = Weak::upgrade(&self.0) {
tree_core.lock_manager.acquire_prohibition()?;
}
Ok(Self(self.0.clone()))
}
#[inline]
#[must_use]
pub fn is_valid_for_node(&self, node: &Node<T>) -> bool {
node.ptr_eq_tree_core_weak(&self.0)
}
#[inline]
pub(crate) fn panic_if_invalid_for_node(&self, node: &Node<T>) {
if !self.is_valid_for_node(node) {
panic!("[precondition] the prohibition is not valid for the node of interest");
}
}
}
pub struct HierarchyEditGrant<T>(Weak<TreeCore<T>>);
impl<T> Drop for HierarchyEditGrant<T> {
#[inline]
fn drop(&mut self) {
if let Some(tree_core) = Weak::upgrade(&self.0) {
tree_core.lock_manager.release_grant();
}
}
}
impl<T> Clone for HierarchyEditGrant<T> {
#[inline]
fn clone(&self) -> Self {
self.try_clone()
.expect("[precondition] too many hierarchy edit grants are active")
}
}
impl<T> HierarchyEditGrant<T> {
pub(super) fn new(tree_core: &Rc<TreeCore<T>>) -> Result<Self, HierarchyEditGrantError> {
tree_core.lock_manager.acquire_grant()?;
Ok(HierarchyEditGrant(Rc::downgrade(tree_core)))
}
pub fn try_clone(&self) -> Result<Self, HierarchyEditGrantError> {
if let Some(tree_core) = Weak::upgrade(&self.0) {
tree_core.lock_manager.acquire_grant()?;
}
Ok(Self(self.0.clone()))
}
#[inline]
#[must_use]
pub fn is_valid_for_node(&self, node: &Node<T>) -> bool {
node.ptr_eq_tree_core_weak(&self.0)
}
#[inline]
pub(crate) fn panic_if_invalid_for_node(&self, node: &Node<T>) {
if !self.is_valid_for_node(node) {
panic!("[precondition] the grant is not valid for the node of interest");
}
}
}
#[derive(Default, Debug)]
pub(crate) struct LockAggregatorForNode {
aggregated_count: usize,
}
impl LockAggregatorForNode {
#[inline]
#[must_use]
pub(crate) fn has_lock(&self) -> bool {
self.aggregated_count != 0
}
pub(crate) fn decrement_count<T>(&mut self, tree_core: &Rc<TreeCore<T>>) {
if self.aggregated_count == 0 {
panic!("[consistency] attempt to decrement aggregated lock count while it is zero");
}
self.aggregated_count -= 1;
if self.aggregated_count == 0 {
tree_core.lock_manager.release_any_lock();
}
}
pub(crate) fn increment_nonzero_count(&mut self) {
if self.aggregated_count == 0 {
panic!("[consistency] expected the lock aggregator already has some locks");
}
let new_count = self.aggregated_count.checked_add(1).unwrap_or_else(|| {
panic!("[precondition] attempt to acuqire too many locks for a node")
});
self.aggregated_count = new_count;
}
pub(crate) fn acquire_edit_prohibition<T>(
&mut self,
tree_core: &Rc<TreeCore<T>>,
) -> Result<(), HierarchyEditProhibitionError> {
tree_core.lock_manager.ensure_prohibition_acquirable()?;
if self.aggregated_count != 0 {
self.increment_nonzero_count();
} else {
tree_core.lock_manager.acquire_prohibition()?;
self.aggregated_count = 1;
}
Ok(())
}
pub(crate) fn acquire_edit_grant<T>(
&mut self,
tree_core: &Rc<TreeCore<T>>,
) -> Result<(), HierarchyEditGrantError> {
tree_core.lock_manager.ensure_grant_acquirable()?;
if self.aggregated_count != 0 {
self.increment_nonzero_count();
} else {
tree_core.lock_manager.acquire_grant()?;
self.aggregated_count = 1;
}
Ok(())
}
}