use crate::{SnapshotLock, SnapshotLockReadGuard, SnapshotLockWriteGuard};
use arc_swap::ArcSwap;
use std::marker::PhantomData;
use std::ops::Deref;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, RwLock, RwLockWriteGuard};
impl<T: Clone> SnapshotLock<T, RwLock<(T, usize)>> {
pub fn new(inner: T) -> Self {
Self {
inner: RwLock::new((inner.clone(), 0)),
latest: ArcSwap::new(Arc::new(inner)),
latest_version: AtomicUsize::new(0),
}
}
pub fn write(&self) -> SnapshotLockWriteGuard<'_, T, RwLockWriteGuard<'_, (T, usize)>> {
let mut guard = self.inner.write().unwrap();
guard.1 += 1; SnapshotLockWriteGuard(guard, PhantomData)
}
pub fn read(&self) -> SnapshotLockReadGuard<T> {
if let Ok(read) = self.inner.try_read() {
let (data, version) = read.deref();
if self.latest_version.swap(*version, Ordering::Acquire) < *version {
self.latest.store(Arc::new(data.clone()));
}
}
SnapshotLockReadGuard(arc_swap::Guard::into_inner(self.latest.load()))
}
}