/rust/registry/src/index.crates.io-1949cf8c6b5b557f/arc-swap-1.9.1/src/access.rs
Line | Count | Source |
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 | | //! ``` |
85 | | use core::marker::PhantomData; |
86 | | use core::ops::Deref; |
87 | | |
88 | | use crate::imports::{Arc, Box, Rc}; |
89 | | |
90 | | use super::ref_cnt::RefCnt; |
91 | | use super::strategy::Strategy; |
92 | | use 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. |
98 | | pub 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 | | |
113 | | impl<T, A: Access<T> + ?Sized, P: Deref<Target = A>> Access<T> for P { |
114 | | type Guard = A::Guard; |
115 | 0 | fn load(&self) -> Self::Guard { |
116 | 0 | self.deref().load() |
117 | 0 | } |
118 | | } |
119 | | |
120 | | impl<T> Access<T> for dyn DynAccess<T> + '_ { |
121 | | type Guard = DynGuard<T>; |
122 | | |
123 | 0 | fn load(&self) -> Self::Guard { |
124 | 0 | self.load() |
125 | 0 | } |
126 | | } |
127 | | |
128 | | impl<T> Access<T> for dyn DynAccess<T> + '_ + Send { |
129 | | type Guard = DynGuard<T>; |
130 | | |
131 | 0 | fn load(&self) -> Self::Guard { |
132 | 0 | self.load() |
133 | 0 | } |
134 | | } |
135 | | |
136 | | impl<T> Access<T> for dyn DynAccess<T> + '_ + Sync + Send { |
137 | | type Guard = DynGuard<T>; |
138 | | |
139 | 0 | fn load(&self) -> Self::Guard { |
140 | 0 | self.load() |
141 | 0 | } |
142 | | } |
143 | | |
144 | | impl<T: RefCnt, S: Strategy<T>> Access<T> for ArcSwapAny<T, S> { |
145 | | type Guard = Guard<T, S>; |
146 | | |
147 | 0 | fn load(&self) -> Self::Guard { |
148 | 0 | self.load() |
149 | 0 | } |
150 | | } |
151 | | |
152 | | #[derive(Debug)] |
153 | | #[doc(hidden)] |
154 | | pub struct DirectDeref<T: RefCnt, S: Strategy<T>>(Guard<T, S>); |
155 | | |
156 | | impl<T, S: Strategy<Arc<T>>> Deref for DirectDeref<Arc<T>, S> { |
157 | | type Target = T; |
158 | 0 | fn deref(&self) -> &T { |
159 | 0 | self.0.deref().deref() |
160 | 0 | } |
161 | | } |
162 | | |
163 | | impl<T, S: Strategy<Arc<T>>> Access<T> for ArcSwapAny<Arc<T>, S> { |
164 | | type Guard = DirectDeref<Arc<T>, S>; |
165 | 0 | fn load(&self) -> Self::Guard { |
166 | 0 | DirectDeref(self.load()) |
167 | 0 | } |
168 | | } |
169 | | |
170 | | impl<T, S: Strategy<Rc<T>>> Deref for DirectDeref<Rc<T>, S> { |
171 | | type Target = T; |
172 | 0 | fn deref(&self) -> &T { |
173 | 0 | self.0.deref().deref() |
174 | 0 | } |
175 | | } |
176 | | |
177 | | impl<T, S: Strategy<Rc<T>>> Access<T> for ArcSwapAny<Rc<T>, S> { |
178 | | type Guard = DirectDeref<Rc<T>, S>; |
179 | 0 | fn load(&self) -> Self::Guard { |
180 | 0 | DirectDeref(self.load()) |
181 | 0 | } |
182 | | } |
183 | | |
184 | | #[doc(hidden)] |
185 | | pub struct DynGuard<T: ?Sized>(Box<dyn Deref<Target = T>>); |
186 | | |
187 | | impl<T: ?Sized> Deref for DynGuard<T> { |
188 | | type Target = T; |
189 | 0 | fn deref(&self) -> &T { |
190 | 0 | &self.0 |
191 | 0 | } |
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 | | /// ``` |
214 | | pub trait DynAccess<T> { |
215 | | /// The equivalent of [`Access::load`]. |
216 | | fn load(&self) -> DynGuard<T>; |
217 | | } |
218 | | |
219 | | impl<T, A> DynAccess<T> for A |
220 | | where |
221 | | A: Access<T>, |
222 | | A::Guard: 'static, |
223 | | { |
224 | 0 | fn load(&self) -> DynGuard<T> { |
225 | 0 | DynGuard(Box::new(Access::load(self))) |
226 | 0 | } |
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 | | /// ``` |
278 | | pub struct AccessConvert<D>(pub D); |
279 | | |
280 | | impl<T, D> Access<T> for AccessConvert<D> |
281 | | where |
282 | | D: Deref, |
283 | | D::Target: DynAccess<T>, |
284 | | { |
285 | | type Guard = DynGuard<T>; |
286 | | |
287 | 0 | fn load(&self) -> Self::Guard { |
288 | 0 | self.0.load() |
289 | 0 | } |
290 | | } |
291 | | |
292 | | #[doc(hidden)] |
293 | | #[derive(Copy, Clone, Debug)] |
294 | | pub struct MapGuard<G, F, T, R> { |
295 | | guard: G, |
296 | | projection: F, |
297 | | _t: PhantomData<fn(&T) -> &R>, |
298 | | } |
299 | | |
300 | | impl<G, F, T, R> Deref for MapGuard<G, F, T, R> |
301 | | where |
302 | | G: Deref<Target = T>, |
303 | | F: Fn(&T) -> &R, |
304 | | { |
305 | | type Target = R; |
306 | 0 | fn deref(&self) -> &R { |
307 | 0 | (self.projection)(&self.guard) |
308 | 0 | } |
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)] |
316 | | pub struct Map<A, T, F> { |
317 | | access: A, |
318 | | projection: F, |
319 | | _t: PhantomData<fn() -> T>, |
320 | | } |
321 | | |
322 | | impl<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 | 0 | pub fn new<R>(access: A, projection: F) -> Self |
335 | 0 | where |
336 | 0 | F: Fn(&T) -> &R + Clone, |
337 | | { |
338 | 0 | Map { |
339 | 0 | access, |
340 | 0 | projection, |
341 | 0 | _t: PhantomData, |
342 | 0 | } |
343 | 0 | } |
344 | | } |
345 | | |
346 | | impl<A, F, T, R> Access<R> for Map<A, T, F> |
347 | | where |
348 | | A: Access<T>, |
349 | | F: Fn(&T) -> &R + Clone, |
350 | | { |
351 | | type Guard = MapGuard<A::Guard, F, T, R>; |
352 | 0 | fn load(&self) -> Self::Guard { |
353 | 0 | let guard = self.access.load(); |
354 | 0 | MapGuard { |
355 | 0 | guard, |
356 | 0 | projection: self.projection.clone(), |
357 | 0 | _t: PhantomData, |
358 | 0 | } |
359 | 0 | } |
360 | | } |
361 | | |
362 | | #[doc(hidden)] |
363 | | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] |
364 | | pub struct ConstantDeref<T>(T); |
365 | | |
366 | | impl<T> Deref for ConstantDeref<T> { |
367 | | type Target = T; |
368 | 0 | fn deref(&self) -> &T { |
369 | 0 | &self.0 |
370 | 0 | } |
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)] |
382 | | pub struct Constant<T>(pub T); |
383 | | |
384 | | impl<T: Clone> Access<T> for Constant<T> { |
385 | | type Guard = ConstantDeref<T>; |
386 | 0 | fn load(&self) -> Self::Guard { |
387 | 0 | ConstantDeref(self.0.clone()) |
388 | 0 | } |
389 | | } |
390 | | |
391 | | #[cfg(test)] |
392 | | mod 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 | | } |