use std::
{
cell::{OnceCell, RefCell, UnsafeCell}, fmt, marker::PhantomData, ops::{Deref, DerefMut}, sync::{Arc, Weak, atomic::{AtomicI32, Ordering}}, time::Duration
};
use crossbeam_deque::{Injector, Steal};
use crossbeam_utils::{Backoff, sync::{Parker, Unparker}};
use crate::{ICoWError, ICoWLockTypes, ICowType};
#[derive(Debug)]
pub struct ICoWCopy<'copy, ITEM: Sized + fmt::Debug>
{
read: ICoWRead<'copy, ITEM>,
new_item: ITEM,
bind: &'copy ICoW<ITEM>,
}
impl<'copy, ITEM: Sized + fmt::Debug> Deref for ICoWCopy<'copy, ITEM>
{
type Target = ITEM;
fn deref(&self) -> &Self::Target
{
return &self.new_item;
}
}
impl<'copy, ITEM: Sized + fmt::Debug> DerefMut for ICoWCopy<'copy, ITEM>
{
fn deref_mut(&mut self) -> &mut Self::Target
{
return &mut self.new_item
}
}
impl<'copy, ITEM: Sized + fmt::Debug> ICoWCopy<'copy, ITEM>
{
pub
fn prev_val(&self) -> &ITEM
{
return &self.read;
}
pub
fn commit(self) -> Result<(), (ICoWError, Self)>
{
if let Err(err) = self.bind.int_lock_excl()
{
return Err((err, self));
}
self.bind.replace(self.new_item);
self.bind.unlock();
return Ok(());
}
pub
fn commit_blocking(self, ignore_excl: bool) -> Result<(), Self>
{
let mut inst = self;
let mut park_cnt = 1;
loop
{
let Err((errn, this)) = inst.commit()
else
{
return Ok(());
};
if errn == ICoWError::ExclusiveLockPending && ignore_excl == false
{
return Err(this);
}
this.bind.park(park_cnt);
park_cnt += 1;
inst = this;
}
}
pub
fn into_inner(self) -> ITEM
{
self.bind.wakeup();
return self.new_item;
}
}
#[derive(Debug)]
pub struct ICoWLock<'lock, ITEM: Sized + fmt::Debug>
{
prev_item: Arc<ITEM>,
pub(crate) item: OnceCell<ITEM>,
inst: &'lock ICoW<ITEM>,
}
impl<'lock, ITEM: Sized + fmt::Debug> Drop for ICoWLock<'lock, ITEM>
{
fn drop(&mut self)
{
if let Some(_item) = self.item.take()
{
self.inst.unlock();
}
return;
}
}
impl<'lock, ITEM: Sized + fmt::Debug> ICoWLock<'lock, ITEM>
{
pub
fn prev_val(&self) -> &ITEM
{
return self.prev_item.as_ref();
}
pub
fn commit(mut self)
{
self.inst.replace(self.item.take().unwrap());
self.inst.unlock();
return;
}
}
impl<'lock, ITEM: Sized + fmt::Debug> Deref for ICoWLock<'lock, ITEM>
{
type Target = ITEM;
fn deref(&self) -> &Self::Target
{
return self.item.get().unwrap();
}
}
impl<'lock, ITEM: Sized + fmt::Debug> DerefMut for ICoWLock<'lock, ITEM>
{
fn deref_mut(&mut self) -> &mut Self::Target
{
return self.item.get_mut().unwrap();
}
}
#[derive(Debug)]
pub struct ICoWWeakRead<'weak, ITEM: Sized + fmt::Debug>(Arc<ITEM>, bool, PhantomData<&'weak ()>);
impl<'weak, ITEM: Sized + fmt::Debug> 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 + fmt::Debug>
{
item: RefCell<Weak<ITEM>>,
base: Weak<ICoWInternal<ITEM>>,
}
unsafe impl<ITEM: Sized + fmt::Debug> Send for ICoWWeak<ITEM> {}
impl<ITEM: Sized + fmt::Debug> 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 + fmt::Debug>
{
pub(crate) item: Arc<ITEM>,
bind: &'read ICoW<ITEM>
}
impl<'read, ITEM: Sized + fmt::Debug> 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 + fmt::Debug> 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
{
read: self,
new_item: new_item,
bind: 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
{
read: self,
new_item: new_item,
bind: 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
{
read: self,
new_item: new_item,
bind: bind,
};
}
}
#[derive(Debug)]
pub struct ICoWInternal<ITEM: Sized + fmt::Debug>
{
op_cnt: AtomicI32,
inner: UnsafeCell<Arc<ITEM>>,
waker: Injector<Unparker>,
waker_lock: AtomicI32,
}
impl<ITEM: Sized + fmt::Debug> ICoWInternal<ITEM>
{
pub
fn new(item: ITEM) -> Self
{
return
Self
{
op_cnt: AtomicI32::new(1),
inner: UnsafeCell::new(Arc::new(item)),
waker: Injector::new(),
waker_lock: AtomicI32::new(0),
};
}
fn read(&self) -> Arc<ITEM>
{
let bkoff = Backoff::new();
let mut park_cnt = 1;
loop
{
let Some(read) = self.try_read()
else
{
if bkoff.is_completed() == false
{
bkoff.snooze();
}
else
{
self.park(park_cnt);
park_cnt += 1;
}
continue;
};
return read;
}
}
fn try_read(&self) -> Option<Arc<ITEM>>
{
let mut inner = self.op_cnt.load(Ordering::Relaxed);
loop
{
if inner > 0
{
let res =
self
.op_cnt
.compare_exchange_weak(
inner,
inner+1,
Ordering::SeqCst,
Ordering::Acquire
);
match res
{
Ok(_old) =>
{
let cow_read = unsafe{ self.inner.get().as_ref() }.unwrap().clone();
self.op_cnt.fetch_sub(1, Ordering::SeqCst);
return Some(cow_read);
},
Err(new_innwe) =>
{
inner = new_innwe;
continue;
}
}
}
else
{
return None;
}
}
}
fn park(&self, repeat: u64)
{
let backoff = Backoff::new();
let mut current = self.waker_lock.load(Ordering::Relaxed);
loop
{
if current <= 0
{
if repeat < 100000
{
PARKER
.with_borrow(|parker| parker.park_timeout(Duration::from_nanos(repeat * 100)));
}
return;
}
let res =
self
.waker_lock
.compare_exchange_weak(
current,
current+1,
Ordering::SeqCst,
Ordering::Acquire
);
if let Err(e) = res
{
current = e;
backoff.snooze();
continue;
}
let unparker =
PARKER
.with_borrow(|parker| parker.unparker().clone());
self.waker.push(unparker);
self.waker_lock.fetch_sub(1, Ordering::SeqCst);
PARKER
.with_borrow(|parker| parker.park());
return;
}
}
}
#[repr(transparent)]
#[derive(Debug, Clone)]
pub struct ICoW<ITEM: Sized + fmt::Debug>(Arc<ICoWInternal<ITEM>>);
unsafe impl<ITEM: Sized + fmt::Debug + Send> Send for ICoW<ITEM> {}
unsafe impl<ITEM: Sized + fmt::Debug + Send> Sync for ICoW<ITEM> {}
impl<ITEM: Sized + fmt::Debug> Drop for ICoW<ITEM>
{
fn drop(&mut self)
{
let mut current = 1;
let backoff = Backoff::new();
loop
{
let res =
self
.0
.op_cnt
.compare_exchange_weak(
current,
0,
Ordering::SeqCst,
Ordering::Acquire
);
if let Err(other) = res
{
if other >= 1
{
current = other;
continue;
}
else if other <= 0
{
backoff.snooze();
continue;
}
}
break;
}
self.unlock();
return;
}
}
impl<ITEM: Sized + fmt::Debug> ICowType for ICoW<ITEM>
{
fn get_lock_type() -> ICoWLockTypes
{
return ICoWLockTypes::Atomic;
}
}
thread_local! {
static PARKER: RefCell<Parker> = RefCell::new(Parker::new());
}
impl<ITEM: Sized + fmt::Debug> ICoW<ITEM>
{
pub
fn new(item: ITEM) -> Self
{
return Self( Arc::new( ICoWInternal::<ITEM>::new(item)) );
}
fn make_waker(&self)
{
self.0.waker_lock.store(1, Ordering::SeqCst);
return;
}
#[inline]
fn replace(&self, new: ITEM)
{
*unsafe { self.0.inner.get().as_mut() }.unwrap() = Arc::new(new);
}
#[inline]
fn unlock(&self)
{
self.0.op_cnt.store(1, Ordering::Relaxed);
self.wakeup();
}
fn wakeup(&self)
{
let backoff = Backoff::new();
let mut current = 1;
loop
{
let res =
self
.0
.waker_lock
.compare_exchange_weak(
current,
-1,
Ordering::SeqCst,
Ordering::Acquire
);
if let Err(e) = res
{
if e <= 0
{
return;
}
else
{
backoff.snooze();
current = e;
continue;
}
}
let backoff = Backoff::new();
if current > 1
{
current = -current;
loop
{
if self.0.waker_lock.load(Ordering::Relaxed) != current
{
backoff.snooze();
continue;
}
break;
}
}
if self.0.waker.is_empty() == false
{
loop
{
match self.0.waker.steal()
{
Steal::Empty =>
return,
Steal::Success(v) =>
{
v.unpark();
},
Steal::Retry =>
return,
}
}
}
return;
}
}
#[inline]
fn park(&self, repeat: u64)
{
self.0.park(repeat);
}
fn int_lock_excl(&self) -> Result<(), ICoWError>
{
let mut current = 1;
let backoff = Backoff::new();
loop
{
let res =
self
.0
.op_cnt
.compare_exchange_weak(
current,
0,
Ordering::SeqCst,
Ordering::Acquire
);
if let Err(other) = res
{
if other >= 1
{
current = other;
continue;
}
else if other <= 0
{
return Err(ICoWError::ExclusiveLockPending);
}
}
if current > 1
{
current = -(current - 1);
loop
{
let Err(other) =
self
.0
.op_cnt
.compare_exchange_weak(
current,
0,
Ordering::SeqCst,
Ordering::Acquire
)
else
{
break;
};
if backoff.is_completed() == false
{
backoff.snooze();
continue;
}
else
{
self.0.op_cnt.store(-(other + 1), Ordering::Relaxed);
return Err(ICoWError::WouldBlock);
}
}
}
return Ok(());
}
}
}
impl<ITEM: Sized + fmt::Debug> ICoW<ITEM>
{
pub
fn reader(&self) -> ICoWWeak<ITEM>
{
let readed = self.read();
return
ICoWWeak
{
item:
RefCell::new(readed.weak()),
base:
Arc::downgrade(&self.0),
};
}
pub
fn read(&self) -> ICoWRead<'_, ITEM>
{
return
ICoWRead
{
item:
self.0.read(),
bind:
self
};
}
pub
fn try_read(&self) -> Option<ICoWRead<'_, ITEM>>
{
return
self.0.try_read()
.map(|arc_val|
ICoWRead
{
item:
arc_val,
bind:
self
}
);
}
pub
fn new_exclusivly(&self, new_item: ITEM) -> ICoWLock<'_, ITEM>
{
let bkoff = Backoff::new();
let mut new_item_loc = new_item;
let mut park_cnt = 1;
loop
{
match self.try_new_exclusivly(new_item_loc)
{
Ok(res) =>
return res,
Err(ret_new_item) =>
{
if bkoff.is_completed() == true
{
self.park(park_cnt);
park_cnt += 1;
}
else
{
bkoff.snooze();
}
new_item_loc = ret_new_item;
}
}
}
}
pub
fn try_new_exclusivly(&self, new_item: ITEM) -> Result<ICoWLock<'_, ITEM>, ITEM>
{
if let Err(_) = self.int_lock_excl()
{
return Err(new_item);
}
self.make_waker();
return Ok(
ICoWLock
{
prev_item:
unsafe{ self.0.inner.get().as_ref() }.unwrap().clone(),
item:
OnceCell::from(new_item),
inst:
self
}
);
}
pub
fn try_new_inplace(&self, new_item: ITEM) -> Result<(), (ICoWError, ITEM)>
{
let read = self.try_read();
if let Some(read_res) = read
{
let ret =
ICoWCopy
{
read: read_res,
new_item: new_item,
bind: self
};
return ret.commit().map_err(|e| (e.0, e.1.new_item));
}
else
{
return Err((ICoWError::ExclusiveLockPending, new_item));
}
}
pub
fn try_new_exclusivly_inplace(&self, new_item: ITEM) -> Result<(), (ICoWError, ITEM)>
{
if let Err(err) = self.int_lock_excl()
{
return Err((err, new_item));
}
self.make_waker();
ICoWLock
{
prev_item:
unsafe{ self.0.inner.get().as_ref() }.unwrap().clone(),
item:
OnceCell::from(new_item),
inst:
self
}
.commit();
return Ok(());
}
}
impl<ITEM: Sized + 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
{
read: read,
new_item: new_item,
bind: 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
{
read: read,
new_item: new_item,
bind: self
};
return Some(ret);
}
fn internal_copy_excl(&self) -> Result<ICoWLock<'_, ITEM>, ICoWError>
{
self.int_lock_excl()?;
self.make_waker();
let prev_item = unsafe{ self.0.inner.get().as_ref() }.unwrap().clone();
let new_val = *prev_item.as_ref();
return Ok(
ICoWLock{ prev_item: prev_item, item: OnceCell::from(new_val), inst: self }
);
}
pub
fn copy_exclusivly(&self) -> ICoWLock<'_, ITEM>
{
let bkoff = Backoff::new();
let mut park_cnt = 1;
loop
{
let Some(res) = self.try_copy_exclusivly()
else
{
if bkoff.is_completed() == false
{
bkoff.snooze();
continue;
}
else
{
self.park(park_cnt);
park_cnt += 1;
continue;
}
};
return res;
}
}
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());
}
}
#[inline]
pub
fn try_copy_exclusivly(&self) -> Option<ICoWLock<'_, ITEM>>
{
return self.internal_copy_excl().ok();
}
}
impl<ITEM: Sized + 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
{
read: read,
new_item: new_item,
bind: 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
{
read: read,
new_item: new_item,
bind: self
};
return Some(ret);
}
fn internal_clone_copy_excl(&self) -> Result<ICoWLock<'_, ITEM>, ICoWError>
{
self.int_lock_excl()?;
self.make_waker();
let prev_item = unsafe{ self.0.inner.get().as_ref() }.unwrap().clone();
let new_val = prev_item.as_ref().clone();
return Ok(
ICoWLock{ prev_item: prev_item, item: OnceCell::from(new_val), 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 bkoff = Backoff::new();
let mut park_cnt = 1;
loop
{
let Some(res) = self.try_clone_copy_exclusivly()
else
{
if bkoff.is_completed() == false
{
bkoff.snooze();
continue;
}
else
{
self.park(park_cnt);
park_cnt += 1;
continue;
}
};
return res;
}
}
#[inline]
pub
fn try_clone_copy_exclusivly(&self) -> Option<ICoWLock<'_, ITEM>>
{
return self.internal_clone_copy_excl().ok();
}
}
impl<ITEM: Sized + fmt::Debug + Default> ICoW<ITEM>
{
pub
fn from_default(&self) -> ICoWCopy<'_, ITEM>
{
let read = self.read();
let new_item = ITEM::default();
let ret =
ICoWCopy
{
read: read,
new_item: new_item,
bind: self
};
return ret;
}
pub
fn try_default(&self) -> Option<ICoWCopy<'_, ITEM>>
{
let read = self.try_read()?;
let new_item = ITEM::default();
let ret =
ICoWCopy
{
read: read,
new_item: new_item,
bind: self
};
return Some(ret);
}
pub
fn default_exclusivly(&self) -> ICoWLock<'_, ITEM>
{
let bkoff = Backoff::new();
let mut park_cnt = 1;
loop
{
let Some(res) = self.try_default_exclusivly()
else
{
if bkoff.is_completed() == false
{
bkoff.snooze();
continue;
}
else
{
self.park(park_cnt);
park_cnt += 1;
continue;
}
};
return res;
}
}
pub
fn try_default_exclusivly(&self) -> Option<ICoWLock<'_, ITEM>>
{
if let Err(_) = self.int_lock_excl()
{
return None;
}
self.make_waker();
let prev_item = unsafe{ self.0.inner.get().as_ref() }.unwrap().clone();
let new_val = ITEM::default();
return Some(
ICoWLock{ prev_item: prev_item, item: OnceCell::from(new_val), inst: self }
);
}
}
#[cfg(test)]
mod test
{
}