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}