arc_swap/
access.rs

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`] instead, which is object safe, but slightly slower.
25//!
26//! For some cases, it is possible to use [`ArcSwapAny::map`]. If that is not flexible enough, the
27//! [`Map`] type can be created directly.
28//!
29//! Note that the [`Access`] trait is also implemented for [`ArcSwapAny`] itself. Additionally,
30//! there's the [`Constant`] helper type, which is useful mostly for testing (it doesn't allow
31//! reloading).
32//!
33//! # Performance
34//!
35//! In general, these utilities use [`ArcSwapAny::load`] internally and then apply the provided
36//! transformation. This has several consequences:
37//!
38//! * Limitations of the [`load`][ArcSwapAny::load] apply ‒ including the recommendation to not
39//!   hold the returned guard object for too long, but long enough to get consistency.
40//! * The transformation should be cheap ‒ optimally just borrowing into the structure.
41//!
42//! # Examples
43//!
44//! ```rust
45//! use std::sync::Arc;
46//! use std::thread::{self, JoinHandle};
47//! use std::time::Duration;
48//!
49//! use arc_swap::ArcSwap;
50//! use arc_swap::access::{Access, Constant, Map};
51//!
52//! fn work_with_usize<A: Access<usize> + Send + 'static>(a: A) -> JoinHandle<()> {
53//!     thread::spawn(move || {
54//!         let mut value = 0;
55//!         while value != 42 {
56//!             let guard = a.load();
57//!             value = *guard;
58//!             println!("{}", value);
59//!             // Not strictly necessary, but dropping the guard can free some resources, like
60//!             // slots for tracking what values are still in use. We do it before the sleeping,
61//!             // not at the end of the scope.
62//!             drop(guard);
63//!             thread::sleep(Duration::from_millis(50));
64//!         }
65//!     })
66//! }
67//!
68//! // Passing the whole thing directly
69//! // (If we kept another Arc to it, we could change the value behind the scenes)
70//! work_with_usize(Arc::new(ArcSwap::from_pointee(42))).join().unwrap();
71//!
72//! // Passing a subset of a structure
73//! struct Cfg {
74//!     value: usize,
75//! }
76//!
77//! let cfg = Arc::new(ArcSwap::from_pointee(Cfg { value: 0 }));
78//! let thread = work_with_usize(Map::new(Arc::clone(&cfg), |cfg: &Cfg| &cfg.value));
79//! cfg.store(Arc::new(Cfg { value: 42 }));
80//! thread.join().unwrap();
81//!
82//! // Passing a constant that can't change. Useful mostly for testing purposes.
83//! work_with_usize(Constant(42)).join().unwrap();
84//! ```
85use core::marker::PhantomData;
86use core::ops::Deref;
87
88use crate::imports::{Arc, Box, Rc};
89
90use super::ref_cnt::RefCnt;
91use super::strategy::Strategy;
92use super::{ArcSwapAny, Guard};
93
94/// Abstracts over ways code can get access to a value of type `T`.
95///
96/// This is the trait that parts of code will use when accessing a subpart of the big data
97/// structure. See the [module documentation](index.html) for details.
98pub trait Access<T> {
99    /// A guard object containing the value and keeping it alive.
100    ///
101    /// For technical reasons, the library doesn't allow direct access into the stored value. A
102    /// temporary guard object must be loaded, that keeps the actual value alive for the time of
103    /// use.
104    type Guard: Deref<Target = T>;
105
106    /// The loading method.
107    ///
108    /// This returns the guard that holds the actual value. Should be called anew each time a fresh
109    /// value is needed.
110    fn load(&self) -> Self::Guard;
111}
112
113impl<T, A: Access<T> + ?Sized, P: Deref<Target = A>> Access<T> for P {
114    type Guard = A::Guard;
115    fn load(&self) -> Self::Guard {
116        self.deref().load()
117    }
118}
119
120impl<T> Access<T> for dyn DynAccess<T> + '_ {
121    type Guard = DynGuard<T>;
122
123    fn load(&self) -> Self::Guard {
124        self.load()
125    }
126}
127
128impl<T> Access<T> for dyn DynAccess<T> + '_ + Send {
129    type Guard = DynGuard<T>;
130
131    fn load(&self) -> Self::Guard {
132        self.load()
133    }
134}
135
136impl<T> Access<T> for dyn DynAccess<T> + '_ + Sync + Send {
137    type Guard = DynGuard<T>;
138
139    fn load(&self) -> Self::Guard {
140        self.load()
141    }
142}
143
144impl<T: RefCnt, S: Strategy<T>> Access<T> for ArcSwapAny<T, S> {
145    type Guard = Guard<T, S>;
146
147    fn load(&self) -> Self::Guard {
148        self.load()
149    }
150}
151
152#[derive(Debug)]
153#[doc(hidden)]
154pub struct DirectDeref<T: RefCnt, S: Strategy<T>>(Guard<T, S>);
155
156impl<T, S: Strategy<Arc<T>>> Deref for DirectDeref<Arc<T>, S> {
157    type Target = T;
158    fn deref(&self) -> &T {
159        self.0.deref().deref()
160    }
161}
162
163impl<T, S: Strategy<Arc<T>>> Access<T> for ArcSwapAny<Arc<T>, S> {
164    type Guard = DirectDeref<Arc<T>, S>;
165    fn load(&self) -> Self::Guard {
166        DirectDeref(self.load())
167    }
168}
169
170impl<T, S: Strategy<Rc<T>>> Deref for DirectDeref<Rc<T>, S> {
171    type Target = T;
172    fn deref(&self) -> &T {
173        self.0.deref().deref()
174    }
175}
176
177impl<T, S: Strategy<Rc<T>>> Access<T> for ArcSwapAny<Rc<T>, S> {
178    type Guard = DirectDeref<Rc<T>, S>;
179    fn load(&self) -> Self::Guard {
180        DirectDeref(self.load())
181    }
182}
183
184#[doc(hidden)]
185pub struct DynGuard<T: ?Sized>(Box<dyn Deref<Target = T>>);
186
187impl<T: ?Sized> Deref for DynGuard<T> {
188    type Target = T;
189    fn deref(&self) -> &T {
190        &self.0
191    }
192}
193
194/// An object-safe version of the [`Access`] trait.
195///
196/// This can be used instead of the [`Access`] trait in case a type erasure is desired. This has
197/// the effect of performance hit (due to boxing of the result and due to dynamic dispatch), but
198/// makes certain code simpler and possibly makes the executable smaller.
199///
200/// This is automatically implemented for everything that implements [`Access`].
201///
202/// # Examples
203///
204/// ```rust
205/// use arc_swap::access::{Constant, DynAccess};
206///
207/// fn do_something(value: Box<dyn DynAccess<usize> + Send>) {
208///     let v = value.load();
209///     println!("{}", *v);
210/// }
211///
212/// do_something(Box::new(Constant(42)));
213/// ```
214pub trait DynAccess<T> {
215    /// The equivalent of [`Access::load`].
216    fn load(&self) -> DynGuard<T>;
217}
218
219impl<T, A> DynAccess<T> for A
220where
221    A: Access<T>,
222    A::Guard: 'static,
223{
224    fn load(&self) -> DynGuard<T> {
225        DynGuard(Box::new(Access::load(self)))
226    }
227}
228
229/// [DynAccess] to [Access] wrapper.
230///
231/// In previous versions, `Box<dyn DynAccess>` didn't implement [Access], to use inside [Map] one
232/// could use this wrapper. Since then, a way was found to solve it. In most cases, this wrapper is
233/// no longer necessary.
234///
235/// This is left in place for two reasons:
236/// * Backwards compatibility.
237/// * Corner-cases not covered by the found solution. For example, trait inheritance in the form of
238///   `Box<dyn SomeTrait>` where `SomeTrait: Access` doesn't work out of the box and still needs
239///   this wrapper.
240///
241/// # Examples
242///
243/// The example is for the simple case (which is no longer needed, but may help as an inspiration).
244///
245/// ```rust
246/// use std::sync::Arc;
247///
248/// use arc_swap::ArcSwap;
249/// use arc_swap::access::{AccessConvert, DynAccess, Map};
250///
251/// struct Inner {
252///     val: usize,
253/// }
254///
255/// struct Middle {
256///     inner: Inner,
257/// }
258///
259/// struct Outer {
260///     middle: Middle,
261/// }
262///
263/// let outer = Arc::new(ArcSwap::from_pointee(Outer {
264///     middle: Middle {
265///         inner: Inner {
266///             val: 42,
267///         }
268///     }
269/// }));
270///
271/// let middle: Arc<dyn DynAccess<Middle>> =
272///     Arc::new(Map::new(outer, |outer: &Outer| &outer.middle));
273/// let inner: Arc<dyn DynAccess<Inner>> =
274///     Arc::new(Map::new(AccessConvert(middle), |middle: &Middle| &middle.inner));
275/// let guard = inner.load();
276/// assert_eq!(42, guard.val);
277/// ```
278pub struct AccessConvert<D>(pub D);
279
280impl<T, D> Access<T> for AccessConvert<D>
281where
282    D: Deref,
283    D::Target: DynAccess<T>,
284{
285    type Guard = DynGuard<T>;
286
287    fn load(&self) -> Self::Guard {
288        self.0.load()
289    }
290}
291
292#[doc(hidden)]
293#[derive(Copy, Clone, Debug)]
294pub struct MapGuard<G, F, T, R> {
295    guard: G,
296    projection: F,
297    _t: PhantomData<fn(&T) -> &R>,
298}
299
300impl<G, F, T, R> Deref for MapGuard<G, F, T, R>
301where
302    G: Deref<Target = T>,
303    F: Fn(&T) -> &R,
304{
305    type Target = R;
306    fn deref(&self) -> &R {
307        (self.projection)(&self.guard)
308    }
309}
310
311/// An adaptor to provide access to a part of larger structure.
312///
313/// This is the *active* part of this module. Use the [module documentation](index.html) for the
314/// details.
315#[derive(Copy, Clone, Debug)]
316pub struct Map<A, T, F> {
317    access: A,
318    projection: F,
319    _t: PhantomData<fn() -> T>,
320}
321
322impl<A, T, F> Map<A, T, F> {
323    /// Creates a new instance.
324    ///
325    /// # Parameters
326    ///
327    /// * `access`: Access to the bigger structure. This is usually something like `Arc<ArcSwap>`
328    ///   or `&ArcSwap`. It is technically possible to use any other [`Access`] here, though, for
329    ///   example to sub-delegate into even smaller structure from a [`Map`] (or generic
330    ///   [`Access`]).
331    /// * `projection`: A function (or closure) responsible to providing a reference into the
332    ///   bigger bigger structure, selecting just subset of it. In general, it is expected to be
333    ///   *cheap* (like only taking reference).
334    pub fn new<R>(access: A, projection: F) -> Self
335    where
336        F: Fn(&T) -> &R + Clone,
337    {
338        Map {
339            access,
340            projection,
341            _t: PhantomData,
342        }
343    }
344}
345
346impl<A, F, T, R> Access<R> for Map<A, T, F>
347where
348    A: Access<T>,
349    F: Fn(&T) -> &R + Clone,
350{
351    type Guard = MapGuard<A::Guard, F, T, R>;
352    fn load(&self) -> Self::Guard {
353        let guard = self.access.load();
354        MapGuard {
355            guard,
356            projection: self.projection.clone(),
357            _t: PhantomData,
358        }
359    }
360}
361
362#[doc(hidden)]
363#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
364pub struct ConstantDeref<T>(T);
365
366impl<T> Deref for ConstantDeref<T> {
367    type Target = T;
368    fn deref(&self) -> &T {
369        &self.0
370    }
371}
372
373/// Access to an constant.
374///
375/// This wraps a constant value to provide [`Access`] to it. It is constant in the sense that,
376/// unlike [`ArcSwapAny`] and [`Map`], the loaded value will always stay the same (there's no
377/// remote `store`).
378///
379/// The purpose is mostly testing and plugging a parameter that works generically from code that
380/// doesn't need the updating functionality.
381#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
382pub struct Constant<T>(pub T);
383
384impl<T: Clone> Access<T> for Constant<T> {
385    type Guard = ConstantDeref<T>;
386    fn load(&self) -> Self::Guard {
387        ConstantDeref(self.0.clone())
388    }
389}
390
391#[cfg(test)]
392mod tests {
393    use super::super::{ArcSwap, ArcSwapOption};
394
395    use super::*;
396
397    fn check_static_dispatch_direct<A: Access<usize>>(a: A) {
398        assert_eq!(42, *a.load());
399    }
400
401    fn check_static_dispatch<A: Access<Arc<usize>>>(a: A) {
402        assert_eq!(42, **a.load());
403    }
404
405    /// Tests dispatching statically from arc-swap works
406    #[test]
407    fn static_dispatch() {
408        let a = ArcSwap::from_pointee(42);
409        check_static_dispatch_direct(&a);
410        check_static_dispatch(&a);
411        check_static_dispatch(a);
412    }
413
414    fn check_dyn_dispatch_direct(a: &dyn DynAccess<usize>) {
415        assert_eq!(42, *a.load());
416    }
417
418    fn check_dyn_dispatch(a: &dyn DynAccess<Arc<usize>>) {
419        assert_eq!(42, **a.load());
420    }
421
422    /// Tests we can also do a dynamic dispatch of the companion trait
423    #[test]
424    fn dyn_dispatch() {
425        let a = ArcSwap::from_pointee(42);
426        check_dyn_dispatch_direct(&a);
427        check_dyn_dispatch(&a);
428    }
429
430    fn check_transition<A>(a: A)
431    where
432        A: Access<usize>,
433        A::Guard: 'static,
434    {
435        check_dyn_dispatch_direct(&a)
436    }
437
438    /// Tests we can easily transition from the static dispatch trait to the dynamic one
439    #[test]
440    fn transition() {
441        let a = ArcSwap::from_pointee(42);
442        check_transition(&a);
443        check_transition(a);
444    }
445
446    /// Test we can dispatch from Arc<ArcSwap<_>> or similar.
447    #[test]
448    fn indirect() {
449        let a = Arc::new(ArcSwap::from_pointee(42));
450        check_static_dispatch(&a);
451        check_dyn_dispatch(&a);
452    }
453
454    struct Cfg {
455        value: usize,
456    }
457
458    #[test]
459    fn map() {
460        let a = ArcSwap::from_pointee(Cfg { value: 42 });
461        let map = a.map(|a: &Cfg| &a.value);
462        check_static_dispatch_direct(&map);
463        check_dyn_dispatch_direct(&map);
464    }
465
466    #[test]
467    fn map_option_some() {
468        let a = ArcSwapOption::from_pointee(Cfg { value: 42 });
469        let map = a.map(|a: &Option<Arc<Cfg>>| a.as_ref().map(|c| &c.value).unwrap());
470        check_static_dispatch_direct(&map);
471        check_dyn_dispatch_direct(&map);
472    }
473
474    #[test]
475    fn map_option_none() {
476        let a = ArcSwapOption::empty();
477        let map = a.map(|a: &Option<Arc<Cfg>>| a.as_ref().map(|c| &c.value).unwrap_or(&42));
478        check_static_dispatch_direct(&map);
479        check_dyn_dispatch_direct(&map);
480    }
481
482    #[test]
483    fn constant() {
484        let c = Constant(42);
485        check_static_dispatch_direct(c);
486        check_dyn_dispatch_direct(&c);
487        check_static_dispatch_direct(c);
488    }
489
490    #[test]
491    fn map_reload() {
492        let a = ArcSwap::from_pointee(Cfg { value: 0 });
493        let map = a.map(|cfg: &Cfg| &cfg.value);
494        assert_eq!(0, *Access::load(&map));
495        a.store(Arc::new(Cfg { value: 42 }));
496        assert_eq!(42, *Access::load(&map));
497    }
498
499    // Compile tests for dynamic access
500    fn _expect_access<T>(_: impl Access<T>) {}
501
502    fn _dyn_access<T>(x: Box<dyn DynAccess<T> + '_>) {
503        _expect_access(x)
504    }
505
506    fn _dyn_access_send<T>(x: Box<dyn DynAccess<T> + '_ + Send>) {
507        _expect_access(x)
508    }
509
510    fn _dyn_access_send_sync<T>(x: Box<dyn DynAccess<T> + '_ + Send + Sync>) {
511        _expect_access(x)
512    }
513
514    #[test]
515    #[allow(clippy::arc_with_non_send_sync)] // Whatever, it's tests...
516    fn double_dyn_access_complex() {
517        struct Inner {
518            val: usize,
519        }
520
521        struct Middle {
522            inner: Inner,
523        }
524
525        struct Outer {
526            middle: Middle,
527        }
528
529        let outer = Arc::new(ArcSwap::from_pointee(Outer {
530            middle: Middle {
531                inner: Inner { val: 42 },
532            },
533        }));
534
535        let middle: Arc<dyn DynAccess<Middle>> =
536            Arc::new(Map::new(outer, |outer: &Outer| &outer.middle));
537        let inner: Arc<dyn DynAccess<Inner>> =
538            Arc::new(Map::new(middle, |middle: &Middle| &middle.inner));
539        // Damn. We have the DynAccess wrapper in scope and need to disambiguate the inner.load()
540        let guard = Access::load(&inner);
541        assert_eq!(42, guard.val);
542    }
543}