use std::
{
cell::{OnceCell, RefCell},
fmt, marker::PhantomData,
ops::{Deref, DerefMut},
sync::
{
Arc, Mutex, MutexGuard, TryLockError, Weak, atomic::{AtomicBool, Ordering}
}
};
use crate::{ICoWError, ICoWLockTypes, ICowType};
#[derive(Debug)]
pub struct ICoWWeakRead<'weak, ITEM: Sized>(Arc<ITEM>, bool, PhantomData<&'weak ()>);
impl<'weak, ITEM: Sized> Deref for ICoWWeakRead<'weak, ITEM>
{
type Target = ITEM;
fn deref(&self) -> &Self::Target
{
return &self.0;
}
}
impl<'weak, ITEM: Sized + fmt::Debug> ICoWWeakRead<'weak, ITEM>
{
pub
fn item_updated(&self) -> bool
{
return self.1;
}
}
#[derive(Debug)]
pub struct ICoWWeak<ITEM: Sized>
{
item: RefCell<Weak<ITEM>>,
base: Weak<ICoWInternal<ITEM>>,
}
unsafe impl<ITEM: Sized> Send for ICoWWeak<ITEM> {}
impl<ITEM: Sized> ICoWWeak<ITEM>
{
pub
fn aquire<'weak>(&self) -> Option<ICoWWeakRead<'weak, ITEM>>
{
let Some(val) = self.item.borrow().upgrade()
else
{
let Some(cur_base) = self.base.upgrade()
else
{
return None;
};
let rd_only = cur_base.read();
*self.item.borrow_mut() = Arc::downgrade(&rd_only);
return Some(ICoWWeakRead(rd_only, true, PhantomData));
};
return Some(ICoWWeakRead(val, false, PhantomData));
}
}
#[derive(Debug)]
pub struct ICoWRead<'read, ITEM: Sized>
{
pub(crate) item: Arc<ITEM>,
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 + fmt::Debug + Clone> ICoWRead<'read, ITEM>
{
pub
fn clone_copy_into_inner(self) -> ITEM
{
return self.item.as_ref().clone();
}
}
impl<'read, ITEM: Sized + fmt::Debug + Copy> ICoWRead<'read, ITEM>
{
pub
fn copy_into_inner(self) -> ITEM
{
return *self.item.as_ref();
}
}
impl<'read, ITEM: Sized> ICoWRead<'read, ITEM>
{
pub
fn weak(&self) -> Weak<ITEM>
{
return Arc::downgrade(&self.item);
}
}
impl<'read, ITEM: Sized + fmt::Debug + Copy> ICoWRead<'read, ITEM>
{
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>
{
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>
{
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
};
}
}
#[derive(Debug)]
pub struct ICoWCopy<'copy, ITEM: Sized>
{
prev_item: ICoWRead<'copy, ITEM>,
new_item: ITEM,
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>
{
pub
fn prev_val(&self) -> &ITEM
{
return &self.prev_item;
}
pub
fn commit(self) -> Result<(), (ICoWError, Self)>
{
let write_lock =
self
.inst
.0
.inner
.try_lock();
let mut lock =
match write_lock
{
Ok(lock) =>
lock,
Err(TryLockError::Poisoned(lock_err)) =>
lock_err.into_inner(),
Err(TryLockError::WouldBlock) =>
{
if self.inst.0.exclusivly_locked.load(Ordering::Relaxed) == true
{
return Err((ICoWError::ExclusiveLockPending, self));
}
else
{
return Err((ICoWError::WouldBlock, self));
}
}
};
*lock = Arc::new(self.new_item);
return Ok(());
}
pub
fn commit_blocking(self, ignore_excl: bool) -> Result<(), Self>
{
if self.inst.0.exclusivly_locked.load(Ordering::Relaxed) == true && ignore_excl == false
{
return Err(self);
}
let mut write_lock =
self
.inst
.0
.inner
.lock()
.unwrap_or_else(|e| e.into_inner());
*write_lock = Arc::new(self.new_item);
return Ok(());
}
pub
fn into_inner(self) -> ITEM
{
return self.new_item;
}
}
#[derive(Debug)]
pub struct ICoWLock<'lock, ITEM: Sized>
{
prev_item: MutexGuard<'lock, Arc<ITEM>>,
pub(crate) item: OnceCell<ITEM>,
inst: &'lock ICoW<ITEM>
}
impl<'lock, ITEM: Sized> Drop for ICoWLock<'lock, ITEM>
{
fn drop(&mut self)
{
if let Some(_item) = self.item.take()
{
}
self.inst.0.exclusivly_locked.store(false, Ordering::Relaxed);
return;
}
}
impl<'lock, ITEM: Sized> ICoWLock<'lock, ITEM>
{
pub
fn prev_val(&self) -> &ITEM
{
return self.prev_item.as_ref();
}
#[inline]
pub
fn commit(mut self)
{
*self.prev_item = Arc::new(self.item.take().unwrap());
return;
}
}
impl<'lock, ITEM: Sized> Deref for ICoWLock<'lock, ITEM>
{
type Target = ITEM;
fn deref(&self) -> &Self::Target
{
return self.item.get().unwrap();
}
}
impl<'lock, ITEM: Sized> DerefMut for ICoWLock<'lock, ITEM>
{
fn deref_mut(&mut self) -> &mut Self::Target
{
return self.item.get_mut().unwrap()
}
}
#[derive(Debug)]
pub struct ICoWInternal<ITEM: Sized>
{
inner: Mutex<Arc<ITEM>>,
exclusivly_locked: AtomicBool,
}
impl<ITEM: Sized> ICoWInternal<ITEM>
{
pub
fn new(item: ITEM) -> Self
{
return
Self
{
inner:
Mutex::new(Arc::new(item)),
exclusivly_locked:
AtomicBool::new(false),
};
}
pub
fn read(&self) -> Arc<ITEM>
{
let lock =
self
.inner
.lock()
.unwrap_or_else(|e| e.into_inner());
return lock.clone();
}
fn try_read(&self) -> Option<Arc<ITEM>>
{
let lock_res =
self
.inner
.try_lock();
match lock_res
{
Ok(lock) =>
{
return Some(lock.clone());
},
Err(TryLockError::WouldBlock)=>
{
return None;
},
Err(TryLockError::Poisoned(lock)) =>
{
return Some(lock.into_inner().clone());
}
}
}
}
#[derive(Debug, Clone)]
pub struct ICoW<ITEM: Sized>(Arc<ICoWInternal<ITEM>>);
unsafe impl<ITEM: Sized + Send> Send for ICoW<ITEM> {}
unsafe impl<ITEM: Sized + Send> Sync for ICoW<ITEM> {}
impl<ITEM> ICowType for ICoW<ITEM>
{
fn get_lock_type() -> ICoWLockTypes
{
return ICoWLockTypes::RwLock;
}
}
impl<ITEM> ICoW<ITEM>
{
pub
fn new(item: ITEM) -> Self
{
return Self( Arc::new( ICoWInternal::<ITEM>::new(item)) );
}
pub
fn reader(&self) -> ICoWWeak<ITEM>
{
let readed = self.read();
return
ICoWWeak
{
item:
RefCell::new(readed.weak()),
base:
Arc::downgrade(&self.0),
};
}
#[inline]
pub
fn read(&self) -> ICoWRead<'_, ITEM>
{
let read_item =
self
.0
.read();
return ICoWRead{ item: read_item, bind: self };
}
#[inline]
pub
fn try_read(&self) -> Option<ICoWRead<'_, ITEM>>
{
return
self
.0
.try_read()
.map(|r|
ICoWRead{ item: r, bind: self }
);
}
pub
fn new_exclusivly(&self, new_item: ITEM) -> ICoWLock<'_, ITEM>
{
let write_lock =
self
.0
.inner
.lock()
.map_or_else(|e| e.into_inner(), |v| v);
self.0.exclusivly_locked.store(true, Ordering::Relaxed);
return
ICoWLock{ prev_item: write_lock, item: OnceCell::from(new_item), inst: self };
}
pub
fn try_new_exclusivly(&self, new_item: ITEM) -> Result<ICoWLock<'_, ITEM>, ITEM>
{
let write_lock =
match self.0.inner.try_lock()
{
Ok(r) => r,
Err(TryLockError::Poisoned(e)) => e.into_inner(),
Err(TryLockError::WouldBlock) =>
return Err(new_item),
};
self.0.exclusivly_locked.store(true, Ordering::Relaxed);
return Ok(
ICoWLock{ prev_item: write_lock, item: OnceCell::from(new_item), inst: self }
);
}
pub
fn try_new_inplace(&self, new_item: ITEM) -> Result<(), (ICoWError, ITEM)>
{
if let Some(read) = self.try_read()
{
let ret =
ICoWCopy
{
prev_item: read,
new_item: new_item,
inst: self
};
return ret.commit().map_err(|e| (e.0, e.1.new_item));
}
else
{
return Err((ICoWError::WouldBlock, new_item));
}
}
pub
fn try_new_exclusivly_inplace(&self, new_item: ITEM) -> Result<(), (ICoWError, ITEM)>
{
let write_lock =
match self.0.inner.try_lock()
{
Ok(lock) =>
lock,
Err(TryLockError::Poisoned(e)) =>
e.into_inner(),
Err(TryLockError::WouldBlock) =>
{
if self.0.exclusivly_locked.load(Ordering::Relaxed) == true
{
return Err((ICoWError::ExclusiveLockPending, new_item));
}
else
{
return Err((ICoWError::WouldBlock, new_item));
}
}
};
self.0.exclusivly_locked.store(true, Ordering::Relaxed);
let ret =
ICoWLock{ prev_item: write_lock, item: OnceCell::from(new_item), inst: self };
ret.commit();
return Ok(());
}
}
impl<ITEM: fmt::Debug + Copy> ICoW<ITEM>
{
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;
}
pub
fn try_copy(&self) -> Option<ICoWCopy<'_, ITEM>>
{
let read = self.try_read()?;
let new_item = *read.item.as_ref();
let ret =
ICoWCopy
{
prev_item: read,
new_item: new_item,
inst: self
};
return Some(ret);
}
pub
fn copy_exclusivly(&self) -> ICoWLock<'_, ITEM>
{
let write_lock =
self
.0
.inner
.lock()
.map_or_else(|e| e.into_inner(), |v| v);
self.0.exclusivly_locked.store(true, Ordering::SeqCst);
let new_item = *write_lock.as_ref();
return
ICoWLock{ prev_item: write_lock, item: OnceCell::from(new_item), inst: self };
}
fn internal_copy_excl(&self) -> Result<ICoWLock<'_, ITEM>, ICoWError>
{
let write_lock =
match self.0.inner.try_lock()
{
Ok(r) => r,
Err(TryLockError::Poisoned(e)) => e.into_inner(),
Err(TryLockError::WouldBlock) =>
{
if self.0.exclusivly_locked.load(Ordering::Relaxed) == true
{
return Err(ICoWError::ExclusiveLockPending);
}
else
{
return Err(ICoWError::WouldBlock);
}
}
};
self.0.exclusivly_locked.store(true, Ordering::SeqCst);
let new_item = *write_lock.as_ref();
return Ok(
ICoWLock{ prev_item: write_lock, item: OnceCell::from(new_item), inst: self }
);
}
pub
fn copy_exclusive_or_read(&self) -> Result<ICoWLock<'_, ITEM>, ICoWRead<'_, ITEM>>
{
loop
{
let res = self.internal_copy_excl();
if let Err(err) = res
{
if err == ICoWError::WouldBlock
{
continue;
}
return Err(self.read());
}
return Ok(res.unwrap());
}
}
pub
fn try_copy_exclusivly(&self) -> Option<ICoWLock<'_, ITEM>>
{
return self.internal_copy_excl().ok();
}
}
impl<ITEM: fmt::Debug + Clone> ICoW<ITEM>
{
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;
}
pub
fn try_clone_copy(&self) -> Option<ICoWCopy<'_, ITEM>>
{
let read = self.try_read()?;
let new_item = read.item.as_ref().clone();
let ret =
ICoWCopy
{
prev_item: read,
new_item: new_item,
inst: self
};
return Some(ret);
}
fn internal_clone_copy_excl(&self) -> Result<ICoWLock<'_, ITEM>, ICoWError>
{
let write_lock =
match self.0.inner.try_lock()
{
Ok(r) => r,
Err(TryLockError::Poisoned(e)) => e.into_inner(),
Err(TryLockError::WouldBlock) =>
{
if self.0.exclusivly_locked.load(Ordering::Relaxed) == true
{
return Err(ICoWError::ExclusiveLockPending);
}
else
{
return Err(ICoWError::WouldBlock);
}
}
};
self.0.exclusivly_locked.store(true, Ordering::Relaxed);
let new_item = write_lock.as_ref().clone();
return Ok(
ICoWLock{ prev_item: write_lock, item: OnceCell::from(new_item), inst: self }
);
}
pub
fn clone_copy_exclus_or_read(&self) -> Result<ICoWLock<'_, ITEM>, ICoWRead<'_, ITEM>>
{
loop
{
let res = self.internal_clone_copy_excl();
if let Err(err) = res
{
if err == ICoWError::WouldBlock
{
continue;
}
return Err(self.read());
}
return Ok(res.unwrap());
}
}
pub
fn clone_copy_exclusivly(&self) -> ICoWLock<'_, ITEM>
{
let write_lock =
self
.0
.inner
.lock()
.map_or_else(|e| e.into_inner(), |v| v);
self.0.exclusivly_locked.store(true, Ordering::Relaxed);
let new_item = write_lock.as_ref().clone();
return
ICoWLock{ prev_item: write_lock, item: OnceCell::from(new_item), inst: self };
}
#[inline]
pub
fn try_clone_copy_exclusivly(&self) -> Option<ICoWLock<'_, ITEM>>
{
return self.internal_clone_copy_excl().ok();
}
}
impl<ITEM: fmt::Debug + Default> ICoW<ITEM>
{
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;
}
pub
fn try_default(&self) -> Option<ICoWCopy<'_, ITEM>>
{
let read = self.try_read()?;
let new_item = ITEM::default();
let ret =
ICoWCopy
{
prev_item: read,
new_item: new_item,
inst: self
};
return Some(ret);
}
pub
fn default_exclusivly(&self) -> ICoWLock<'_, ITEM>
{
let write_lock =
self
.0
.inner
.lock()
.map_or_else(|e| e.into_inner(), |v| v);
self.0.exclusivly_locked.store(true, Ordering::Relaxed);
let new_item = ITEM::default();
return
ICoWLock{ prev_item: write_lock, item: OnceCell::from(new_item), inst: self };
}
pub
fn try_default_exclusivly(&self) -> Option<ICoWLock<'_, ITEM>>
{
let write_lock =
match self.0.inner.try_lock()
{
Ok(r) => r,
Err(TryLockError::Poisoned(e)) => e.into_inner(),
Err(TryLockError::WouldBlock) =>
return None
};
self.0.exclusivly_locked.store(true, Ordering::Relaxed);
let new_item = ITEM::default();
return Some(
ICoWLock{ prev_item: write_lock, item: OnceCell::from(new_item), inst: self }
);
}
}
#[cfg(test)]
mod test
{
}