1use crate::macros::cfg_log;
2use crate::*;
3
4#[allow(missing_debug_implementations)]
21pub struct RefValue<T>(Arc<Mutex<T>>, String);
22
23impl<T> Clone for RefValue<T> {
24 fn clone(&self) -> Self {
25 RefValue(self.0.clone(), self.1.clone())
26 }
27}
28
29impl<T> RefValue<T> {
30 fn new(k: String, v: T) -> Self {
31 Self(Arc::new(Mutex::new(v)), k)
32 }
33
34 fn set(&self, v: T) -> Result<(), ConfigError> {
35 *self.0.lock_c()? = v;
36 Ok(())
37 }
38
39 pub fn with<F: FnOnce(&T) -> R, R>(&self, f: F) -> Result<R, ConfigError> {
41 let g = self.0.lock_c()?;
42 Ok((f)(&*g))
43 }
44}
45impl<T: Clone> RefValue<T> {
46 pub fn get(&self) -> Result<T, ConfigError> {
48 self.with(|v| v.clone())
49 }
50}
51
52impl<T: FromConfig + Send + 'static> FromConfig for RefValue<T> {
53 fn from_config(
54 context: &mut ConfigContext<'_>,
55 value: Option<ConfigValue<'_>>,
56 ) -> Result<Self, ConfigError> {
57 if context.ref_value_flag {
58 return Err(ConfigError::RefValueRecursiveError);
59 }
60 context.ref_value_flag = true;
61 let v = do_from_config(context, value);
62 context.ref_value_flag = false;
63 if v.is_ok() {
64 cfg_log!(
65 log::Level::Debug,
66 "RefValue {} registered!",
67 context.current_key_str()
68 );
69 }
70 v
71 }
72}
73
74#[inline]
75fn do_from_config<T: FromConfig + Send + 'static>(
76 context: &mut ConfigContext<'_>,
77 value: Option<ConfigValue<'_>>,
78) -> Result<RefValue<T>, ConfigError> {
79 let v = RefValue::new(context.current_key(), T::from_config(context, value)?);
80 context.as_refresher().push(v.clone())?;
81 Ok(v)
82}
83
84trait Ref: Send {
85 fn refresh(&self, config: &Configuration) -> Result<(), ConfigError>;
86}
87
88impl<T: FromConfig + Send> Ref for RefValue<T> {
89 fn refresh(&self, config: &Configuration) -> Result<(), ConfigError> {
90 cfg_log!(log::Level::Debug, "RefValue {} refreshing...", &self.1);
91 self.set(config.get(&self.1)?)
92 }
93}
94
95pub(crate) struct Refresher {
96 max: usize,
97 refs: Mutex<Vec<Box<dyn Ref + Send + 'static>>>,
98}
99
100impl Refresher {
101 pub(crate) fn new() -> Self {
102 Self {
103 max: 1024,
104 refs: Mutex::new(vec![]),
105 }
106 }
107
108 fn push(&self, r: impl Ref + 'static) -> Result<(), ConfigError> {
109 let g = self.refs.try_lock_c()?;
110 if let Some(mut g) = g {
111 if g.len() >= self.max {
112 return Err(ConfigError::TooManyInstances(self.max));
113 }
114 g.push(Box::new(r));
115 Ok(())
116 } else {
117 Err(ConfigError::RefValueRecursiveError)
118 }
119 }
120
121 pub(crate) fn refresh(&self, c: &Configuration) -> Result<(), ConfigError> {
122 let g = self.refs.lock_c()?;
123 let it = g.iter();
124 for i in it {
125 i.refresh(c)?;
126 }
127 Ok(())
128 }
129}
130
131#[cfg(test)]
132mod test {
133 use std::sync::Arc;
134
135 use crate::{
136 source::{memory::HashSource, ConfigSource, ConfigSourceBuilder},
137 Mutex, *,
138 };
139
140 #[derive(FromConfig)]
141 struct A {
142 _ref_b: RefValue<B>,
143 }
144 #[derive(FromConfig)]
145 struct B {
146 _ref_c: RefValue<u8>,
147 }
148
149 macro_rules! should_err {
150 ($v:ident) => {
151 assert_eq!(true, $v.is_err());
152 match $v.err().unwrap() {
153 ConfigError::RefValueRecursiveError => {}
154 e => {
155 println!("{:?}", e);
156 assert_eq!(true, false)
157 }
158 }
159 };
160 }
161
162 #[test]
163 fn recursive_test() {
164 let config = Configuration::new();
165 let v = config.get::<A>("hello");
166 should_err!(v);
167 let v = config.get::<RefValue<B>>("hello");
168 should_err!(v);
169 let v = config.get::<RefValue<RefValue<u8>>>("hello");
170 should_err!(v);
171 }
172
173 struct R(Arc<Mutex<(u64, bool)>>);
174
175 impl ConfigSource for R {
176 fn name(&self) -> &str {
177 "r"
178 }
179
180 fn load(&self, builder: &mut ConfigSourceBuilder<'_>) -> Result<(), ConfigError> {
181 builder.set("hello", self.0.lock_c()?.0);
182 Ok(())
183 }
184
185 fn allow_refresh(&self) -> bool {
186 true
187 }
188
189 fn refreshable(&self) -> Result<bool, ConfigError> {
190 let mut g = self.0.lock_c()?;
191 let flag = g.1;
192 g.1 = false;
193 Ok(flag)
194 }
195 }
196
197 impl R {
198 fn set(&self, v: u64) {
199 *self.0.lock_c().unwrap() = (v, true);
200 }
201
202 fn get(&self) -> u64 {
203 self.0.lock_c().unwrap().0
204 }
205 }
206
207 macro_rules! should_eq {
208 ($config:ident: $r:ident. $v:ident = $i:ident) => {
209 $r.set($i);
210 assert_eq!(true, $config.refresh_ref().unwrap());
211 assert_eq!(false, $config.refresh_ref().unwrap());
212 assert_eq!($i, $v.get().unwrap());
213 assert_eq!(0, $config.get::<u64>("hello").unwrap());
214 };
215 }
216
217 #[test]
218 fn refresh_test() {
219 let r = R(Arc::new(Mutex::new((0, true))));
220 assert_eq!("r", r.name());
221 let config = Configuration::new()
222 .register_source(R(r.0.clone()))
223 .unwrap();
224 let v = config.get::<RefValue<u64>>("hello").unwrap();
225
226 for i in 0..1000 {
227 should_eq!(config: r.v = i);
228 }
229 }
230
231 macro_rules! should_eq_mut {
232 ($config:ident: $r:ident. $v:ident = $i:ident) => {
233 $r.set($i);
234 assert_eq!(true, $config.refresh().unwrap());
235 assert_eq!(false, $config.refresh().unwrap());
236 assert_eq!($i, $v.get().unwrap());
237 assert_eq!($i, $config.get::<u64>("hello").unwrap());
238 };
239 }
240 #[test]
241 fn refresh_mut_test() {
242 let r = R(Arc::new(Mutex::new((0, true))));
243 assert_eq!("r", r.name());
244 let mut config = Configuration::new()
245 .register_source(R(r.0.clone()))
246 .unwrap();
247 let v = config.get::<RefValue<u64>>("hello").unwrap();
248
249 for i in 0..1000 {
250 should_eq_mut!(config: r.v = i);
251 }
252 }
253
254 macro_rules! should_eq_2 {
255 ($config:ident: $r:ident.$s:ident. $v:ident = $i:ident) => {
256 $s.set($i);
257 assert_eq!(true, $config.refresh().unwrap());
258 assert_eq!(false, $config.refresh().unwrap());
259 assert_eq!($r.get(), $v.get().unwrap());
260 $r.set($i);
261 assert_eq!($i, $r.get());
262 assert_ne!($r.get(), $v.get().unwrap());
263 assert_eq!(true, $config.refresh().unwrap());
264 assert_eq!(false, $config.refresh().unwrap());
265 assert_eq!($i, $v.get().unwrap());
266 assert_eq!($i, $config.get::<u64>("hello").unwrap());
267 };
268 }
269
270 #[test]
271 fn multiple_source_refresh_test() {
272 let a = HashSource::new("name");
273 let r = R(Arc::new(Mutex::new((0, true))));
274 let s = R(Arc::new(Mutex::new((0, true))));
275 assert_eq!("r", r.name());
276 let mut config = Configuration::new()
277 .register_source(a)
278 .unwrap()
279 .register_source(R(r.0.clone()))
280 .unwrap()
281 .register_source(R(s.0.clone()))
282 .unwrap();
283 let v = config.get::<RefValue<u64>>("hello").unwrap();
284
285 for i in 1..1000 {
286 should_eq_2!(config: r.s.v = i);
287 }
288 }
289}