1use std::ops::Deref;
3
4use gix_features::threading::{get_mut, get_ref, MutableOnDemand, OwnShared};
5
6#[derive(Debug)]
8pub struct FileSnapshot<T: std::fmt::Debug> {
9 value: T,
10 modified: std::time::SystemTime,
11}
12
13impl<T: std::fmt::Debug> FileSnapshot<T> {
15 pub fn new(value: T) -> Self {
20 FileSnapshot {
21 value,
22 modified: std::time::UNIX_EPOCH,
23 }
24 }
25}
26
27impl<T: std::fmt::Debug> From<T> for FileSnapshot<T> {
28 fn from(value: T) -> Self {
29 FileSnapshot::new(value)
30 }
31}
32
33impl<T: Clone + std::fmt::Debug> Clone for FileSnapshot<T> {
34 fn clone(&self) -> Self {
35 Self {
36 value: self.value.clone(),
37 modified: self.modified,
38 }
39 }
40}
41
42pub type SharedFileSnapshot<T> = OwnShared<FileSnapshot<T>>;
44
45#[derive(Debug, Default)]
50pub struct SharedFileSnapshotMut<T: std::fmt::Debug>(pub MutableOnDemand<Option<SharedFileSnapshot<T>>>);
51
52impl<T: std::fmt::Debug> Deref for FileSnapshot<T> {
53 type Target = T;
54
55 fn deref(&self) -> &Self::Target {
56 &self.value
57 }
58}
59
60impl<T: std::fmt::Debug> std::ops::DerefMut for FileSnapshot<T> {
61 fn deref_mut(&mut self) -> &mut Self::Target {
62 &mut self.value
63 }
64}
65
66impl<T: std::fmt::Debug> Deref for SharedFileSnapshotMut<T> {
67 type Target = MutableOnDemand<Option<SharedFileSnapshot<T>>>;
68
69 fn deref(&self) -> &Self::Target {
70 &self.0
71 }
72}
73
74impl<T: std::fmt::Debug> SharedFileSnapshotMut<T> {
75 pub fn new() -> Self {
79 SharedFileSnapshotMut(MutableOnDemand::new(None))
80 }
81
82 pub fn force_refresh<E>(
85 &self,
86 open: impl FnOnce() -> Result<Option<(std::time::SystemTime, T)>, E>,
87 ) -> Result<(), E> {
88 let mut state = get_mut(&self.0);
89 *state = open()?.map(|(modified, value)| OwnShared::new(FileSnapshot { value, modified }));
90 Ok(())
91 }
92
93 pub fn recent_snapshot<E>(
100 &self,
101 mut current_modification_time: impl FnMut() -> Option<std::time::SystemTime>,
102 open: impl FnOnce() -> Result<Option<T>, E>,
103 ) -> Result<Option<SharedFileSnapshot<T>>, E> {
104 let state = get_ref(self);
105 let recent_modification = current_modification_time();
106 let buffer = match (&*state, recent_modification) {
107 (None, None) => (*state).clone(),
108 (Some(_), None) => {
109 drop(state);
110 let mut state = get_mut(self);
111 *state = None;
112 (*state).clone()
113 }
114 (Some(snapshot), Some(modified_time)) => {
115 if snapshot.modified < modified_time {
116 drop(state);
117 let mut state = get_mut(self);
118
119 if let (Some(_snapshot), Some(modified_time)) = (&*state, current_modification_time()) {
120 *state = open()?.map(|value| {
121 OwnShared::new(FileSnapshot {
122 value,
123 modified: modified_time,
124 })
125 });
126 }
127
128 (*state).clone()
129 } else {
130 Some(snapshot.clone())
133 }
134 }
135 (None, Some(_modified_time)) => {
136 drop(state);
137 let mut state = get_mut(self);
138 if let (None, Some(modified_time)) = (&*state, current_modification_time()) {
141 *state = open()?.map(|value| {
142 OwnShared::new(FileSnapshot {
143 value,
144 modified: modified_time,
145 })
146 });
147 }
148 (*state).clone()
149 }
150 };
151 Ok(buffer)
152 }
153}