instance-copy-on-write 0.10.1

A MT-safe copy-on-write implementation for the data structures.
Documentation
/*-
 * instance-copy-on-write - a synchronization primitive based on copy-on-write.
 * 
 * Copyright (C) 2025 Aleksandr Morozov alex@4neko.org
 * 
 * The instance-copy-on-write crate can be redistributed and/or modified
 * under the terms of either of the following licenses:
 *
 *   1. The MIT License (MIT)
 */


use std::
{
    cell::RefCell, fmt, ops::{Deref, DerefMut}, rc::{Rc, Weak}
};

use crate::{ICoWLockTypes, ICowType};

/// A Single thread realization.

/// A read only guard. Implements [Deref] only. The guarded value is valid
/// all the time, even if the inner value was updated. The updated value
/// will not be visible in the current instance until `re-read` is 
/// performed.
#[derive(Debug)]
pub struct ICoWRead<'read, ITEM: Sized>
{
    /// Guarded value.
    pub(crate) item: Rc<ITEM>,

    /// A bind to base.
    bind: &'read ICoW<ITEM>
}

impl<'read, ITEM: Sized> Deref for ICoWRead<'read, ITEM>
{
    type Target = ITEM;

    fn deref(&self) -> &Self::Target
    {
        return &self.item;
    }
}

impl<'read, ITEM: Sized> ICoWRead<'read, ITEM>
{
    /// Consumes the itance and returns the read-only value.
    pub 
    fn into_inner(self) -> Rc<ITEM>
    {
        return self.item;
    }

    /// Returns the weak reference.
    pub 
    fn weak(&self) -> Weak<ITEM>
    {
        return Rc::downgrade(&self.item);
    }
}

impl<'read, ITEM: Sized + fmt::Debug + Copy> ICoWRead<'read, ITEM>
{
    /// Upgrades from [ICoWRead] `the self` to copy [ICoWCopy] which can 
    /// be commited to mainstream by using [Copy].
    pub 
    fn upgrade_copy(self) -> ICoWCopy<'read, ITEM> 
    {
        let new_item = *self.item;
        let bind = self.bind;

        return 
            ICoWCopy
            {
                prev_item: self, 
                new_item: new_item,
                inst: bind
            };
    }
}

impl<'read, ITEM: Sized + fmt::Debug + Clone> ICoWRead<'read, ITEM>
{
    /// Upgrades from [ICoWRead] `the self` to copy [ICoWCopy] which can 
    /// be commited to mainstream by using [Clone].
    pub 
    fn upgrade_clone_copy(self) -> ICoWCopy<'read, ITEM> 
    {
        let new_item = self.item.as_ref().clone();
        let bind = self.bind;

         return 
            ICoWCopy
            {
                prev_item: self, 
                new_item: new_item,
                inst: bind
            };
    }
}

impl<'read, ITEM: Sized + fmt::Debug + Default> ICoWRead<'read, ITEM>
{
    /// Upgrades from [ICoWRead] `the self` to copy [ICoWCopy] which can 
    /// be commited to mainstream by using [Default].
    pub 
    fn upgrade_default(self) -> ICoWCopy<'read, ITEM> 
    {
        let new_item = ITEM::default();
        let bind = self.bind;

         return 
            ICoWCopy
            {
                prev_item: self, 
                new_item: new_item,
                inst: bind
            };
    }
}

/// A write-guard which holds new value to which the new data is written. And
/// previous value too. This type of guard is not exclusive, so multiple
/// CoW operations may be performed in parallel which is not normally needed.
/// 
/// The changes made in the current instance becomes visible for the rest
/// of the threads only after commit.
#[derive(Debug)]
pub struct ICoWCopy<'copy, ITEM: Sized>
{
    /// A reference to previous value
    prev_item: ICoWRead<'copy, ITEM>,
    
    /// A freshly createc/copied/clonned item
    new_item: ITEM,

    /// A reference to base to avoid Send.
    inst: &'copy ICoW<ITEM>
}

impl<'copy, ITEM: Sized> Deref for ICoWCopy<'copy, ITEM>
{
    type Target = ITEM;

    fn deref(&self) -> &Self::Target
    {
        return &self.new_item;
    }
}

impl<'copy, ITEM: Sized> DerefMut for ICoWCopy<'copy, ITEM>
{
    fn deref_mut(&mut self) -> &mut Self::Target
    {
        return &mut self.new_item
    }
}

impl<'copy, ITEM: Sized> ICoWCopy<'copy, ITEM>
{
    /// Returns a reference to previous value. To access modified version use
    /// [Deref] or [DerefMut].
    pub 
    fn prev_val(&self) -> &ITEM
    {
        return &self.prev_item;
    }

    /// Commits the changes made in the guarded variable. A non-blocking
    /// function. It will not block the thread completly and returns the
    /// [ICoWError::WouldBlock] if attempt to grab the pointer atomically 
    /// fails in reasonable time. for blocking `commit` use 
    /// [Self::commit_blocking].
    pub 
    fn commit(self)
    {
        *self.inst.inner.borrow_mut() = Rc::new(self.new_item);

        return;
    }

    /// Drops the instance without commiting changes returning 
    /// a copy, clone, default, or new i.e what was in the `new` field
    /// of the instance.
    pub 
    fn into_inner(self) -> ITEM
    {
        return self.new_item;
    }
}

/// A main structure which implements CoW approach based on [RwLock]. The object 
/// stored inside can be read directly, but  modifying the `inner` value is 
/// performed using `CoW` copy-on-write approach. 
/// 
/// The `read` operations are faster than `write`, because in order to `write` a
/// more operations needs to be performed.
/// 
/// This is for Mutlithreading environment only. It will be usedless when using
/// in single-thread programs. For the single thread, use a `SICoW` which would
/// improve the performance.
/// 
/// The inner value must be either [Copy], [Clone], [Default], or provide 
/// new value manually. The copied value is modified and stored back either
/// shared or exclusive method. The exclusive lock prevents other CoW operations
/// guaranteeing the uniq write access.
/// 
/// ```ignore
/// #[derive(Debug, Clone)]
/// struct TestStruct { s: u32 }
/// 
/// let cow_val = ICoW::new(TestStruct{ s: 2 });
/// 
/// // read
/// let read0 = cow_val.read().unwrap();
/// // ...
/// drop(read0);
/// 
/// // write new non-exclusivly
/// let mut write0 = cow_val.try_clone_copy().unwrap();
/// write0.s = 3;
/// 
/// write0.commit().unwrap();
/// 
/// // write new exclusivly
/// let mut write0 = cow_val.try_clone_copy_exclusivly().unwrap();
/// write0.s = 3;
/// 
/// write0.commit().unwrap(); 
/// 
/// ```
#[derive(Debug)]
pub struct ICoW<ITEM: Sized>
{
    /// A rwlock protected CoW.
    inner: RefCell<Rc<ITEM>>,
}

impl<ITEM> ICowType for ICoW<ITEM>
{
    fn get_lock_type() -> ICoWLockTypes 
    {
        return ICoWLockTypes::RwLock;
    }
}

impl<ITEM> ICoW<ITEM>
{
    /// Initalizes a new instance.
    pub 
    fn new(item: ITEM) -> Self
    {
        return 
            Self
            { 
                inner: 
                    RefCell::new(Rc::new(item)),
            }
    }

    /// Attempts to read the inner value returning the guard. This function 
    /// blocks the current thread until the value becomes available. This
    /// can happen if exclusive copy-on-write is in progress.
    /// 
    /// # Returns 
    /// 
    /// An instance with clonned reference is returned.
    pub 
    fn read(&self) -> ICoWRead<'_, ITEM>
    {
        let lock = 
            self
                .inner
                .borrow();

        return ICoWRead{ item: lock.clone(), bind: self };
    }

    /// Updates old value to new value for the inner.
    pub 
    fn new_inplace(&self, new_item: ITEM)
    {
        let read = self.read();

        let ret = 
            ICoWCopy
            { 
                prev_item: read, 
                new_item: new_item, 
                inst: self 
            };

        ret.commit();

        return;
    }
}

impl<ITEM: fmt::Debug + Copy> ICoW<ITEM>
{
    /// Performs the copy of the inner value for writing.
    /// 
    /// Blocking function i.e always retruns the result.
    /// 
    /// # Returns
    /// 
    /// An [ICoWCopy] is returned.
    pub 
    fn copy(&self) -> ICoWCopy<'_, ITEM>
    {
        let read = self.read();

        let new_item = *read.item.as_ref();

        let ret = 
            ICoWCopy
            { 
                prev_item: read, 
                new_item: new_item, 
                inst: self 
            };

        return ret;
    }
}

impl<ITEM: fmt::Debug + Clone> ICoW<ITEM>
{
    /// > [!IMPORTANT]
    /// > Previously `clone()`. renamed to `clone_copy()` due to the 
    /// > conflict with [Clone].
    /// 
    /// Attempts to perform the clone of the inner value for writing.
    /// 
    /// Blocking function i.e always retruns the result.
    /// 
    /// # Returns
    /// 
    /// An [ICoWCopy] is returned.
    pub 
    fn clone_copy(&self) -> ICoWCopy<'_, ITEM>
    {
        let read = self.read();

        let new_item = read.item.as_ref().clone();

        let ret = 
            ICoWCopy
            { 
                prev_item: read, 
                new_item: new_item, 
                inst: self 
            };

        return ret;
    }
}

impl<ITEM: fmt::Debug + Default> ICoW<ITEM>
{
    /// Construct the guard from the [Default] of the inner value for writing.
    /// 
    /// Blocking function i.e always retruns the result.
    /// 
    /// # Returns
    /// 
    /// An [Option] is returned where the [Option::None] is returned if
    /// it failed.
    pub 
    fn from_default(&self) -> ICoWCopy<'_, ITEM>
    {
        let read = self.read();

        let new_item = ITEM::default();

        let ret = 
            ICoWCopy
            { 
                prev_item: read, 
                new_item: new_item, 
                inst: self 
            };

        return ret;
    }
}


#[cfg(test)]
mod test
{
    // mutex based specific tests goes there
}