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> + ?Sized, 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> Access<T> for dyn DynAccess<T> + '_ { 123 type Guard = DynGuard<T>; 124 load(&self) -> Self::Guard125 fn load(&self) -> Self::Guard { 126 self.load() 127 } 128 } 129 130 impl<T> Access<T> for dyn DynAccess<T> + '_ + Send { 131 type Guard = DynGuard<T>; 132 load(&self) -> Self::Guard133 fn load(&self) -> Self::Guard { 134 self.load() 135 } 136 } 137 138 impl<T> Access<T> for dyn DynAccess<T> + '_ + Sync + Send { 139 type Guard = DynGuard<T>; 140 load(&self) -> Self::Guard141 fn load(&self) -> Self::Guard { 142 self.load() 143 } 144 } 145 146 impl<T: RefCnt, S: Strategy<T>> Access<T> for ArcSwapAny<T, S> { 147 type Guard = Guard<T, S>; 148 load(&self) -> Self::Guard149 fn load(&self) -> Self::Guard { 150 self.load() 151 } 152 } 153 154 #[derive(Debug)] 155 #[doc(hidden)] 156 pub struct DirectDeref<T: RefCnt, S: Strategy<T>>(Guard<T, S>); 157 158 impl<T, S: Strategy<Arc<T>>> Deref for DirectDeref<Arc<T>, S> { 159 type Target = T; deref(&self) -> &T160 fn deref(&self) -> &T { 161 self.0.deref().deref() 162 } 163 } 164 165 impl<T, S: Strategy<Arc<T>>> Access<T> for ArcSwapAny<Arc<T>, S> { 166 type Guard = DirectDeref<Arc<T>, S>; load(&self) -> Self::Guard167 fn load(&self) -> Self::Guard { 168 DirectDeref(self.load()) 169 } 170 } 171 172 impl<T, S: Strategy<Rc<T>>> Deref for DirectDeref<Rc<T>, S> { 173 type Target = T; deref(&self) -> &T174 fn deref(&self) -> &T { 175 self.0.deref().deref() 176 } 177 } 178 179 impl<T, S: Strategy<Rc<T>>> Access<T> for ArcSwapAny<Rc<T>, S> { 180 type Guard = DirectDeref<Rc<T>, S>; load(&self) -> Self::Guard181 fn load(&self) -> Self::Guard { 182 DirectDeref(self.load()) 183 } 184 } 185 186 #[doc(hidden)] 187 pub struct DynGuard<T: ?Sized>(Box<dyn Deref<Target = T>>); 188 189 impl<T: ?Sized> Deref for DynGuard<T> { 190 type Target = T; deref(&self) -> &T191 fn deref(&self) -> &T { 192 &self.0 193 } 194 } 195 196 /// An object-safe version of the [`Access`] trait. 197 /// 198 /// This can be used instead of the [`Access`] trait in case a type erasure is desired. This has 199 /// the effect of performance hit (due to boxing of the result and due to dynamic dispatch), but 200 /// makes certain code simpler and possibly makes the executable smaller. 201 /// 202 /// This is automatically implemented for everything that implements [`Access`]. 203 /// 204 /// # Examples 205 /// 206 /// ```rust 207 /// use arc_swap::access::{Constant, DynAccess}; 208 /// 209 /// fn do_something(value: Box<dyn DynAccess<usize> + Send>) { 210 /// let v = value.load(); 211 /// println!("{}", *v); 212 /// } 213 /// 214 /// do_something(Box::new(Constant(42))); 215 /// ``` 216 pub trait DynAccess<T> { 217 /// The equivalent of [`Access::load`]. load(&self) -> DynGuard<T>218 fn load(&self) -> DynGuard<T>; 219 } 220 221 impl<T, A> DynAccess<T> for A 222 where 223 A: Access<T>, 224 A::Guard: 'static, 225 { load(&self) -> DynGuard<T>226 fn load(&self) -> DynGuard<T> { 227 DynGuard(Box::new(Access::load(self))) 228 } 229 } 230 231 /// [DynAccess] to [Access] wrapper. 232 /// 233 /// In previous versions, `Box<dyn DynAccess>` didn't implement [Access], to use inside [Map] one 234 /// could use this wrapper. Since then, a way was found to solve it. In most cases, this wrapper is 235 /// no longer necessary. 236 /// 237 /// This is left in place for two reasons: 238 /// * Backwards compatibility. 239 /// * Corner-cases not covered by the found solution. For example, trait inheritance in the form of 240 /// `Box<dyn SomeTrait>` where `SomeTrait: Access` doesn't work out of the box and still needs 241 /// this wrapper. 242 /// 243 /// # Examples 244 /// 245 /// The example is for the simple case (which is no longer needed, but may help as an inspiration). 246 /// 247 /// ```rust 248 /// use std::sync::Arc; 249 /// 250 /// use arc_swap::ArcSwap; 251 /// use arc_swap::access::{AccessConvert, DynAccess, Map}; 252 /// 253 /// struct Inner { 254 /// val: usize, 255 /// } 256 /// 257 /// struct Middle { 258 /// inner: Inner, 259 /// } 260 /// 261 /// struct Outer { 262 /// middle: Middle, 263 /// } 264 /// 265 /// let outer = Arc::new(ArcSwap::from_pointee(Outer { 266 /// middle: Middle { 267 /// inner: Inner { 268 /// val: 42, 269 /// } 270 /// } 271 /// })); 272 /// 273 /// let middle: Arc<dyn DynAccess<Middle>> = 274 /// Arc::new(Map::new(outer, |outer: &Outer| &outer.middle)); 275 /// let inner: Arc<dyn DynAccess<Inner>> = 276 /// Arc::new(Map::new(AccessConvert(middle), |middle: &Middle| &middle.inner)); 277 /// let guard = inner.load(); 278 /// assert_eq!(42, guard.val); 279 /// ``` 280 pub struct AccessConvert<D>(pub D); 281 282 impl<T, D> Access<T> for AccessConvert<D> 283 where 284 D: Deref, 285 D::Target: DynAccess<T>, 286 { 287 type Guard = DynGuard<T>; 288 load(&self) -> Self::Guard289 fn load(&self) -> Self::Guard { 290 self.0.load() 291 } 292 } 293 294 #[doc(hidden)] 295 #[derive(Copy, Clone, Debug)] 296 pub struct MapGuard<G, F, T, R> { 297 guard: G, 298 projection: F, 299 _t: PhantomData<fn(&T) -> &R>, 300 } 301 302 impl<G, F, T, R> Deref for MapGuard<G, F, T, R> 303 where 304 G: Deref<Target = T>, 305 F: Fn(&T) -> &R, 306 { 307 type Target = R; deref(&self) -> &R308 fn deref(&self) -> &R { 309 (self.projection)(&self.guard) 310 } 311 } 312 313 /// An adaptor to provide access to a part of larger structure. 314 /// 315 /// This is the *active* part of this module. Use the [module documentation](index.html) for the 316 /// details. 317 #[derive(Copy, Clone, Debug)] 318 pub struct Map<A, T, F> { 319 access: A, 320 projection: F, 321 _t: PhantomData<fn() -> T>, 322 } 323 324 impl<A, T, F> Map<A, T, F> { 325 /// Creates a new instance. 326 /// 327 /// # Parameters 328 /// 329 /// * `access`: Access to the bigger structure. This is usually something like `Arc<ArcSwap>` 330 /// or `&ArcSwap`. It is technically possible to use any other [`Access`] here, though, for 331 /// example to sub-delegate into even smaller structure from a [`Map`] (or generic 332 /// [`Access`]). 333 /// * `projection`: A function (or closure) responsible to providing a reference into the 334 /// bigger bigger structure, selecting just subset of it. In general, it is expected to be 335 /// *cheap* (like only taking reference). new<R>(access: A, projection: F) -> Self where F: Fn(&T) -> &R + Clone,336 pub fn new<R>(access: A, projection: F) -> Self 337 where 338 F: Fn(&T) -> &R + Clone, 339 { 340 Map { 341 access, 342 projection, 343 _t: PhantomData, 344 } 345 } 346 } 347 348 impl<A, F, T, R> Access<R> for Map<A, T, F> 349 where 350 A: Access<T>, 351 F: Fn(&T) -> &R + Clone, 352 { 353 type Guard = MapGuard<A::Guard, F, T, R>; load(&self) -> Self::Guard354 fn load(&self) -> Self::Guard { 355 let guard = self.access.load(); 356 MapGuard { 357 guard, 358 projection: self.projection.clone(), 359 _t: PhantomData, 360 } 361 } 362 } 363 364 #[doc(hidden)] 365 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] 366 pub struct ConstantDeref<T>(T); 367 368 impl<T> Deref for ConstantDeref<T> { 369 type Target = T; deref(&self) -> &T370 fn deref(&self) -> &T { 371 &self.0 372 } 373 } 374 375 /// Access to an constant. 376 /// 377 /// This wraps a constant value to provide [`Access`] to it. It is constant in the sense that, 378 /// unlike [`ArcSwapAny`] and [`Map`], the loaded value will always stay the same (there's no 379 /// remote `store`). 380 /// 381 /// The purpose is mostly testing and plugging a parameter that works generically from code that 382 /// doesn't need the updating functionality. 383 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] 384 pub struct Constant<T>(pub T); 385 386 impl<T: Clone> Access<T> for Constant<T> { 387 type Guard = ConstantDeref<T>; load(&self) -> Self::Guard388 fn load(&self) -> Self::Guard { 389 ConstantDeref(self.0.clone()) 390 } 391 } 392 393 #[cfg(test)] 394 mod tests { 395 use super::super::{ArcSwap, ArcSwapOption}; 396 397 use super::*; 398 check_static_dispatch_direct<A: Access<usize>>(a: A)399 fn check_static_dispatch_direct<A: Access<usize>>(a: A) { 400 assert_eq!(42, *a.load()); 401 } 402 check_static_dispatch<A: Access<Arc<usize>>>(a: A)403 fn check_static_dispatch<A: Access<Arc<usize>>>(a: A) { 404 assert_eq!(42, **a.load()); 405 } 406 407 /// Tests dispatching statically from arc-swap works 408 #[test] static_dispatch()409 fn static_dispatch() { 410 let a = ArcSwap::from_pointee(42); 411 check_static_dispatch_direct(&a); 412 check_static_dispatch(&a); 413 check_static_dispatch(a); 414 } 415 check_dyn_dispatch_direct(a: &dyn DynAccess<usize>)416 fn check_dyn_dispatch_direct(a: &dyn DynAccess<usize>) { 417 assert_eq!(42, *a.load()); 418 } 419 check_dyn_dispatch(a: &dyn DynAccess<Arc<usize>>)420 fn check_dyn_dispatch(a: &dyn DynAccess<Arc<usize>>) { 421 assert_eq!(42, **a.load()); 422 } 423 424 /// Tests we can also do a dynamic dispatch of the companion trait 425 #[test] dyn_dispatch()426 fn dyn_dispatch() { 427 let a = ArcSwap::from_pointee(42); 428 check_dyn_dispatch_direct(&a); 429 check_dyn_dispatch(&a); 430 } 431 check_transition<A>(a: A) where A: Access<usize>, A::Guard: 'static,432 fn check_transition<A>(a: A) 433 where 434 A: Access<usize>, 435 A::Guard: 'static, 436 { 437 check_dyn_dispatch_direct(&a) 438 } 439 440 /// Tests we can easily transition from the static dispatch trait to the dynamic one 441 #[test] transition()442 fn transition() { 443 let a = ArcSwap::from_pointee(42); 444 check_transition(&a); 445 check_transition(a); 446 } 447 448 /// Test we can dispatch from Arc<ArcSwap<_>> or similar. 449 #[test] indirect()450 fn indirect() { 451 let a = Arc::new(ArcSwap::from_pointee(42)); 452 check_static_dispatch(&a); 453 check_dyn_dispatch(&a); 454 } 455 456 struct Cfg { 457 value: usize, 458 } 459 460 #[test] map()461 fn map() { 462 let a = ArcSwap::from_pointee(Cfg { value: 42 }); 463 let map = a.map(|a: &Cfg| &a.value); 464 check_static_dispatch_direct(&map); 465 check_dyn_dispatch_direct(&map); 466 } 467 468 #[test] map_option_some()469 fn map_option_some() { 470 let a = ArcSwapOption::from_pointee(Cfg { value: 42 }); 471 let map = a.map(|a: &Option<Arc<Cfg>>| a.as_ref().map(|c| &c.value).unwrap()); 472 check_static_dispatch_direct(&map); 473 check_dyn_dispatch_direct(&map); 474 } 475 476 #[test] map_option_none()477 fn map_option_none() { 478 let a = ArcSwapOption::empty(); 479 let map = a.map(|a: &Option<Arc<Cfg>>| a.as_ref().map(|c| &c.value).unwrap_or(&42)); 480 check_static_dispatch_direct(&map); 481 check_dyn_dispatch_direct(&map); 482 } 483 484 #[test] constant()485 fn constant() { 486 let c = Constant(42); 487 check_static_dispatch_direct(c); 488 check_dyn_dispatch_direct(&c); 489 check_static_dispatch_direct(c); 490 } 491 492 #[test] map_reload()493 fn map_reload() { 494 let a = ArcSwap::from_pointee(Cfg { value: 0 }); 495 let map = a.map(|cfg: &Cfg| &cfg.value); 496 assert_eq!(0, *Access::load(&map)); 497 a.store(Arc::new(Cfg { value: 42 })); 498 assert_eq!(42, *Access::load(&map)); 499 } 500 501 // Compile tests for dynamic access _expect_access<T>(_: impl Access<T>)502 fn _expect_access<T>(_: impl Access<T>) {} 503 _dyn_access<T>(x: Box<dyn DynAccess<T> + '_>)504 fn _dyn_access<T>(x: Box<dyn DynAccess<T> + '_>) { 505 _expect_access(x) 506 } 507 _dyn_access_send<T>(x: Box<dyn DynAccess<T> + '_ + Send>)508 fn _dyn_access_send<T>(x: Box<dyn DynAccess<T> + '_ + Send>) { 509 _expect_access(x) 510 } 511 _dyn_access_send_sync<T>(x: Box<dyn DynAccess<T> + '_ + Send + Sync>)512 fn _dyn_access_send_sync<T>(x: Box<dyn DynAccess<T> + '_ + Send + Sync>) { 513 _expect_access(x) 514 } 515 516 #[test] double_dyn_access_complex()517 fn double_dyn_access_complex() { 518 struct Inner { 519 val: usize, 520 } 521 522 struct Middle { 523 inner: Inner, 524 } 525 526 struct Outer { 527 middle: Middle, 528 } 529 530 let outer = Arc::new(ArcSwap::from_pointee(Outer { 531 middle: Middle { 532 inner: Inner { val: 42 }, 533 }, 534 })); 535 536 let middle: Arc<dyn DynAccess<Middle>> = 537 Arc::new(Map::new(outer, |outer: &Outer| &outer.middle)); 538 let inner: Arc<dyn DynAccess<Inner>> = 539 Arc::new(Map::new(middle, |middle: &Middle| &middle.inner)); 540 // Damn. We have the DynAccess wrapper in scope and need to disambiguate the inner.load() 541 let guard = Access::load(&inner); 542 assert_eq!(42, guard.val); 543 } 544 } 545