1 #![deny(unsafe_code)]
2 
3 //! Abstracting over accessing parts of stored value.
4 //!
5 //! Sometimes, there's a big globalish data structure (like a configuration for the whole program).
6 //! Then there are parts of the program that need access to up-to-date version of their *part* of
7 //! the configuration, but for reasons of code separation and reusability, it is not desirable to
8 //! pass the whole configuration to each of the parts.
9 //!
10 //! This module provides means to grant the parts access to the relevant subsets of such global
11 //! data structure while masking the fact it is part of the bigger whole from the component.
12 //!
13 //! Note that the [`cache`][crate::cache] module has its own [`Access`][crate::cache::Access] trait
14 //! that serves a similar purpose, but with cached access. The signatures are different, therefore
15 //! an incompatible trait.
16 //!
17 //! # The general idea
18 //!
19 //! Each part of the code accepts generic [`Access<T>`][Access] for the `T` of its interest. This
20 //! provides means to load current version of the structure behind the scenes and get only the
21 //! relevant part, without knowing what the big structure is.
22 //!
23 //! For technical reasons, the [`Access`] trait is not object safe. If type erasure is desired, it
24 //! is possible use the [`DynAccess`][crate::access::DynAccess] instead, which is object safe, but
25 //! slightly slower.
26 //!
27 //! For some cases, it is possible to use [`ArcSwapAny::map`]. If that is not flexible enough, the
28 //! [`Map`] type can be created directly.
29 //!
30 //! Note that the [`Access`] trait is also implemented for [`ArcSwapAny`] itself. Additionally,
31 //! there's the [`Constant`][crate::access::Constant] helper type, which is useful mostly for
32 //! testing (it doesn't allow reloading).
33 //!
34 //! # Performance
35 //!
36 //! In general, these utilities use [`ArcSwapAny::load`] internally and then apply the provided
37 //! transformation. This has several consequences:
38 //!
39 //! * Limitations of the [`load`][ArcSwapAny::load] apply ‒ including the recommendation to not
40 //!   hold the returned guard object for too long, but long enough to get consistency.
41 //! * The transformation should be cheap ‒ optimally just borrowing into the structure.
42 //!
43 //! # Examples
44 //!
45 //! ```rust
46 //! use std::sync::Arc;
47 //! use std::thread::{self, JoinHandle};
48 //! use std::time::Duration;
49 //!
50 //! use arc_swap::ArcSwap;
51 //! use arc_swap::access::{Access, Constant, Map};
52 //!
53 //! fn work_with_usize<A: Access<usize> + Send + 'static>(a: A) -> JoinHandle<()> {
54 //!     thread::spawn(move || {
55 //!         let mut value = 0;
56 //!         while value != 42 {
57 //!             let guard = a.load();
58 //!             value = *guard;
59 //!             println!("{}", value);
60 //!             // Not strictly necessary, but dropping the guard can free some resources, like
61 //!             // slots for tracking what values are still in use. We do it before the sleeping,
62 //!             // not at the end of the scope.
63 //!             drop(guard);
64 //!             thread::sleep(Duration::from_millis(50));
65 //!         }
66 //!     })
67 //! }
68 //!
69 //! // Passing the whole thing directly
70 //! // (If we kept another Arc to it, we could change the value behind the scenes)
71 //! work_with_usize(Arc::new(ArcSwap::from_pointee(42))).join().unwrap();
72 //!
73 //! // Passing a subset of a structure
74 //! struct Cfg {
75 //!     value: usize,
76 //! }
77 //!
78 //! let cfg = Arc::new(ArcSwap::from_pointee(Cfg { value: 0 }));
79 //! let thread = work_with_usize(Map::new(Arc::clone(&cfg), |cfg: &Cfg| &cfg.value));
80 //! cfg.store(Arc::new(Cfg { value: 42 }));
81 //! thread.join().unwrap();
82 //!
83 //! // Passing a constant that can't change. Useful mostly for testing purposes.
84 //! work_with_usize(Constant(42)).join().unwrap();
85 //! ```
86 
87 use std::marker::PhantomData;
88 use std::ops::Deref;
89 use std::rc::Rc;
90 use std::sync::Arc;
91 
92 use super::ref_cnt::RefCnt;
93 use super::strategy::Strategy;
94 use super::{ArcSwapAny, Guard};
95 
96 /// Abstracts over ways code can get access to a value of type `T`.
97 ///
98 /// This is the trait that parts of code will use when accessing a subpart of the big data
99 /// structure. See the [module documentation](index.html) for details.
100 pub trait Access<T> {
101     /// A guard object containing the value and keeping it alive.
102     ///
103     /// For technical reasons, the library doesn't allow direct access into the stored value. A
104     /// temporary guard object must be loaded, that keeps the actual value alive for the time of
105     /// use.
106     type Guard: Deref<Target = T>;
107 
108     /// The loading method.
109     ///
110     /// This returns the guard that holds the actual value. Should be called anew each time a fresh
111     /// value is needed.
load(&self) -> Self::Guard112     fn load(&self) -> Self::Guard;
113 }
114 
115 impl<T, A: Access<T>, P: Deref<Target = A>> Access<T> for P {
116     type Guard = A::Guard;
load(&self) -> Self::Guard117     fn load(&self) -> Self::Guard {
118         self.deref().load()
119     }
120 }
121 
122 impl<T: RefCnt, S: Strategy<T>> Access<T> for ArcSwapAny<T, S> {
123     type Guard = Guard<T, S>;
124 
load(&self) -> Self::Guard125     fn load(&self) -> Self::Guard {
126         self.load()
127     }
128 }
129 
130 #[derive(Debug)]
131 #[doc(hidden)]
132 pub struct DirectDeref<T: RefCnt, S: Strategy<T>>(Guard<T, S>);
133 
134 impl<T, S: Strategy<Arc<T>>> Deref for DirectDeref<Arc<T>, S> {
135     type Target = T;
deref(&self) -> &T136     fn deref(&self) -> &T {
137         self.0.deref().deref()
138     }
139 }
140 
141 impl<T, S: Strategy<Arc<T>>> Access<T> for ArcSwapAny<Arc<T>, S> {
142     type Guard = DirectDeref<Arc<T>, S>;
load(&self) -> Self::Guard143     fn load(&self) -> Self::Guard {
144         DirectDeref(self.load())
145     }
146 }
147 
148 impl<T, S: Strategy<Rc<T>>> Deref for DirectDeref<Rc<T>, S> {
149     type Target = T;
deref(&self) -> &T150     fn deref(&self) -> &T {
151         self.0.deref().deref()
152     }
153 }
154 
155 impl<T, S: Strategy<Rc<T>>> Access<T> for ArcSwapAny<Rc<T>, S> {
156     type Guard = DirectDeref<Rc<T>, S>;
load(&self) -> Self::Guard157     fn load(&self) -> Self::Guard {
158         DirectDeref(self.load())
159     }
160 }
161 
162 #[doc(hidden)]
163 pub struct DynGuard<T: ?Sized>(Box<dyn Deref<Target = T>>);
164 
165 impl<T: ?Sized> Deref for DynGuard<T> {
166     type Target = T;
deref(&self) -> &T167     fn deref(&self) -> &T {
168         &self.0
169     }
170 }
171 
172 /// An object-safe version of the [`Access`] trait.
173 ///
174 /// This can be used instead of the [`Access`] trait in case a type erasure is desired. This has
175 /// the effect of performance hit (due to boxing of the result and due to dynamic dispatch), but
176 /// makes certain code simpler and possibly makes the executable smaller.
177 ///
178 /// This is automatically implemented for everything that implements [`Access`].
179 ///
180 /// # Examples
181 ///
182 /// ```rust
183 /// use arc_swap::access::{Constant, DynAccess};
184 ///
185 /// fn do_something(value: Box<dyn DynAccess<usize> + Send>) {
186 ///     let v = value.load();
187 ///     println!("{}", *v);
188 /// }
189 ///
190 /// do_something(Box::new(Constant(42)));
191 /// ```
192 pub trait DynAccess<T> {
193     /// The equivalent of [`Access::load`].
load(&self) -> DynGuard<T>194     fn load(&self) -> DynGuard<T>;
195 }
196 
197 impl<T, A> DynAccess<T> for A
198 where
199     A: Access<T>,
200     A::Guard: 'static,
201 {
load(&self) -> DynGuard<T>202     fn load(&self) -> DynGuard<T> {
203         DynGuard(Box::new(Access::load(self)))
204     }
205 }
206 
207 /// [DynAccess] to [Access] wrapper.
208 ///
209 /// A workaround to allow double-dyn mapping, since `Box<dyn DynAccess>` doesn't implement [Access]
210 /// and [Map] needs that.
211 ///
212 /// ```rust
213 /// use std::sync::Arc;
214 ///
215 /// use arc_swap::ArcSwap;
216 /// use arc_swap::access::{AccessConvert, DynAccess, Map};
217 ///
218 /// struct Inner {
219 ///     val: usize,
220 /// }
221 ///
222 /// struct Middle {
223 ///     inner: Inner,
224 /// }
225 ///
226 /// struct Outer {
227 ///     middle: Middle,
228 /// }
229 ///
230 /// let outer = Arc::new(ArcSwap::from_pointee(Outer {
231 ///     middle: Middle {
232 ///         inner: Inner {
233 ///             val: 42,
234 ///         }
235 ///     }
236 /// }));
237 ///
238 /// let middle: Arc<dyn DynAccess<Middle>> =
239 ///     Arc::new(Map::new(outer, |outer: &Outer| &outer.middle));
240 /// let inner: Arc<dyn DynAccess<Inner>> =
241 ///     Arc::new(Map::new(AccessConvert(middle), |middle: &Middle| &middle.inner));
242 /// let guard = inner.load();
243 /// assert_eq!(42, guard.val);
244 /// ```
245 pub struct AccessConvert<D>(pub D);
246 
247 impl<T, D> Access<T> for AccessConvert<D>
248 where
249     D: Deref,
250     D::Target: DynAccess<T>,
251 {
252     type Guard = DynGuard<T>;
253 
load(&self) -> Self::Guard254     fn load(&self) -> Self::Guard {
255         self.0.load()
256     }
257 }
258 
259 #[doc(hidden)]
260 #[derive(Copy, Clone, Debug)]
261 pub struct MapGuard<G, F, T, R> {
262     guard: G,
263     projection: F,
264     _t: PhantomData<fn(&T) -> &R>,
265 }
266 
267 impl<G, F, T, R> Deref for MapGuard<G, F, T, R>
268 where
269     G: Deref<Target = T>,
270     F: Fn(&T) -> &R,
271 {
272     type Target = R;
deref(&self) -> &R273     fn deref(&self) -> &R {
274         (self.projection)(&self.guard)
275     }
276 }
277 
278 /// An adaptor to provide access to a part of larger structure.
279 ///
280 /// This is the *active* part of this module. Use the [module documentation](index.html) for the
281 /// details.
282 #[derive(Copy, Clone, Debug)]
283 pub struct Map<A, T, F> {
284     access: A,
285     projection: F,
286     _t: PhantomData<fn() -> T>,
287 }
288 
289 impl<A, T, F> Map<A, T, F> {
290     /// Creates a new instance.
291     ///
292     /// # Parameters
293     ///
294     /// * `access`: Access to the bigger structure. This is usually something like `Arc<ArcSwap>`
295     ///   or `&ArcSwap`. It is technically possible to use any other [`Access`] here, though, for
296     ///   example to sub-delegate into even smaller structure from a [`Map`] (or generic
297     ///   [`Access`]).
298     /// * `projection`: A function (or closure) responsible to providing a reference into the
299     ///   bigger bigger structure, selecting just subset of it. In general, it is expected to be
300     ///   *cheap* (like only taking reference).
new<R>(access: A, projection: F) -> Self where F: Fn(&T) -> &R + Clone,301     pub fn new<R>(access: A, projection: F) -> Self
302     where
303         F: Fn(&T) -> &R + Clone,
304     {
305         Map {
306             access,
307             projection,
308             _t: PhantomData,
309         }
310     }
311 }
312 
313 impl<A, F, T, R> Access<R> for Map<A, T, F>
314 where
315     A: Access<T>,
316     F: Fn(&T) -> &R + Clone,
317 {
318     type Guard = MapGuard<A::Guard, F, T, R>;
load(&self) -> Self::Guard319     fn load(&self) -> Self::Guard {
320         let guard = self.access.load();
321         MapGuard {
322             guard,
323             projection: self.projection.clone(),
324             _t: PhantomData,
325         }
326     }
327 }
328 
329 #[doc(hidden)]
330 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
331 pub struct ConstantDeref<T>(T);
332 
333 impl<T> Deref for ConstantDeref<T> {
334     type Target = T;
deref(&self) -> &T335     fn deref(&self) -> &T {
336         &self.0
337     }
338 }
339 
340 /// Access to an constant.
341 ///
342 /// This wraps a constant value to provide [`Access`] to it. It is constant in the sense that,
343 /// unlike [`ArcSwapAny`] and [`Map`], the loaded value will always stay the same (there's no
344 /// remote `store`).
345 ///
346 /// The purpose is mostly testing and plugging a parameter that works generically from code that
347 /// doesn't need the updating functionality.
348 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
349 pub struct Constant<T>(pub T);
350 
351 impl<T: Clone> Access<T> for Constant<T> {
352     type Guard = ConstantDeref<T>;
load(&self) -> Self::Guard353     fn load(&self) -> Self::Guard {
354         ConstantDeref(self.0.clone())
355     }
356 }
357 
358 #[cfg(test)]
359 mod tests {
360     use super::super::{ArcSwap, ArcSwapOption};
361 
362     use super::*;
363 
check_static_dispatch_direct<A: Access<usize>>(a: A)364     fn check_static_dispatch_direct<A: Access<usize>>(a: A) {
365         assert_eq!(42, *a.load());
366     }
367 
check_static_dispatch<A: Access<Arc<usize>>>(a: A)368     fn check_static_dispatch<A: Access<Arc<usize>>>(a: A) {
369         assert_eq!(42, **a.load());
370     }
371 
372     /// Tests dispatching statically from arc-swap works
373     #[test]
static_dispatch()374     fn static_dispatch() {
375         let a = ArcSwap::from_pointee(42);
376         check_static_dispatch_direct(&a);
377         check_static_dispatch(&a);
378         check_static_dispatch(a);
379     }
380 
check_dyn_dispatch_direct(a: &dyn DynAccess<usize>)381     fn check_dyn_dispatch_direct(a: &dyn DynAccess<usize>) {
382         assert_eq!(42, *a.load());
383     }
384 
check_dyn_dispatch(a: &dyn DynAccess<Arc<usize>>)385     fn check_dyn_dispatch(a: &dyn DynAccess<Arc<usize>>) {
386         assert_eq!(42, **a.load());
387     }
388 
389     /// Tests we can also do a dynamic dispatch of the companion trait
390     #[test]
dyn_dispatch()391     fn dyn_dispatch() {
392         let a = ArcSwap::from_pointee(42);
393         check_dyn_dispatch_direct(&a);
394         check_dyn_dispatch(&a);
395     }
396 
check_transition<A>(a: A) where A: Access<usize>, A::Guard: 'static,397     fn check_transition<A>(a: A)
398     where
399         A: Access<usize>,
400         A::Guard: 'static,
401     {
402         check_dyn_dispatch_direct(&a)
403     }
404 
405     /// Tests we can easily transition from the static dispatch trait to the dynamic one
406     #[test]
transition()407     fn transition() {
408         let a = ArcSwap::from_pointee(42);
409         check_transition(&a);
410         check_transition(a);
411     }
412 
413     /// Test we can dispatch from Arc<ArcSwap<_>> or similar.
414     #[test]
indirect()415     fn indirect() {
416         let a = Arc::new(ArcSwap::from_pointee(42));
417         check_static_dispatch(&a);
418         check_dyn_dispatch(&a);
419     }
420 
421     struct Cfg {
422         value: usize,
423     }
424 
425     #[test]
map()426     fn map() {
427         let a = ArcSwap::from_pointee(Cfg { value: 42 });
428         let map = a.map(|a: &Cfg| &a.value);
429         check_static_dispatch_direct(&map);
430         check_dyn_dispatch_direct(&map);
431     }
432 
433     #[test]
map_option_some()434     fn map_option_some() {
435         let a = ArcSwapOption::from_pointee(Cfg { value: 42 });
436         let map = a.map(|a: &Option<Arc<Cfg>>| a.as_ref().map(|c| &c.value).unwrap());
437         check_static_dispatch_direct(&map);
438         check_dyn_dispatch_direct(&map);
439     }
440 
441     #[test]
map_option_none()442     fn map_option_none() {
443         let a = ArcSwapOption::empty();
444         let map = a.map(|a: &Option<Arc<Cfg>>| a.as_ref().map(|c| &c.value).unwrap_or(&42));
445         check_static_dispatch_direct(&map);
446         check_dyn_dispatch_direct(&map);
447     }
448 
449     #[test]
constant()450     fn constant() {
451         let c = Constant(42);
452         check_static_dispatch_direct(&c);
453         check_dyn_dispatch_direct(&c);
454         check_static_dispatch_direct(c);
455     }
456 
457     #[test]
map_reload()458     fn map_reload() {
459         let a = ArcSwap::from_pointee(Cfg { value: 0 });
460         let map = a.map(|cfg: &Cfg| &cfg.value);
461         assert_eq!(0, *Access::load(&map));
462         a.store(Arc::new(Cfg { value: 42 }));
463         assert_eq!(42, *Access::load(&map));
464     }
465 }
466