#![deny(unsafe_code)] //! Abstracting over accessing parts of stored value. //! //! Sometimes, there's a big globalish data structure (like a configuration for the whole program). //! Then there are parts of the program that need access to up-to-date version of their *part* of //! the configuration, but for reasons of code separation and reusability, it is not desirable to //! pass the whole configuration to each of the parts. //! //! This module provides means to grant the parts access to the relevant subsets of such global //! data structure while masking the fact it is part of the bigger whole from the component. //! //! Note that the [`cache`][crate::cache] module has its own [`Access`][crate::cache::Access] trait //! that serves a similar purpose, but with cached access. The signatures are different, therefore //! an incompatible trait. //! //! # The general idea //! //! Each part of the code accepts generic [`Access`][Access] for the `T` of its interest. This //! provides means to load current version of the structure behind the scenes and get only the //! relevant part, without knowing what the big structure is. //! //! For technical reasons, the [`Access`] trait is not object safe. If type erasure is desired, it //! is possible use the [`DynAccess`][crate::access::DynAccess] instead, which is object safe, but //! slightly slower. //! //! For some cases, it is possible to use [`ArcSwapAny::map`]. If that is not flexible enough, the //! [`Map`] type can be created directly. //! //! Note that the [`Access`] trait is also implemented for [`ArcSwapAny`] itself. Additionally, //! there's the [`Constant`][crate::access::Constant] helper type, which is useful mostly for //! testing (it doesn't allow reloading). //! //! # Performance //! //! In general, these utilities use [`ArcSwapAny::load`] internally and then apply the provided //! transformation. This has several consequences: //! //! * Limitations of the [`load`][ArcSwapAny::load] apply ‒ including the recommendation to not //! hold the returned guard object for too long, but long enough to get consistency. //! * The transformation should be cheap ‒ optimally just borrowing into the structure. //! //! # Examples //! //! ```rust //! use std::sync::Arc; //! use std::thread::{self, JoinHandle}; //! use std::time::Duration; //! //! use arc_swap::ArcSwap; //! use arc_swap::access::{Access, Constant, Map}; //! //! fn work_with_usize + Send + 'static>(a: A) -> JoinHandle<()> { //! thread::spawn(move || { //! let mut value = 0; //! while value != 42 { //! let guard = a.load(); //! value = *guard; //! println!("{}", value); //! // Not strictly necessary, but dropping the guard can free some resources, like //! // slots for tracking what values are still in use. We do it before the sleeping, //! // not at the end of the scope. //! drop(guard); //! thread::sleep(Duration::from_millis(50)); //! } //! }) //! } //! //! // Passing the whole thing directly //! // (If we kept another Arc to it, we could change the value behind the scenes) //! work_with_usize(Arc::new(ArcSwap::from_pointee(42))).join().unwrap(); //! //! // Passing a subset of a structure //! struct Cfg { //! value: usize, //! } //! //! let cfg = Arc::new(ArcSwap::from_pointee(Cfg { value: 0 })); //! let thread = work_with_usize(Map::new(Arc::clone(&cfg), |cfg: &Cfg| &cfg.value)); //! cfg.store(Arc::new(Cfg { value: 42 })); //! thread.join().unwrap(); //! //! // Passing a constant that can't change. Useful mostly for testing purposes. //! work_with_usize(Constant(42)).join().unwrap(); //! ``` use std::marker::PhantomData; use std::ops::Deref; use std::rc::Rc; use std::sync::Arc; use super::ref_cnt::RefCnt; use super::strategy::Strategy; use super::{ArcSwapAny, Guard}; /// Abstracts over ways code can get access to a value of type `T`. /// /// This is the trait that parts of code will use when accessing a subpart of the big data /// structure. See the [module documentation](index.html) for details. pub trait Access { /// A guard object containing the value and keeping it alive. /// /// For technical reasons, the library doesn't allow direct access into the stored value. A /// temporary guard object must be loaded, that keeps the actual value alive for the time of /// use. type Guard: Deref; /// The loading method. /// /// This returns the guard that holds the actual value. Should be called anew each time a fresh /// value is needed. fn load(&self) -> Self::Guard; } impl + ?Sized, P: Deref> Access for P { type Guard = A::Guard; fn load(&self) -> Self::Guard { self.deref().load() } } impl Access for dyn DynAccess + '_ { type Guard = DynGuard; fn load(&self) -> Self::Guard { self.load() } } impl Access for dyn DynAccess + '_ + Send { type Guard = DynGuard; fn load(&self) -> Self::Guard { self.load() } } impl Access for dyn DynAccess + '_ + Sync + Send { type Guard = DynGuard; fn load(&self) -> Self::Guard { self.load() } } impl> Access for ArcSwapAny { type Guard = Guard; fn load(&self) -> Self::Guard { self.load() } } #[derive(Debug)] #[doc(hidden)] pub struct DirectDeref>(Guard); impl>> Deref for DirectDeref, S> { type Target = T; fn deref(&self) -> &T { self.0.deref().deref() } } impl>> Access for ArcSwapAny, S> { type Guard = DirectDeref, S>; fn load(&self) -> Self::Guard { DirectDeref(self.load()) } } impl>> Deref for DirectDeref, S> { type Target = T; fn deref(&self) -> &T { self.0.deref().deref() } } impl>> Access for ArcSwapAny, S> { type Guard = DirectDeref, S>; fn load(&self) -> Self::Guard { DirectDeref(self.load()) } } #[doc(hidden)] pub struct DynGuard(Box>); impl Deref for DynGuard { type Target = T; fn deref(&self) -> &T { &self.0 } } /// An object-safe version of the [`Access`] trait. /// /// This can be used instead of the [`Access`] trait in case a type erasure is desired. This has /// the effect of performance hit (due to boxing of the result and due to dynamic dispatch), but /// makes certain code simpler and possibly makes the executable smaller. /// /// This is automatically implemented for everything that implements [`Access`]. /// /// # Examples /// /// ```rust /// use arc_swap::access::{Constant, DynAccess}; /// /// fn do_something(value: Box + Send>) { /// let v = value.load(); /// println!("{}", *v); /// } /// /// do_something(Box::new(Constant(42))); /// ``` pub trait DynAccess { /// The equivalent of [`Access::load`]. fn load(&self) -> DynGuard; } impl DynAccess for A where A: Access, A::Guard: 'static, { fn load(&self) -> DynGuard { DynGuard(Box::new(Access::load(self))) } } /// [DynAccess] to [Access] wrapper. /// /// In previous versions, `Box` didn't implement [Access], to use inside [Map] one /// could use this wrapper. Since then, a way was found to solve it. In most cases, this wrapper is /// no longer necessary. /// /// This is left in place for two reasons: /// * Backwards compatibility. /// * Corner-cases not covered by the found solution. For example, trait inheritance in the form of /// `Box` where `SomeTrait: Access` doesn't work out of the box and still needs /// this wrapper. /// /// # Examples /// /// The example is for the simple case (which is no longer needed, but may help as an inspiration). /// /// ```rust /// use std::sync::Arc; /// /// use arc_swap::ArcSwap; /// use arc_swap::access::{AccessConvert, DynAccess, Map}; /// /// struct Inner { /// val: usize, /// } /// /// struct Middle { /// inner: Inner, /// } /// /// struct Outer { /// middle: Middle, /// } /// /// let outer = Arc::new(ArcSwap::from_pointee(Outer { /// middle: Middle { /// inner: Inner { /// val: 42, /// } /// } /// })); /// /// let middle: Arc> = /// Arc::new(Map::new(outer, |outer: &Outer| &outer.middle)); /// let inner: Arc> = /// Arc::new(Map::new(AccessConvert(middle), |middle: &Middle| &middle.inner)); /// let guard = inner.load(); /// assert_eq!(42, guard.val); /// ``` pub struct AccessConvert(pub D); impl Access for AccessConvert where D: Deref, D::Target: DynAccess, { type Guard = DynGuard; fn load(&self) -> Self::Guard { self.0.load() } } #[doc(hidden)] #[derive(Copy, Clone, Debug)] pub struct MapGuard { guard: G, projection: F, _t: PhantomData &R>, } impl Deref for MapGuard where G: Deref, F: Fn(&T) -> &R, { type Target = R; fn deref(&self) -> &R { (self.projection)(&self.guard) } } /// An adaptor to provide access to a part of larger structure. /// /// This is the *active* part of this module. Use the [module documentation](index.html) for the /// details. #[derive(Copy, Clone, Debug)] pub struct Map { access: A, projection: F, _t: PhantomData T>, } impl Map { /// Creates a new instance. /// /// # Parameters /// /// * `access`: Access to the bigger structure. This is usually something like `Arc` /// or `&ArcSwap`. It is technically possible to use any other [`Access`] here, though, for /// example to sub-delegate into even smaller structure from a [`Map`] (or generic /// [`Access`]). /// * `projection`: A function (or closure) responsible to providing a reference into the /// bigger bigger structure, selecting just subset of it. In general, it is expected to be /// *cheap* (like only taking reference). pub fn new(access: A, projection: F) -> Self where F: Fn(&T) -> &R + Clone, { Map { access, projection, _t: PhantomData, } } } impl Access for Map where A: Access, F: Fn(&T) -> &R + Clone, { type Guard = MapGuard; fn load(&self) -> Self::Guard { let guard = self.access.load(); MapGuard { guard, projection: self.projection.clone(), _t: PhantomData, } } } #[doc(hidden)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct ConstantDeref(T); impl Deref for ConstantDeref { type Target = T; fn deref(&self) -> &T { &self.0 } } /// Access to an constant. /// /// This wraps a constant value to provide [`Access`] to it. It is constant in the sense that, /// unlike [`ArcSwapAny`] and [`Map`], the loaded value will always stay the same (there's no /// remote `store`). /// /// The purpose is mostly testing and plugging a parameter that works generically from code that /// doesn't need the updating functionality. #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Constant(pub T); impl Access for Constant { type Guard = ConstantDeref; fn load(&self) -> Self::Guard { ConstantDeref(self.0.clone()) } } #[cfg(test)] mod tests { use super::super::{ArcSwap, ArcSwapOption}; use super::*; fn check_static_dispatch_direct>(a: A) { assert_eq!(42, *a.load()); } fn check_static_dispatch>>(a: A) { assert_eq!(42, **a.load()); } /// Tests dispatching statically from arc-swap works #[test] fn static_dispatch() { let a = ArcSwap::from_pointee(42); check_static_dispatch_direct(&a); check_static_dispatch(&a); check_static_dispatch(a); } fn check_dyn_dispatch_direct(a: &dyn DynAccess) { assert_eq!(42, *a.load()); } fn check_dyn_dispatch(a: &dyn DynAccess>) { assert_eq!(42, **a.load()); } /// Tests we can also do a dynamic dispatch of the companion trait #[test] fn dyn_dispatch() { let a = ArcSwap::from_pointee(42); check_dyn_dispatch_direct(&a); check_dyn_dispatch(&a); } fn check_transition(a: A) where A: Access, A::Guard: 'static, { check_dyn_dispatch_direct(&a) } /// Tests we can easily transition from the static dispatch trait to the dynamic one #[test] fn transition() { let a = ArcSwap::from_pointee(42); check_transition(&a); check_transition(a); } /// Test we can dispatch from Arc> or similar. #[test] fn indirect() { let a = Arc::new(ArcSwap::from_pointee(42)); check_static_dispatch(&a); check_dyn_dispatch(&a); } struct Cfg { value: usize, } #[test] fn map() { let a = ArcSwap::from_pointee(Cfg { value: 42 }); let map = a.map(|a: &Cfg| &a.value); check_static_dispatch_direct(&map); check_dyn_dispatch_direct(&map); } #[test] fn map_option_some() { let a = ArcSwapOption::from_pointee(Cfg { value: 42 }); let map = a.map(|a: &Option>| a.as_ref().map(|c| &c.value).unwrap()); check_static_dispatch_direct(&map); check_dyn_dispatch_direct(&map); } #[test] fn map_option_none() { let a = ArcSwapOption::empty(); let map = a.map(|a: &Option>| a.as_ref().map(|c| &c.value).unwrap_or(&42)); check_static_dispatch_direct(&map); check_dyn_dispatch_direct(&map); } #[test] fn constant() { let c = Constant(42); check_static_dispatch_direct(c); check_dyn_dispatch_direct(&c); check_static_dispatch_direct(c); } #[test] fn map_reload() { let a = ArcSwap::from_pointee(Cfg { value: 0 }); let map = a.map(|cfg: &Cfg| &cfg.value); assert_eq!(0, *Access::load(&map)); a.store(Arc::new(Cfg { value: 42 })); assert_eq!(42, *Access::load(&map)); } // Compile tests for dynamic access fn _expect_access(_: impl Access) {} fn _dyn_access(x: Box + '_>) { _expect_access(x) } fn _dyn_access_send(x: Box + '_ + Send>) { _expect_access(x) } fn _dyn_access_send_sync(x: Box + '_ + Send + Sync>) { _expect_access(x) } #[test] fn double_dyn_access_complex() { struct Inner { val: usize, } struct Middle { inner: Inner, } struct Outer { middle: Middle, } let outer = Arc::new(ArcSwap::from_pointee(Outer { middle: Middle { inner: Inner { val: 42 }, }, })); let middle: Arc> = Arc::new(Map::new(outer, |outer: &Outer| &outer.middle)); let inner: Arc> = Arc::new(Map::new(middle, |middle: &Middle| &middle.inner)); // Damn. We have the DynAccess wrapper in scope and need to disambiguate the inner.load() let guard = Access::load(&inner); assert_eq!(42, guard.val); } }