1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
#![allow(non_snake_case)]
#![allow(unused_parens)]
mod guard;
mod holder;
use std::sync::Arc;
use parking_lot::RawRwLock;
use parking_lot::lock_api::RwLockReadGuard;
use crate::guard::Guard;
use crate::holder::Holder;
/// HArcMut : Hyultis Arc Mut
/// store a content inside a Arc<RwLock<>> to be a mutable between thread
/// use a cloned "local" version of the content, for faster/simpler access
pub struct HArcMut<T>
where T: Clone
{
_shared: Arc<Holder<T>>,
_local: Holder<T>,
}
impl<T> HArcMut<T>
where T: Clone
{
pub fn new(data: T) -> Self
{
return HArcMut
{
_local: Holder::new(data.clone()),
_shared: Arc::new(Holder::new(data)),
};
}
/// get readonly content
pub fn get(&self) -> RwLockReadGuard<'_, RawRwLock, T>
{
self._local.updateIfOlder(self._shared.as_ref());
return self._local.Data.read();
}
/// update local and shared content via a guard
/// and readonly part by cloning on drop (*beware*: dropping guard is important to get shared and local updated and sync)
pub fn get_mut(&self) -> Guard<'_, T>
{
Guard{
context: self,
guarded: self._shared.Data.write()
}
}
/// update local and shared content (and readonly part by cloning)
/// this is a bit slower than get_mut, but dont need a drop.
/// note : I is simply ignored (QOL)
pub fn update<I>(&self, mut fnUpdate: impl FnMut(&mut T) -> I)
{
let tmp = &mut self._shared.Data.write();
fnUpdate(tmp);
let updatetime = self._shared.updateTime();
*self._local.TimeUpdate.write() = updatetime;
*self._local.Data.write() = tmp.clone();
}
/// if closure return "true" update local part by cloning the updated shared content
/// *beware if you update the &mut, but returning false* : shared and local data will be desync
pub fn updateIf(&self, mut fnUpdate: impl FnMut(&mut T) -> bool)
{
let tmp = &mut self._shared.Data.write();
if (fnUpdate(tmp))
{
let updatetime = self._shared.updateTime();
*self._local.TimeUpdate.write() = updatetime;
*self._local.Data.write() = tmp.clone();
}
}
/// must be regulary manually checked
/// if true, the local storage must drop this local instance
pub fn isWantDrop(&self) -> bool
{
self._local.updateIfOlder(self._shared.as_ref());
return *self._local.WantDrop.read();
}
/// used to set the state of shared intance to "Want drop"
/// and normally be used juste before dropping the local instance
pub fn setDrop(&self)
{
*self._shared.WantDrop.write() = true;
let time = self._shared.updateTime();
*self._local.WantDrop.write() = true;
*self._local.TimeUpdate.write() = time;
}
//////////////////// PRIVATE /////////////////
fn update_internal(&self, tmp : T)
{
let updatetime = self._shared.updateTime();
*self._local.TimeUpdate.write() = updatetime;
*self._local.Data.write() = tmp;
}
}
impl<T> Clone for HArcMut<T>
where T: Clone
{
fn clone(&self) -> Self {
return HArcMut {
_shared: self._shared.clone(),
_local: self._local.clone(),
};
}
}
/* Hope, one day ?
impl<T> HArcMut<T>
where T: Clone + Any
{
pub fn get_as<I: 'static>(&self) -> Option<RwLockReadGuard<'_,RawRwLock,I>>
{
self._local.updateIfOlder(self._shared.as_ref());
let tmp = &self._local.Data as &dyn Any;
return match tmp.downcast_ref::<RwLock<I>>() {
None => None,
Some(x) => {
Some(x.read())
}
};
}
pub fn get_mut_as<I>(&self) -> Option<Guard<'_, RwLockWriteGuard<'static,I>>>
where I: 'static + Clone,
RwLockWriteGuard<'static,I> : Clone
{
let tmp = &self._shared.Data as &dyn Any;
return match tmp.downcast_ref::<RwLock<I>>() {
None => None,
Some(x) => {
Guard::<I>{
context: self,
guarded: x.write()
}
}
};
}
}
*/