use std::ops::Deref;
use gix_features::threading::{get_mut, get_ref, MutableOnDemand, OwnShared};
#[derive(Debug)]
pub struct FileSnapshot<T: std::fmt::Debug> {
value: T,
modified: std::time::SystemTime,
}
impl<T: Clone + std::fmt::Debug> Clone for FileSnapshot<T> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
modified: self.modified,
}
}
}
pub type SharedFileSnapshot<T> = OwnShared<FileSnapshot<T>>;
#[derive(Debug, Default)]
pub struct SharedFileSnapshotMut<T: std::fmt::Debug>(pub MutableOnDemand<Option<SharedFileSnapshot<T>>>);
impl<T: std::fmt::Debug> Deref for FileSnapshot<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<T: std::fmt::Debug> Deref for SharedFileSnapshotMut<T> {
type Target = MutableOnDemand<Option<SharedFileSnapshot<T>>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: std::fmt::Debug> SharedFileSnapshotMut<T> {
pub fn new() -> Self {
SharedFileSnapshotMut(MutableOnDemand::new(None))
}
pub fn force_refresh<E>(
&self,
open: impl FnOnce() -> Result<Option<(std::time::SystemTime, T)>, E>,
) -> Result<(), E> {
let mut state = get_mut(&self.0);
*state = open()?.map(|(modified, value)| OwnShared::new(FileSnapshot { value, modified }));
Ok(())
}
pub fn recent_snapshot<E>(
&self,
mut current_modification_time: impl FnMut() -> Option<std::time::SystemTime>,
open: impl FnOnce() -> Result<Option<T>, E>,
) -> Result<Option<SharedFileSnapshot<T>>, E> {
let state = get_ref(self);
let recent_modification = current_modification_time();
let buffer = match (&*state, recent_modification) {
(None, None) => (*state).clone(),
(Some(_), None) => {
drop(state);
let mut state = get_mut(self);
*state = None;
(*state).clone()
}
(Some(snapshot), Some(modified_time)) => {
if snapshot.modified < modified_time {
drop(state);
let mut state = get_mut(self);
if let (Some(_snapshot), Some(modified_time)) = (&*state, current_modification_time()) {
*state = open()?.map(|value| {
OwnShared::new(FileSnapshot {
value,
modified: modified_time,
})
});
}
(*state).clone()
} else {
Some(snapshot.clone())
}
}
(None, Some(_modified_time)) => {
drop(state);
let mut state = get_mut(self);
if let (None, Some(modified_time)) = (&*state, current_modification_time()) {
*state = open()?.map(|value| {
OwnShared::new(FileSnapshot {
value,
modified: modified_time,
})
});
}
(*state).clone()
}
};
Ok(buffer)
}
}