tux_owned_alloc/
cache.rs

1/// A general purpouse cache suitable for saving discarted memory allocations in
2/// a tight loop.
3///
4/// # Dummy Example
5/// ```rust
6/// extern crate owned_alloc;
7///
8/// use owned_alloc::{Cache, RawVec, UninitAlloc};
9///
10/// fn do_some_stuff(iter: usize, n: usize) -> usize {
11///     let mut cache = Cache::new();
12///     let mut res = 0usize;
13///
14///     for i in 1 ..= iter {
15///         let alloc =
16///             cache.take_or(|| UninitAlloc::from(RawVec::with_capacity(n)));
17///
18///         let inited = unsafe {
19///             alloc.init_in_place(|slice| {
20///                 for j in 0 .. slice.len() {
21///                     (&mut slice[j] as *mut usize)
22///                         .write(i.wrapping_mul(j + 1))
23///                 }
24///             })
25///         };
26///
27///         for &item in &*inited {
28///             res = res.wrapping_add(item);
29///         }
30///
31///         cache.store(inited.drop_in_place());
32///     }
33///
34///     res
35/// }
36///
37/// assert_eq!(do_some_stuff(2, 3), 1 + 2 + 3 + 2 + 4 + 6);
38/// ```
39
40#[derive(Debug)]
41pub struct Cache<A> {
42    stored: Option<A>,
43}
44
45impl<A> Cache<A> {
46    /// Creates a new cache with no data.
47    pub fn new() -> Self {
48        Self { stored: None }
49    }
50
51    /// Stores data into the cache.
52    pub fn store(&mut self, val: A) {
53        self.stored = Some(val);
54    }
55
56    /// Takes the data from the cache.
57    pub fn take(&mut self) -> Option<A> {
58        self.stored.take()
59    }
60
61    /// Takes the data from the cache. If there was no data, the passed closure
62    /// is called to produce the returned data.
63    pub fn take_or<F>(&mut self, create: F) -> A
64    where
65        F: FnOnce() -> A,
66    {
67        self.take().unwrap_or_else(create)
68    }
69}
70
71impl<A> Default for Cache<A> {
72    fn default() -> Self {
73        Self::new()
74    }
75}