1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
use std::sync::Arc; use std::sync::Mutex; pub struct Lazy<A> { data: Arc<Mutex<LazyData<A>>>, } impl<A> Clone for Lazy<A> { fn clone(&self) -> Self { Lazy { data: self.data.clone(), } } } pub enum LazyData<A> { Thunk(Box<dyn FnMut() -> A + Send>), Value(A), } impl<A: Send + Clone + 'static> Lazy<A> { pub fn new<THUNK: FnMut() -> A + Send + 'static>(thunk: THUNK) -> Lazy<A> { Lazy { data: Arc::new(Mutex::new(LazyData::Thunk(Box::new(thunk)))), } } pub fn of_value(value: A) -> Lazy<A> { Lazy { data: Arc::new(Mutex::new(LazyData::Value(value))), } } pub fn run(&self) -> A { let mut l = self.data.lock(); let data: &mut LazyData<A> = l.as_mut().unwrap(); let next_op: Option<LazyData<A>>; let result: A; match data { LazyData::Thunk(ref mut k) => { result = k(); next_op = Some(LazyData::Value(result.clone())); } LazyData::Value(ref x) => { result = x.clone(); next_op = None; } } if let Some(next) = next_op { *data = next; } result } }