moka/
common.rs

1use std::time::Duration;
2
3pub(crate) mod builder_utils;
4pub(crate) mod concurrent;
5pub(crate) mod deque;
6pub(crate) mod entry;
7pub(crate) mod error;
8pub(crate) mod frequency_sketch;
9pub(crate) mod time;
10pub(crate) mod timer_wheel;
11
12#[cfg(test)]
13pub(crate) mod test_utils;
14
15use self::concurrent::constants::{
16    DEFAULT_EVICTION_BATCH_SIZE, DEFAULT_MAINTENANCE_TASK_TIMEOUT_MILLIS,
17    DEFAULT_MAX_LOG_SYNC_REPEATS,
18};
19
20// Note: `CacheRegion` cannot have more than four enum variants. This is because
21// `crate::{sync,unsync}::DeqNodes` uses a `tagptr::TagNonNull<DeqNode<T>, 2>`
22// pointer, where the 2-bit tag is `CacheRegion`.
23#[derive(Clone, Copy, Debug, Eq)]
24pub(crate) enum CacheRegion {
25    Window = 0,
26    MainProbation = 1,
27    MainProtected = 2,
28    Other = 3,
29}
30
31impl From<usize> for CacheRegion {
32    fn from(n: usize) -> Self {
33        match n {
34            0 => Self::Window,
35            1 => Self::MainProbation,
36            2 => Self::MainProtected,
37            3 => Self::Other,
38            _ => panic!("No such CacheRegion variant for {n}"),
39        }
40    }
41}
42
43impl CacheRegion {
44    pub(crate) fn name(self) -> &'static str {
45        match self {
46            Self::Window => "window",
47            Self::MainProbation => "main probation",
48            Self::MainProtected => "main protected",
49            Self::Other => "other",
50        }
51    }
52}
53
54impl PartialEq<Self> for CacheRegion {
55    fn eq(&self, other: &Self) -> bool {
56        core::mem::discriminant(self) == core::mem::discriminant(other)
57    }
58}
59
60impl PartialEq<usize> for CacheRegion {
61    fn eq(&self, other: &usize) -> bool {
62        *self as usize == *other
63    }
64}
65
66#[derive(Clone, Debug)]
67pub(crate) struct HousekeeperConfig {
68    /// The timeout duration for the `run_pending_tasks` method. This is a safe-guard
69    /// to prevent cache read/write operations (that may call `run_pending_tasks`
70    /// internally) from being blocked for a long time when the user wrote a slow
71    /// eviction listener closure.
72    ///
73    /// Used only when the eviction listener closure is set for the cache instance.
74    ///
75    /// Default: `DEFAULT_MAINTENANCE_TASK_TIMEOUT_MILLIS`
76    pub(crate) maintenance_task_timeout: Duration,
77    /// The maximum repeat count for receiving operation logs from the read and write
78    /// log channels. Default: `MAX_LOG_SYNC_REPEATS`.
79    pub(crate) max_log_sync_repeats: u32,
80    /// The batch size of entries to be processed by each internal eviction method.
81    /// Default: `EVICTION_BATCH_SIZE`.
82    pub(crate) eviction_batch_size: u32,
83}
84
85impl Default for HousekeeperConfig {
86    fn default() -> Self {
87        Self {
88            maintenance_task_timeout: Duration::from_millis(
89                DEFAULT_MAINTENANCE_TASK_TIMEOUT_MILLIS,
90            ),
91            max_log_sync_repeats: DEFAULT_MAX_LOG_SYNC_REPEATS as u32,
92            eviction_batch_size: DEFAULT_EVICTION_BATCH_SIZE,
93        }
94    }
95}
96
97impl HousekeeperConfig {
98    #[cfg(test)]
99    pub(crate) fn new(
100        maintenance_task_timeout: Option<Duration>,
101        max_log_sync_repeats: Option<u32>,
102        eviction_batch_size: Option<u32>,
103    ) -> Self {
104        Self {
105            maintenance_task_timeout: maintenance_task_timeout.unwrap_or(Duration::from_millis(
106                DEFAULT_MAINTENANCE_TASK_TIMEOUT_MILLIS,
107            )),
108            max_log_sync_repeats: max_log_sync_repeats
109                .unwrap_or(DEFAULT_MAX_LOG_SYNC_REPEATS as u32),
110            eviction_batch_size: eviction_batch_size.unwrap_or(DEFAULT_EVICTION_BATCH_SIZE),
111        }
112    }
113}
114
115// Ensures the value fits in a range of `128u32..=u32::MAX`.
116pub(crate) fn sketch_capacity(max_capacity: u64) -> u32 {
117    max_capacity.try_into().unwrap_or(u32::MAX).max(128)
118}
119
120#[cfg(test)]
121pub(crate) fn available_parallelism() -> usize {
122    use std::{num::NonZeroUsize, thread::available_parallelism};
123    available_parallelism().map(NonZeroUsize::get).unwrap_or(1)
124}