1use gix_features::threading::{get_mut, get_ref, MutableOnDemand, OwnShared};
3use std::ops::Deref;
4
5#[derive(Debug)]
7pub struct FileSnapshot<T: std::fmt::Debug> {
8 value: T,
9 modified: std::time::SystemTime,
10}
11
12impl<T: std::fmt::Debug> FileSnapshot<T> {
14 pub fn new(value: T) -> Self {
19 FileSnapshot {
20 value,
21 modified: std::time::UNIX_EPOCH,
22 }
23 }
24}
25
26impl<T: std::fmt::Debug> From<T> for FileSnapshot<T> {
27 fn from(value: T) -> Self {
28 FileSnapshot::new(value)
29 }
30}
31
32impl<T: Clone + std::fmt::Debug> Clone for FileSnapshot<T> {
33 fn clone(&self) -> Self {
34 Self {
35 value: self.value.clone(),
36 modified: self.modified,
37 }
38 }
39}
40
41impl<T: Clone + std::fmt::Debug> FileSnapshot<T> {
42 pub fn into_owned_or_cloned(self: OwnShared<Self>) -> T {
44 match OwnShared::try_unwrap(self) {
45 Ok(this) => this.value,
46 Err(this) => this.value.clone(),
47 }
48 }
49}
50
51pub type SharedFileSnapshot<T> = OwnShared<FileSnapshot<T>>;
53
54#[derive(Debug, Default)]
59pub struct SharedFileSnapshotMut<T: std::fmt::Debug>(pub MutableOnDemand<Option<SharedFileSnapshot<T>>>);
60
61impl<T: std::fmt::Debug> Deref for FileSnapshot<T> {
62 type Target = T;
63
64 fn deref(&self) -> &Self::Target {
65 &self.value
66 }
67}
68
69impl<T: std::fmt::Debug> std::ops::DerefMut for FileSnapshot<T> {
70 fn deref_mut(&mut self) -> &mut Self::Target {
71 &mut self.value
72 }
73}
74
75impl<T: std::fmt::Debug> Deref for SharedFileSnapshotMut<T> {
76 type Target = MutableOnDemand<Option<SharedFileSnapshot<T>>>;
77
78 fn deref(&self) -> &Self::Target {
79 &self.0
80 }
81}
82
83impl<T: std::fmt::Debug> SharedFileSnapshotMut<T> {
84 pub fn new() -> Self {
88 SharedFileSnapshotMut(MutableOnDemand::new(None))
89 }
90
91 pub fn force_refresh<E>(
94 &self,
95 open: impl FnOnce() -> Result<Option<(std::time::SystemTime, T)>, E>,
96 ) -> Result<(), E> {
97 let mut state = get_mut(&self.0);
98 *state = open()?.map(|(modified, value)| OwnShared::new(FileSnapshot { value, modified }));
99 Ok(())
100 }
101
102 pub fn recent_snapshot<E>(
109 &self,
110 mut current_modification_time: impl FnMut() -> Option<std::time::SystemTime>,
111 open: impl FnOnce() -> Result<Option<T>, E>,
112 ) -> Result<Option<SharedFileSnapshot<T>>, E> {
113 let state = get_ref(self);
114 let recent_modification = current_modification_time();
115 let buffer = match (&*state, recent_modification) {
116 (None, None) => (*state).clone(),
117 (Some(_), None) => {
118 drop(state);
119 let mut state = get_mut(self);
120 *state = None;
121 (*state).clone()
122 }
123 (Some(snapshot), Some(modified_time)) => {
124 if snapshot.modified < modified_time {
125 drop(state);
126 let mut state = get_mut(self);
127
128 if let (Some(_snapshot), Some(modified_time)) = (&*state, current_modification_time()) {
129 *state = open()?.map(|value| {
130 OwnShared::new(FileSnapshot {
131 value,
132 modified: modified_time,
133 })
134 });
135 }
136
137 (*state).clone()
138 } else {
139 Some(snapshot.clone())
142 }
143 }
144 (None, Some(_modified_time)) => {
145 drop(state);
146 let mut state = get_mut(self);
147 if let (None, Some(modified_time)) = (&*state, current_modification_time()) {
150 *state = open()?.map(|value| {
151 OwnShared::new(FileSnapshot {
152 value,
153 modified: modified_time,
154 })
155 });
156 }
157 (*state).clone()
158 }
159 };
160 Ok(buffer)
161 }
162}