1use crate::{
2 linked_slab::Token,
3 options::*,
4 shard::{self, CacheShard, InsertStrategy},
5 DefaultHashBuilder, Equivalent, Lifecycle, MemoryUsed, UnitWeighter, Weighter,
6};
7use std::hash::{BuildHasher, Hash};
8
9#[derive(Clone)]
11pub struct Cache<
12 Key,
13 Val,
14 We = UnitWeighter,
15 B = DefaultHashBuilder,
16 L = DefaultLifecycle<Key, Val>,
17> {
18 shard: CacheShard<Key, Val, We, B, L, SharedPlaceholder>,
19}
20
21impl<Key: Eq + Hash, Val> Cache<Key, Val> {
22 pub fn new(items_capacity: usize) -> Self {
24 Self::with(
25 items_capacity,
26 items_capacity as u64,
27 Default::default(),
28 Default::default(),
29 Default::default(),
30 )
31 }
32}
33
34impl<Key: Eq + Hash, Val, We: Weighter<Key, Val>> Cache<Key, Val, We> {
35 pub fn with_weighter(
36 estimated_items_capacity: usize,
37 weight_capacity: u64,
38 weighter: We,
39 ) -> Self {
40 Self::with(
41 estimated_items_capacity,
42 weight_capacity,
43 weighter,
44 Default::default(),
45 Default::default(),
46 )
47 }
48}
49
50impl<Key: Eq + Hash, Val, We: Weighter<Key, Val>, B: BuildHasher, L: Lifecycle<Key, Val>>
51 Cache<Key, Val, We, B, L>
52{
53 pub fn with(
57 estimated_items_capacity: usize,
58 weight_capacity: u64,
59 weighter: We,
60 hash_builder: B,
61 lifecycle: L,
62 ) -> Self {
63 Self::with_options(
64 OptionsBuilder::new()
65 .estimated_items_capacity(estimated_items_capacity)
66 .weight_capacity(weight_capacity)
67 .build()
68 .unwrap(),
69 weighter,
70 hash_builder,
71 lifecycle,
72 )
73 }
74
75 pub fn with_options(options: Options, weighter: We, hash_builder: B, lifecycle: L) -> Self {
94 let shard = CacheShard::new(
95 options.hot_allocation,
96 options.ghost_allocation,
97 options.estimated_items_capacity,
98 options.weight_capacity,
99 weighter,
100 hash_builder,
101 lifecycle,
102 );
103 Self { shard }
104 }
105
106 pub fn is_empty(&self) -> bool {
108 self.shard.len() == 0
109 }
110
111 pub fn len(&self) -> usize {
113 self.shard.len()
114 }
115
116 pub fn weight(&self) -> u64 {
118 self.shard.weight()
119 }
120
121 pub fn capacity(&self) -> u64 {
123 self.shard.capacity()
124 }
125
126 #[cfg(feature = "stats")]
128 pub fn misses(&self) -> u64 {
129 self.shard.misses()
130 }
131
132 #[cfg(feature = "stats")]
134 pub fn hits(&self) -> u64 {
135 self.shard.hits()
136 }
137
138 pub fn reserve(&mut self, additional: usize) {
141 self.shard.reserve(additional);
142 }
143
144 pub fn contains_key<Q>(&self, key: &Q) -> bool
146 where
147 Q: Hash + Equivalent<Key> + ?Sized,
148 {
149 self.shard.contains(self.shard.hash(key), key)
150 }
151
152 pub fn get<Q>(&self, key: &Q) -> Option<&Val>
154 where
155 Q: Hash + Equivalent<Key> + ?Sized,
156 {
157 self.shard.get(self.shard.hash(key), key)
158 }
159
160 pub fn get_mut<Q>(&mut self, key: &Q) -> Option<RefMut<'_, Key, Val, We, B, L>>
164 where
165 Q: Hash + Equivalent<Key> + ?Sized,
166 {
167 self.shard.get_mut(self.shard.hash(key), key).map(RefMut)
168 }
169
170 pub fn peek<Q>(&self, key: &Q) -> Option<&Val>
172 where
173 Q: Hash + Equivalent<Key> + ?Sized,
174 {
175 self.shard.peek(self.shard.hash(key), key)
176 }
177
178 pub fn peek_mut<Q>(&mut self, key: &Q) -> Option<RefMut<'_, Key, Val, We, B, L>>
182 where
183 Q: Hash + Equivalent<Key> + ?Sized,
184 {
185 self.shard.peek_mut(self.shard.hash(key), key).map(RefMut)
186 }
187
188 pub fn remove<Q>(&mut self, key: &Q) -> Option<(Key, Val)>
191 where
192 Q: Hash + Equivalent<Key> + ?Sized,
193 {
194 self.shard.remove(self.shard.hash(key), key)
195 }
196
197 pub fn remove_if<Q, F>(&mut self, key: &Q, f: F) -> Option<(Key, Val)>
202 where
203 Q: Hash + Equivalent<Key> + ?Sized,
204 F: FnOnce(&Val) -> bool,
205 {
206 self.shard.remove_if(self.shard.hash(key), key, f)
207 }
208
209 pub fn replace(&mut self, key: Key, value: Val, soft: bool) -> Result<(), (Key, Val)> {
215 let lcs = self.replace_with_lifecycle(key, value, soft)?;
216 self.shard.lifecycle.end_request(lcs);
217 Ok(())
218 }
219
220 pub fn replace_with_lifecycle(
226 &mut self,
227 key: Key,
228 value: Val,
229 soft: bool,
230 ) -> Result<L::RequestState, (Key, Val)> {
231 let mut lcs = self.shard.lifecycle.begin_request();
232 self.shard.insert(
233 &mut lcs,
234 self.shard.hash(&key),
235 key,
236 value,
237 InsertStrategy::Replace { soft },
238 )?;
239 Ok(lcs)
240 }
241
242 pub fn retain<F>(&mut self, f: F)
246 where
247 F: Fn(&Key, &Val) -> bool,
248 {
249 self.shard.retain(f);
250 }
251
252 pub fn get_or_insert_with<Q, E>(
257 &mut self,
258 key: &Q,
259 with: impl FnOnce() -> Result<Val, E>,
260 ) -> Result<Option<&Val>, E>
261 where
262 Q: Hash + Equivalent<Key> + ToOwned<Owned = Key> + ?Sized,
263 {
264 let idx = match self.shard.get_or_placeholder(self.shard.hash(key), key) {
265 Ok((idx, _)) => idx,
266 Err((plh, _)) => {
267 let v = with()?;
268 let mut lcs = self.shard.lifecycle.begin_request();
269 let replaced = self.shard.replace_placeholder(&mut lcs, &plh, false, v);
270 self.shard.lifecycle.end_request(lcs);
271 debug_assert!(replaced.is_ok(), "unsync replace_placeholder can't fail");
272 plh.idx
273 }
274 };
275 Ok(self.shard.peek_token(idx))
276 }
277
278 pub fn get_mut_or_insert_with<'a, Q, E>(
283 &'a mut self,
284 key: &Q,
285 with: impl FnOnce() -> Result<Val, E>,
286 ) -> Result<Option<RefMut<'a, Key, Val, We, B, L>>, E>
287 where
288 Q: Hash + Equivalent<Key> + ToOwned<Owned = Key> + ?Sized,
289 {
290 let idx = match self.shard.get_or_placeholder(self.shard.hash(key), key) {
291 Ok((idx, _)) => idx,
292 Err((plh, _)) => {
293 let v = with()?;
294 let mut lcs = self.shard.lifecycle.begin_request();
295 let replaced = self.shard.replace_placeholder(&mut lcs, &plh, false, v);
296 debug_assert!(replaced.is_ok(), "unsync replace_placeholder can't fail");
297 self.shard.lifecycle.end_request(lcs);
298 plh.idx
299 }
300 };
301 Ok(self.shard.peek_token_mut(idx).map(RefMut))
302 }
303
304 pub fn get_ref_or_guard<Q>(&mut self, key: &Q) -> Result<&Val, Guard<'_, Key, Val, We, B, L>>
308 where
309 Q: Hash + Equivalent<Key> + ToOwned<Owned = Key> + ?Sized,
310 {
311 match self.shard.get_or_placeholder(self.shard.hash(key), key) {
313 Ok((_, v)) => unsafe {
314 let v: *const Val = v;
317 Ok(&*v)
318 },
319 Err((placeholder, _)) => Err(Guard {
320 cache: self,
321 placeholder,
322 inserted: false,
323 }),
324 }
325 }
326
327 pub fn get_mut_or_guard<'a, Q>(
333 &'a mut self,
334 key: &Q,
335 ) -> Result<Option<RefMut<'a, Key, Val, We, B, L>>, Guard<'a, Key, Val, We, B, L>>
336 where
337 Q: Hash + Equivalent<Key> + ToOwned<Owned = Key> + ?Sized,
338 {
339 match self.shard.get_or_placeholder(self.shard.hash(key), key) {
341 Ok((idx, _)) => Ok(self.shard.peek_token_mut(idx).map(RefMut)),
342 Err((placeholder, _)) => Err(Guard {
343 cache: self,
344 placeholder,
345 inserted: false,
346 }),
347 }
348 }
349
350 pub fn insert(&mut self, key: Key, value: Val) {
352 let lcs = self.insert_with_lifecycle(key, value);
353 self.shard.lifecycle.end_request(lcs);
354 }
355
356 pub fn insert_with_lifecycle(&mut self, key: Key, value: Val) -> L::RequestState {
358 let mut lcs = self.shard.lifecycle.begin_request();
359 let result = self.shard.insert(
360 &mut lcs,
361 self.shard.hash(&key),
362 key,
363 value,
364 InsertStrategy::Insert,
365 );
366 debug_assert!(result.is_ok());
368 lcs
369 }
370
371 pub fn clear(&mut self) {
373 self.shard.clear();
374 }
375
376 pub fn iter(&self) -> impl Iterator<Item = (&'_ Key, &'_ Val)> + '_ {
378 self.shard.iter()
380 }
381
382 pub fn drain(&mut self) -> impl Iterator<Item = (Key, Val)> + '_ {
386 self.shard.drain()
388 }
389
390 pub fn set_capacity(&mut self, new_weight_capacity: u64) {
395 self.shard.set_capacity(new_weight_capacity);
396 }
397
398 #[cfg(any(fuzzing, test))]
399 pub fn validate(&self, accept_overweight: bool) {
400 self.shard.validate(accept_overweight);
401 }
402
403 pub fn memory_used(&self) -> MemoryUsed {
408 self.shard.memory_used()
409 }
410}
411
412impl<Key, Val, We, B, L> std::fmt::Debug for Cache<Key, Val, We, B, L> {
413 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
414 f.debug_struct("Cache").finish_non_exhaustive()
415 }
416}
417
418pub struct DefaultLifecycle<Key, Val>(std::marker::PhantomData<(Key, Val)>);
420
421impl<Key, Val> std::fmt::Debug for DefaultLifecycle<Key, Val> {
422 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
423 f.debug_tuple("DefaultLifecycle").finish()
424 }
425}
426
427impl<Key, Val> Default for DefaultLifecycle<Key, Val> {
428 #[inline]
429 fn default() -> Self {
430 Self(Default::default())
431 }
432}
433
434impl<Key, Val> Clone for DefaultLifecycle<Key, Val> {
435 #[inline]
436 fn clone(&self) -> Self {
437 Self(Default::default())
438 }
439}
440
441impl<Key, Val> Lifecycle<Key, Val> for DefaultLifecycle<Key, Val> {
442 type RequestState = ();
443
444 #[inline]
445 fn begin_request(&self) -> Self::RequestState {}
446}
447
448#[derive(Debug, Clone)]
449pub(crate) struct SharedPlaceholder {
450 hash: u64,
451 idx: Token,
452}
453
454pub struct Guard<'a, Key, Val, We, B, L> {
455 cache: &'a mut Cache<Key, Val, We, B, L>,
456 placeholder: SharedPlaceholder,
457 inserted: bool,
458}
459
460impl<Key: Eq + Hash, Val, We: Weighter<Key, Val>, B: BuildHasher, L: Lifecycle<Key, Val>>
461 Guard<'_, Key, Val, We, B, L>
462{
463 pub fn insert(self, value: Val) {
465 self.insert_internal(value, false);
466 }
467
468 pub fn insert_with_lifecycle(self, value: Val) -> L::RequestState {
470 self.insert_internal(value, true).unwrap()
471 }
472
473 #[inline]
474 fn insert_internal(mut self, value: Val, return_lcs: bool) -> Option<L::RequestState> {
475 let mut lcs = self.cache.shard.lifecycle.begin_request();
476 let replaced =
477 self.cache
478 .shard
479 .replace_placeholder(&mut lcs, &self.placeholder, false, value);
480 debug_assert!(replaced.is_ok(), "unsync replace_placeholder can't fail");
481 self.inserted = true;
482 if return_lcs {
483 Some(lcs)
484 } else {
485 self.cache.shard.lifecycle.end_request(lcs);
486 None
487 }
488 }
489}
490
491impl<Key, Val, We, B, L> Drop for Guard<'_, Key, Val, We, B, L> {
492 #[inline]
493 fn drop(&mut self) {
494 #[cold]
495 fn drop_slow<Key, Val, We, B, L>(this: &mut Guard<'_, Key, Val, We, B, L>) {
496 this.cache.shard.remove_placeholder(&this.placeholder);
497 }
498 if !self.inserted {
499 drop_slow(self);
500 }
501 }
502}
503
504pub struct RefMut<'cache, Key, Val, We: Weighter<Key, Val>, B, L>(
505 crate::shard::RefMut<'cache, Key, Val, We, B, L, SharedPlaceholder>,
506);
507
508impl<Key, Val, We: Weighter<Key, Val>, B, L> std::ops::Deref for RefMut<'_, Key, Val, We, B, L> {
509 type Target = Val;
510
511 #[inline]
512 fn deref(&self) -> &Self::Target {
513 self.0.pair().1
514 }
515}
516
517impl<Key, Val, We: Weighter<Key, Val>, B, L> std::ops::DerefMut for RefMut<'_, Key, Val, We, B, L> {
518 #[inline]
519 fn deref_mut(&mut self) -> &mut Self::Target {
520 self.0.value_mut()
521 }
522}
523
524impl shard::SharedPlaceholder for SharedPlaceholder {
525 #[inline]
526 fn new(hash: u64, idx: Token) -> Self {
527 Self { hash, idx }
528 }
529
530 #[inline]
531 fn same_as(&self, _other: &Self) -> bool {
532 true
533 }
534
535 #[inline]
536 fn hash(&self) -> u64 {
537 self.hash
538 }
539
540 #[inline]
541 fn idx(&self) -> Token {
542 self.idx
543 }
544}
545
546#[cfg(test)]
547mod tests {
548 use super::*;
549
550 struct Weighter;
551
552 impl crate::Weighter<u32, u32> for Weighter {
553 fn weight(&self, _key: &u32, val: &u32) -> u64 {
554 *val as u64
555 }
556 }
557
558 #[test]
559 fn test_zero_weights() {
560 let mut cache = Cache::with_weighter(100, 100, Weighter);
561 cache.insert(0, 0);
562 assert_eq!(cache.weight(), 0);
563 for i in 1..100 {
564 cache.insert(i, i);
565 cache.insert(i, i);
566 }
567 assert_eq!(cache.get(&0).copied(), Some(0));
568 assert!(cache.contains_key(&0));
569 let a = cache.weight();
570 *cache.get_mut(&0).unwrap() += 1;
571 assert_eq!(cache.weight(), a + 1);
572 for i in 1..100 {
573 cache.insert(i, i);
574 cache.insert(i, i);
575 }
576 assert_eq!(cache.get(&0), None);
577 assert!(!cache.contains_key(&0));
578
579 cache.insert(0, 1);
580 let a = cache.weight();
581 *cache.get_mut(&0).unwrap() -= 1;
582 assert_eq!(cache.weight(), a - 1);
583 for i in 1..100 {
584 cache.insert(i, i);
585 cache.insert(i, i);
586 }
587 assert_eq!(cache.get(&0).copied(), Some(0));
588 assert!(cache.contains_key(&0));
589 }
590
591 #[test]
592 fn test_set_capacity() {
593 let mut cache = Cache::new(100);
594 for i in 0..80 {
595 cache.insert(i, i);
596 }
597 let initial_len = cache.len();
598 assert!(initial_len <= 80);
599
600 cache.set_capacity(50);
602 assert!(cache.len() <= 50);
603 assert!(cache.weight() <= 50);
604 cache.validate(false);
605
606 cache.set_capacity(200);
608 assert_eq!(cache.capacity(), 200);
609 cache.validate(false);
610
611 for i in 100..180 {
613 cache.insert(i, i);
614 }
615 assert!(cache.len() <= 180);
616 assert!(cache.weight() <= 200);
617 cache.validate(false);
618 }
619
620 #[test]
621 fn test_set_capacity_with_ghosts() {
622 let mut cache = Cache::new(50);
624
625 for i in 0..100 {
627 cache.insert(i, i);
628 }
629 cache.validate(false);
630
631 cache.set_capacity(25);
633 assert!(cache.weight() <= 25);
634 cache.validate(false);
635
636 cache.set_capacity(100);
638 assert_eq!(cache.capacity(), 100);
639 cache.validate(false);
640
641 for i in 100..150 {
643 cache.insert(i, i);
644 }
645 cache.validate(false);
646 }
647
648 #[test]
649 fn test_remove_if() {
650 let mut cache = Cache::new(100);
651
652 cache.insert(1, 10);
654 cache.insert(2, 20);
655 cache.insert(3, 30);
656
657 let removed = cache.remove_if(&2, |v| *v == 20);
659 assert_eq!(removed, Some((2, 20)));
660 assert_eq!(cache.get(&2), None);
661
662 let not_removed = cache.remove_if(&3, |v| *v == 999);
664 assert_eq!(not_removed, None);
665 assert_eq!(cache.get(&3), Some(&30));
666
667 let not_found = cache.remove_if(&999, |_| true);
669 assert_eq!(not_found, None);
670
671 cache.validate(false);
672 }
673}