Skip to main content

ferroui_reactiveui/
rx_cache_size.rs

1//! `RxCacheSize` (`ReactiveUI.Shared/RxCacheSize.cs`).
2
3use std::cell::Cell;
4
5/// The limit of the small caches on mobile targets (`DefaultSmallCacheLimit`).
6#[cfg(any(target_os = "android", target_os = "ios"))]
7const DEFAULT_SMALL_CACHE_LIMIT: usize = 32;
8/// The limit of the big caches on mobile targets (`DefaultBigCacheLimit`).
9#[cfg(any(target_os = "android", target_os = "ios"))]
10const DEFAULT_BIG_CACHE_LIMIT: usize = 64;
11/// The limit of the small caches (`DefaultSmallCacheLimit`).
12#[cfg(not(any(target_os = "android", target_os = "ios")))]
13const DEFAULT_SMALL_CACHE_LIMIT: usize = 64;
14/// The limit of the big caches (`DefaultBigCacheLimit`).
15#[cfg(not(any(target_os = "android", target_os = "ios")))]
16const DEFAULT_BIG_CACHE_LIMIT: usize = 256;
17
18ferroui_system::ferro_thread_local! {
19    /// The limits, once read or initialized (`_limits`).
20    static LIMITS: Cell<Option<(usize, usize)>> = const { Cell::new(None) };
21}
22
23/// The sizes of the caches of ReactiveUI (`RxCacheSize`): the memoizing caches of view location
24/// and of the observation of properties.
25///
26/// Deviation (DEVIATIONS.md, ReactiveUI): the limits are per thread, as the caches that read
27/// them are.
28pub struct RxCacheSize;
29
30impl RxCacheSize {
31    /// The limit of the small caches (`SmallCacheLimit`).
32    pub fn small_cache_limit() -> usize {
33        Self::limits().0
34    }
35
36    /// The limit of the big caches (`BigCacheLimit`).
37    pub fn big_cache_limit() -> usize {
38        Self::limits().1
39    }
40
41    /// Sets the limits unless they were set or read before (`Initialize`); the builder of the
42    /// application calls it.
43    pub fn initialize(small_cache_limit: usize, big_cache_limit: usize) {
44        LIMITS.with(|limits| {
45            if limits.get().is_none() {
46                limits.set(Some((small_cache_limit, big_cache_limit)));
47            }
48        });
49    }
50
51    /// Forgets the limits, so that the next read or initialization sets them again
52    /// (`ResetForTesting`); for tests.
53    #[doc(hidden)]
54    pub fn reset_for_testing() {
55        LIMITS.with(|limits| limits.set(None));
56    }
57
58    fn limits() -> (usize, usize) {
59        LIMITS.with(|limits| match limits.get() {
60            Some(current) => current,
61            None => {
62                let defaults = (DEFAULT_SMALL_CACHE_LIMIT, DEFAULT_BIG_CACHE_LIMIT);
63                limits.set(Some(defaults));
64                defaults
65            }
66        })
67    }
68}