use std::sync::{Arc, RwLock};
use educe::Educe;
use crate::{Error, Result};
#[derive(Debug, Educe)]
#[educe(Default)]
#[cfg_attr(docsrs, doc(cfg(feature = "experimental-api")))]
#[cfg_attr(not(feature = "experimental-api"), allow(unreachable_pub))]
pub struct SharedMutArc<T> {
dir: RwLock<Option<Arc<T>>>,
}
#[cfg_attr(not(feature = "experimental-api"), allow(unreachable_pub))]
impl<T> SharedMutArc<T> {
pub fn new() -> Self {
SharedMutArc::default()
}
pub fn replace(&self, new_val: T) {
let mut w = self
.dir
.write()
.expect("Poisoned lock for directory reference");
*w = Some(Arc::new(new_val));
}
#[allow(unused)]
pub(crate) fn clear(&self) {
let mut w = self
.dir
.write()
.expect("Poisoned lock for directory reference");
*w = None;
}
pub fn get(&self) -> Option<Arc<T>> {
let r = self
.dir
.read()
.expect("Poisoned lock for directory reference");
r.as_ref().map(Arc::clone)
}
pub fn mutate<F, U>(&self, func: F) -> Result<U>
where
F: FnOnce(&mut T) -> Result<U>,
T: Clone,
{
let mut writeable = self
.dir
.write()
.expect("Poisoned lock for directory reference");
let dir = writeable.as_mut();
match dir {
None => Err(Error::DirectoryNotPresent), Some(arc) => func(Arc::make_mut(arc)),
}
}
}
#[cfg(test)]
mod test {
#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::clone_on_copy)]
#![allow(clippy::dbg_macro)]
#![allow(clippy::mixed_attributes_style)]
#![allow(clippy::print_stderr)]
#![allow(clippy::print_stdout)]
#![allow(clippy::single_char_pattern)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::unchecked_time_subtraction)]
#![allow(clippy::useless_vec)]
#![allow(clippy::needless_pass_by_value)]
use super::*;
#[test]
fn shared_mut_arc() {
let val: SharedMutArc<Vec<u32>> = SharedMutArc::new();
assert_eq!(val.get(), None);
val.replace(Vec::new());
assert_eq!(val.get().unwrap().as_ref()[..], Vec::<u32>::new());
val.mutate(|v| {
v.push(99);
Ok(())
})
.unwrap();
assert_eq!(val.get().unwrap().as_ref()[..], [99]);
val.clear();
assert_eq!(val.get(), None);
assert!(
val.mutate(|v| {
v.push(99);
Ok(())
})
.is_err()
);
}
}