moka/sync_base/
iter.rs
1use std::{hash::Hash, sync::Arc};
2
3pub(crate) trait ScanningGet<K, V> {
5 fn num_cht_segments(&self) -> usize;
7
8 fn scanning_get(&self, key: &Arc<K>) -> Option<V>;
14
15 fn keys(&self, cht_segment: usize) -> Option<Vec<Arc<K>>>;
17}
18
19pub struct Iter<'i, K, V> {
23 keys: Option<Vec<Arc<K>>>,
24 cache_segments: Box<[&'i dyn ScanningGet<K, V>]>,
25 num_cht_segments: usize,
26 cache_seg_index: usize,
27 cht_seg_index: usize,
28 is_done: bool,
29}
30
31impl<'i, K, V> Iter<'i, K, V> {
32 pub(crate) fn with_single_cache_segment(
33 cache: &'i dyn ScanningGet<K, V>,
34 num_cht_segments: usize,
35 ) -> Self {
36 Self {
37 keys: None,
38 cache_segments: Box::new([cache]),
39 num_cht_segments,
40 cache_seg_index: 0,
41 cht_seg_index: 0,
42 is_done: false,
43 }
44 }
45
46 #[cfg(feature = "sync")]
47 pub(crate) fn with_multiple_cache_segments(
48 cache_segments: Box<[&'i dyn ScanningGet<K, V>]>,
49 num_cht_segments: usize,
50 ) -> Self {
51 Self {
52 keys: None,
53 cache_segments,
54 num_cht_segments,
55 cache_seg_index: 0,
56 cht_seg_index: 0,
57 is_done: false,
58 }
59 }
60}
61
62impl<K, V> Iterator for Iter<'_, K, V>
63where
64 K: Eq + Hash + Send + Sync + 'static,
65 V: Clone + Send + Sync + 'static,
66{
67 type Item = (Arc<K>, V);
68
69 fn next(&mut self) -> Option<Self::Item> {
70 if self.is_done {
71 return None;
72 }
73
74 while let Some(key) = self.next_key() {
75 if let Some(v) = self.cache().scanning_get(&key) {
76 return Some((key, v));
77 }
78 }
79
80 self.is_done = true;
81 None
82 }
83}
84
85impl<'i, K, V> Iter<'i, K, V>
86where
87 K: Eq + Hash + Send + Sync + 'static,
88 V: Clone + Send + Sync + 'static,
89{
90 fn cache(&self) -> &'i dyn ScanningGet<K, V> {
91 self.cache_segments[self.cache_seg_index]
92 }
93
94 fn next_key(&mut self) -> Option<Arc<K>> {
95 while let Some(keys) = self.current_keys() {
96 if let key @ Some(_) = keys.pop() {
97 return key;
98 }
99 }
100 None
101 }
102
103 fn current_keys(&mut self) -> Option<&mut Vec<Arc<K>>> {
104 while self.keys.as_ref().map_or(true, Vec::is_empty) {
106 if self.cht_seg_index >= self.num_cht_segments {
108 self.cache_seg_index += 1;
109 self.cht_seg_index = 0;
110 if self.cache_seg_index >= self.cache_segments.len() {
111 return None;
113 }
114 }
115
116 let cache_segment = self.cache_segments[self.cache_seg_index];
117 self.keys = cache_segment.keys(self.cht_seg_index);
118 self.num_cht_segments = cache_segment.num_cht_segments();
119
120 self.cht_seg_index += 1;
121 }
122
123 self.keys.as_mut()
124 }
125}
126
127#[allow(clippy::extra_unused_lifetimes)]
132unsafe impl<'a, K, V> Send for Iter<'_, K, V>
133where
134 K: 'a + Eq + Hash + Send,
135 V: 'a + Send,
136{
137}
138
139#[allow(clippy::extra_unused_lifetimes)]
144unsafe impl<'a, K, V> Sync for Iter<'_, K, V>
145where
146 K: 'a + Eq + Hash + Sync,
147 V: 'a + Sync,
148{
149}