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