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