sodium_rust/impl_/
lazy.rs1use parking_lot::Mutex;
2use std::sync::Arc;
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 data = self.data.lock();
44 let next_op: Option<LazyData<A>>;
45 let result: A;
46 match &mut *data {
47 LazyData::Thunk(ref mut k) => {
48 result = k();
49 next_op = Some(LazyData::Value(result.clone()));
50 }
51 LazyData::Value(ref x) => {
52 result = x.clone();
53 next_op = None;
54 }
55 }
56 if let Some(next) = next_op {
57 *data = next;
58 }
59 result
60 }
61}