use fn_memo::FnMemo; use recur_fn::*; use std::{ sync::{Arc, RwLock}, thread, time, }; pub fn test_sync( memoizer: impl Fn( Box<dyn DynRecurFn<usize, usize> + Send + Sync>, &dyn Fn(Arc<dyn FnMemo<usize, usize> + Send + Sync>), ), ) { let cnt = Arc::new(RwLock::new(0)); memoizer( Box::new({ let cnt = Arc::clone(&cnt); recur_fn(move |fib, n: usize| { thread::sleep(time::Duration::from_millis(50)); *cnt.write().unwrap() += 1; if n <= 1 { n } else { fib(n - 1) + fib(n - 2) } }) }), &|fib| { assert_eq!(5, fib.call(5)); assert_eq!(6, *cnt.read().unwrap()); assert_eq!(1, fib.call(2)); assert_eq!(6, *cnt.read().unwrap()); fib.clear_cache(); *cnt.write().unwrap() = 0; let mut threads = Vec::new(); let expects = [0, 1, 1, 2, 3, 5]; for arg in 0..=5 { for _ in 0..10 { let test = Arc::clone(&fib); threads.push(thread::spawn(move || { assert_eq!(expects[arg], test.call(arg)); })); } } for thread in threads { thread.join().unwrap() } assert_eq!(6, *cnt.read().unwrap()); }, ) }