mini_moka/
unsync.rs

1//! Provides a *not* thread-safe cache implementation built upon
2//! [`std::collections::HashMap`][std-hashmap].
3//!
4//! [std-hashmap]: https://doc.rust-lang.org/std/collections/struct.HashMap.html
5
6mod builder;
7mod cache;
8mod deques;
9mod iter;
10
11use std::{ptr::NonNull, rc::Rc};
12use tagptr::TagNonNull;
13
14pub use builder::CacheBuilder;
15pub use cache::Cache;
16pub use iter::Iter;
17
18use crate::common::{deque::DeqNode, time::Instant};
19
20pub(crate) type Weigher<K, V> = Box<dyn FnMut(&K, &V) -> u32>;
21
22pub(crate) trait AccessTime {
23    fn last_accessed(&self) -> Option<Instant>;
24    fn set_last_accessed(&mut self, timestamp: Instant);
25    fn last_modified(&self) -> Option<Instant>;
26    fn set_last_modified(&mut self, timestamp: Instant);
27}
28
29pub(crate) struct KeyDate<K> {
30    pub(crate) key: Rc<K>,
31    pub(crate) timestamp: Option<Instant>,
32}
33
34impl<K> KeyDate<K> {
35    pub(crate) fn new(key: Rc<K>, timestamp: Option<Instant>) -> Self {
36        Self { key, timestamp }
37    }
38}
39
40pub(crate) struct KeyHashDate<K> {
41    pub(crate) key: Rc<K>,
42    pub(crate) hash: u64,
43    pub(crate) timestamp: Option<Instant>,
44}
45
46impl<K> KeyHashDate<K> {
47    pub(crate) fn new(key: Rc<K>, hash: u64, timestamp: Option<Instant>) -> Self {
48        Self {
49            key,
50            hash,
51            timestamp,
52        }
53    }
54}
55
56// DeqNode for an access order queue.
57type KeyDeqNodeAo<K> = TagNonNull<DeqNode<KeyHashDate<K>>, 2>;
58
59// DeqNode for the write order queue.
60type KeyDeqNodeWo<K> = NonNull<DeqNode<KeyDate<K>>>;
61
62struct EntryInfo<K> {
63    access_order_q_node: Option<KeyDeqNodeAo<K>>,
64    write_order_q_node: Option<KeyDeqNodeWo<K>>,
65    policy_weight: u32,
66}
67
68pub(crate) struct ValueEntry<K, V> {
69    pub(crate) value: V,
70    info: EntryInfo<K>,
71}
72
73impl<K, V> ValueEntry<K, V> {
74    pub(crate) fn new(value: V, policy_weight: u32) -> Self {
75        Self {
76            value,
77            info: EntryInfo {
78                access_order_q_node: None,
79                write_order_q_node: None,
80                policy_weight,
81            },
82        }
83    }
84
85    #[inline]
86    pub(crate) fn replace_deq_nodes_with(&mut self, mut other: Self) {
87        self.info.access_order_q_node = other.info.access_order_q_node.take();
88        self.info.write_order_q_node = other.info.write_order_q_node.take();
89    }
90
91    #[inline]
92    pub(crate) fn access_order_q_node(&self) -> Option<KeyDeqNodeAo<K>> {
93        self.info.access_order_q_node
94    }
95
96    #[inline]
97    pub(crate) fn set_access_order_q_node(&mut self, node: Option<KeyDeqNodeAo<K>>) {
98        self.info.access_order_q_node = node;
99    }
100
101    #[inline]
102    pub(crate) fn take_access_order_q_node(&mut self) -> Option<KeyDeqNodeAo<K>> {
103        self.info.access_order_q_node.take()
104    }
105
106    #[inline]
107    pub(crate) fn write_order_q_node(&self) -> Option<KeyDeqNodeWo<K>> {
108        self.info.write_order_q_node
109    }
110
111    #[inline]
112    pub(crate) fn set_write_order_q_node(&mut self, node: Option<KeyDeqNodeWo<K>>) {
113        self.info.write_order_q_node = node;
114    }
115
116    #[inline]
117    pub(crate) fn take_write_order_q_node(&mut self) -> Option<KeyDeqNodeWo<K>> {
118        self.info.write_order_q_node.take()
119    }
120
121    #[inline]
122    pub(crate) fn policy_weight(&self) -> u32 {
123        self.info.policy_weight
124    }
125
126    #[inline]
127    pub(crate) fn set_policy_weight(&mut self, policy_weight: u32) {
128        self.info.policy_weight = policy_weight;
129    }
130}
131
132impl<K, V> AccessTime for ValueEntry<K, V> {
133    #[inline]
134    fn last_accessed(&self) -> Option<Instant> {
135        self.access_order_q_node()
136            .and_then(|node| unsafe { node.as_ref() }.element.timestamp)
137    }
138
139    #[inline]
140    fn set_last_accessed(&mut self, timestamp: Instant) {
141        if let Some(mut node) = self.info.access_order_q_node {
142            unsafe { node.as_mut() }.set_last_accessed(timestamp);
143        }
144    }
145
146    #[inline]
147    fn last_modified(&self) -> Option<Instant> {
148        self.write_order_q_node()
149            .and_then(|node| unsafe { node.as_ref() }.element.timestamp)
150    }
151
152    #[inline]
153    fn set_last_modified(&mut self, timestamp: Instant) {
154        if let Some(mut node) = self.info.write_order_q_node {
155            unsafe { node.as_mut() }.set_last_modified(timestamp);
156        }
157    }
158}
159
160impl<K> AccessTime for DeqNode<KeyDate<K>> {
161    #[inline]
162    fn last_accessed(&self) -> Option<Instant> {
163        None
164    }
165
166    #[inline]
167    fn set_last_accessed(&mut self, _timestamp: Instant) {
168        unreachable!();
169    }
170
171    #[inline]
172    fn last_modified(&self) -> Option<Instant> {
173        self.element.timestamp
174    }
175
176    #[inline]
177    fn set_last_modified(&mut self, timestamp: Instant) {
178        self.element.timestamp = Some(timestamp);
179    }
180}
181
182impl<K> AccessTime for DeqNode<KeyHashDate<K>> {
183    #[inline]
184    fn last_accessed(&self) -> Option<Instant> {
185        self.element.timestamp
186    }
187
188    #[inline]
189    fn set_last_accessed(&mut self, timestamp: Instant) {
190        self.element.timestamp = Some(timestamp);
191    }
192
193    #[inline]
194    fn last_modified(&self) -> Option<Instant> {
195        None
196    }
197
198    #[inline]
199    fn set_last_modified(&mut self, _timestamp: Instant) {
200        unreachable!();
201    }
202}