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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/// A general purpouse cache suitable for saving discarted memory allocations in
/// a tight loop.
///
/// # Dummy Example
/// ```rust
/// extern crate owned_alloc;
///
/// use owned_alloc::{Cache, RawVec, UninitAlloc};
///
/// fn do_some_stuff(iter: usize, n: usize) -> usize {
///     let mut cache = Cache::new();
///     let mut res = 0usize;
///
///     for i in 1 ..= iter {
///         let alloc =
///             cache.take_or(|| UninitAlloc::from(RawVec::with_capacity(n)));
///
///         let inited = unsafe {
///             alloc.init_in_place(|slice| {
///                 for j in 0 .. slice.len() {
///                     (&mut slice[j] as *mut usize)
///                         .write(i.wrapping_mul(j + 1))
///                 }
///             })
///         };
///
///         for &item in &*inited {
///             res = res.wrapping_add(item);
///         }
///
///         cache.store(inited.drop_in_place());
///     }
///
///     res
/// }
///
/// assert_eq!(do_some_stuff(2, 3), 1 + 2 + 3 + 2 + 4 + 6);
/// ```

#[derive(Debug)]
pub struct Cache<A> {
    stored: Option<A>,
}

impl<A> Cache<A> {
    /// Creates a new cache with no data.
    pub fn new() -> Self {
        Self { stored: None }
    }

    /// Stores data into the cache.
    pub fn store(&mut self, val: A) {
        self.stored = Some(val);
    }

    /// Takes the data from the cache.
    pub fn take(&mut self) -> Option<A> {
        self.stored.take()
    }

    /// Takes the data from the cache. If there was no data, the passed closure
    /// is called to produce the returned data.
    pub fn take_or<F>(&mut self, create: F) -> A
    where
        F: FnOnce() -> A,
    {
        self.take().unwrap_or_else(create)
    }
}

impl<A> Default for Cache<A> {
    fn default() -> Self {
        Self::new()
    }
}