mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
changed VData implementation. It will now always (exception: references) behave like a clone BUT it will avoid cloning whenever possible using Copy-on-Write-style logic.
This commit is contained in:
parent
79b169d951
commit
6f31abd5cc
@ -24,6 +24,8 @@ impl VData {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
eprintln!("VData: assign: overwriting my previous Arc because it was immutable.");
|
||||
*self = new_val.to();
|
||||
}
|
||||
pub fn inner_replace(&mut self, new_val: VDataEnum) -> VDataEnum {
|
||||
@ -39,14 +41,20 @@ impl VData {
|
||||
}
|
||||
/// returns the contained VDataEnum. May or may not clone.
|
||||
pub fn inner(self) -> VDataEnum {
|
||||
self.data().0.clone()
|
||||
// Arc::unwrap_or_clone(self.data).lock().unwrap().0
|
||||
let o = match Arc::try_unwrap(self.data) {
|
||||
Ok(v) => std::mem::replace(&mut v.lock().unwrap().0, VDataEnum::Bool(false)),
|
||||
Err(e) => e.lock().unwrap().0.clone(),
|
||||
};
|
||||
o
|
||||
}
|
||||
/// ensures self is mutable, then returns a new instance of VData that is also mutable and uses the same Arc<Mutex<_>>.
|
||||
pub fn clone_mut(&mut self) -> Self {
|
||||
// if not mutable, copy and set to mutable.
|
||||
self.make_mut();
|
||||
// now, both self and the returned value are set to mutable and share the same mutex.
|
||||
self.clone_mut_assume()
|
||||
let o = self.clone_mut_assume();
|
||||
o
|
||||
}
|
||||
/// like clone_mut, but assumes self is already mutable, and therefor does not need to mutate self
|
||||
/// as the Arc<Mutex<_>> will stay the same.
|
||||
@ -61,9 +69,17 @@ impl VData {
|
||||
/// makes self mutable. might clone.
|
||||
pub fn make_mut(&mut self) -> &mut Self {
|
||||
{
|
||||
let mut s = self.data.lock().unwrap();
|
||||
let mut s = self.data();
|
||||
if !s.1 {
|
||||
*s = (s.0.clone(), true);
|
||||
if Arc::strong_count(&self.data) > 1 {
|
||||
// not mutable yet - clone the value to avoid modifying an immutable one.
|
||||
#[cfg(debug_assertions)]
|
||||
eprintln!("VData: actually copying value due to mutation of an immutable shared value. (strong count: {})", Arc::strong_count(&self.data));
|
||||
*s = (s.0.clone(), true);
|
||||
} else {
|
||||
// value was immutable, but not shared, so we can just make it mutable.
|
||||
s.1 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
self
|
||||
@ -74,13 +90,39 @@ impl VData {
|
||||
}
|
||||
impl Clone for VData {
|
||||
fn clone(&self) -> Self {
|
||||
#[cfg(debug_assertions)]
|
||||
eprint!("VData: Clone: ");
|
||||
let mut d = self.data.lock().unwrap();
|
||||
// set to immutable, locking the data as-is.
|
||||
d.1 = false;
|
||||
// then return the same arc (-> avoid cloning)
|
||||
Self {
|
||||
data: Arc::clone(&self.data),
|
||||
}
|
||||
let o = if d.1 {
|
||||
if Arc::strong_count(&self.data) > 1 {
|
||||
// mutable, copy the value to avoid accidentally modifying it.
|
||||
#[cfg(debug_assertions)]
|
||||
eprint!(
|
||||
"copying value due to clone of a mutable shared value. (strong count: {})",
|
||||
Arc::strong_count(&self.data)
|
||||
);
|
||||
d.0.clone().to()
|
||||
} else {
|
||||
// mutable, but not shared. just change it to not being mutable.
|
||||
#[cfg(debug_assertions)]
|
||||
eprint!("setting mutable value to immutable to avoid copying. clone will happen when value is used mutably.");
|
||||
d.1 = false;
|
||||
// then return the same arc (-> avoid cloning)
|
||||
Self {
|
||||
data: Arc::clone(&self.data),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#[cfg(debug_assertions)]
|
||||
eprint!("immutably cloning immutable value. no copy necessary.");
|
||||
// immutable, return the same arc (-> avoid cloning)
|
||||
Self {
|
||||
data: Arc::clone(&self.data),
|
||||
}
|
||||
};
|
||||
#[cfg(debug_assertions)]
|
||||
eprintln!();
|
||||
o
|
||||
}
|
||||
}
|
||||
impl Debug for VData {
|
||||
|
Loading…
Reference in New Issue
Block a user