diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 81554b74..d528728f 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -13,6 +13,7 @@ license = "GPL-3.0" [dependencies] chrono = "0.4.38" itertools = "0.13.0" +lazy_static = "1.5.0" num-traits = "0.2.19" seq-macro = "0.3.5" diff --git a/rust/src/include/fibonacci.rs b/rust/src/include/fibonacci.rs index c49480be..5a033013 100644 --- a/rust/src/include/fibonacci.rs +++ b/rust/src/include/fibonacci.rs @@ -2,12 +2,14 @@ use std::ops::{Add,Mul}; use num_traits::{one,zero,One,Zero}; +use crate::include::iter_cache::cache_iterator; + pub fn fib() -> impl Iterator where I: Copy + Zero + One + Add + 'static { - return Fibonacci::::new(); + return cache_iterator(Fibonacci::::new()); } pub fn fib_by_3() -> impl Iterator where I: Copy + Zero + One + Add + Mul + 'static { - return FibonacciBy3::::new(); + return cache_iterator(FibonacciBy3::::new()); } #[derive(Clone, Copy, Debug, Hash)] diff --git a/rust/src/include/iter_cache.rs b/rust/src/include/iter_cache.rs index 75418726..e2bfb1ad 100644 --- a/rust/src/include/iter_cache.rs +++ b/rust/src/include/iter_cache.rs @@ -1,10 +1,14 @@ -use std::any::TypeId; +use lazy_static::lazy_static; + +use std::any::{Any,TypeId}; use std::collections::HashMap; use std::sync::{Mutex, RwLock}; -use std::sync::Once; -static INIT: Once = Once::new(); -static mut CACHE_MAP: Option>>>>> = None; +type CacheVector = Vec>>; +type CacheMap = HashMap<(TypeId, TypeId), Mutex>>; +lazy_static! { + static ref CACHE_MAP: RwLock> = RwLock::new(HashMap::new()); +} pub fn cache_iterator(iterator: I) -> impl Iterator where @@ -32,12 +36,6 @@ where T: Copy + 'static { pub fn new(inner: I) -> Self { - // Initialize the global cache map if it hasn't been initialized yet - unsafe { - INIT.call_once(|| { - CACHE_MAP = Some(RwLock::new(HashMap::new())); - }); - } CachingIterator { inner, index: 0, @@ -46,10 +44,9 @@ where } } - // Initialize the cache for the given type fn initialize_cache(&self) { unsafe { - let mut cache_map = CACHE_MAP.as_ref().unwrap().write().unwrap(); + let mut cache_map = CACHE_MAP.write().unwrap(); cache_map.entry(self.type_id) .or_insert_with(|| Mutex::new(Vec::new())); } @@ -64,38 +61,41 @@ where type Item = T; fn next(&mut self) -> Option { - // Ensure the cache is initialized self.initialize_cache(); - - // Access the global cache map - let cache_map = unsafe { CACHE_MAP.as_ref().unwrap().read().unwrap() }; - - let mut cache = cache_map - .get(&self.type_id) - .expect("Cache for this type should be initialized") - .lock() - .unwrap(); + let mut cache: CacheVector = CACHE_MAP.read() + .unwrap() + .get(&self.type_id) + .expect("Cache for this type should be initialized"); + .lock() + .unwrap(); if self.index < cache.len() { // Return the cached result let boxed_item = &cache[self.index]; let result = boxed_item.downcast_ref::().unwrap(); self.index += 1; - Some(*result) - } else { - // Fetch the next result from the inner iterator and cache it - while self.inner_index < self.index { - self.inner.next(); + if let Some(boxed_item) = &cache[self.index] { + let result = boxed_item.downcast_ref::().unwrap(); + self.index += 1; + return Some(*result); + } else { + return None; + } + } + while self.inner_index < self.index { + self.inner.next(); + self.inner_index += 1; + } + return match self.inner.next() { + Some(value) => { + self.ensure_capacity(&mut cache, self.index + 1); + cache[self.index] = Some(Box::new(value)); + self.index += 1; self.inner_index += 1; + return Some(value); } - match self.inner.next() { - Some(value) => { - cache.push(Box::new(value)); - self.index += 1; - self.inner_index += 1; - Some(value) - } - None => None, + None => { + return None; } } } diff --git a/rust/src/include/primes.rs b/rust/src/include/primes.rs index 32669cf2..52fb7c5f 100644 --- a/rust/src/include/primes.rs +++ b/rust/src/include/primes.rs @@ -5,6 +5,8 @@ use std::ops::{Add,Div,Mul,Rem}; use num_traits::{one,zero,One,Zero}; +use crate::include::iter_cache::cache_iterator; + #[derive(Clone, Debug)] pub struct Eratosthenes where I: Hash { sieve: HashMap>, @@ -60,7 +62,7 @@ impl Iterator for Eratosthenes where I: Hash + One + Zero + Add + Mul + Or } pub fn primes() -> impl Iterator where I: Hash + One + Zero + Add + Mul + Ord + Copy + 'static { - return Eratosthenes::new(); + return cache_iterator(Eratosthenes::new()); } pub fn primes_until(x: I) -> impl Iterator where I: Hash + One + Zero + Add + Mul + Ord + Copy + 'static {