iter_cache.rs
View source code here on GitHub!
Includes
std::sync::Once
- pub struct iter_cache::CachingIterator<I, T> where I: Iterator<Item = T> + 'static, T: Clone + 'static
This struct implements a global cache that maps an iterator-iterated pair to a cache of values. It is mostly intended for use with the prime function generator.
- pub fn iter_cache::CachingIterator::new() -> CachingIterator<I, T> where I: Iterator<Item = T> + 'static, T: Clone + 'static
- pub fn iter_cache::CachingIterator::default() -> CachingIterator<I, T> where I: Iterator<Item = T> + 'static, T: Clone + 'static
- pub fn iter_cache::CachingIterator::next() -> Option<T> where T: Clone + 'static
1use lazy_static::lazy_static;
2
3use std::any::{Any,TypeId};
4use std::collections::HashMap;
5use std::sync::{Mutex, RwLock};
6
7type CacheVector<T> = Vec<Box<T>>;
8type CacheMap<T> = HashMap<(TypeId, TypeId), Mutex<CacheVector<T>>>;
9lazy_static! {
10 static ref CACHE_MAP: RwLock<CacheMap<dyn Any + Send>> = RwLock::new(HashMap::new());
11}
12
13pub fn cache_iterator<I, T>(iterator: I) -> impl Iterator<Item = T>
14where
15 I: Iterator<Item = T> + 'static,
16 T: Copy + Send + 'static
17{
18 return CachingIterator::new(iterator);
19}
20
21#[derive(Clone, Copy, Debug, Hash)]
22pub struct CachingIterator<I, T>
23where
24 I: Iterator<Item = T> + 'static,
25 T: Copy + Send + 'static
26{
27 inner: I,
28 index: usize,
29 inner_index: usize,
30 type_id: (TypeId, TypeId),
31}
32
33impl<I, T> CachingIterator<I, T>
34where
35 I: Iterator<Item = T> + 'static,
36 T: Copy + Send + 'static
37{
38 pub fn new(inner: I) -> Self {
39 CachingIterator {
40 inner,
41 index: 0,
42 inner_index: 0,
43 type_id: (TypeId::of::<I>(), TypeId::of::<T>())
44 }
45 }
46
47 fn initialize_cache(&self) {
48 let mut cache_map = CACHE_MAP.write().unwrap();
49 cache_map.entry(self.type_id)
50 .or_insert_with(|| Mutex::new(Vec::new()));
51 }
52}
53
54impl<I, T> Iterator for CachingIterator<I, T>
55where
56 I: Iterator<Item = T> + 'static,
57 T: Copy + Send + 'static
58{
59 type Item = T;
60
61 fn next(&mut self) -> Option<Self::Item> {
62 self.initialize_cache();
63 let cache_map = CACHE_MAP.read()
64 .unwrap();
65 let mut cache = cache_map.get(&self.type_id)
66 .expect("Cache for this type should be initialized")
67 .lock()
68 .unwrap();
69
70 if self.index < cache.len() {
71 let boxed_item = &cache[self.index];
72 let result = boxed_item.downcast_ref::<T>().unwrap();
73 self.index += 1;
74 return Some(*result);
75 }
76 while self.inner_index < self.index {
77 self.inner.next();
78 self.inner_index += 1;
79 }
80 match self.inner.next() {
81 Some(value) => {
82 cache.push(Box::new(value));
83 self.index += 1;
84 self.inner_index += 1;
85 return Some(value);
86 }
87 None => {
88 return None;
89 }
90 }
91 }
92}