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
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
//! A two-level LRU cache.
//!
//! Two keys are used in the cache, one to access another layer of LRU caches,
//! and the second to store a payload in that bottom-layered cache.
use register::Register;
pub use self::cacheable::Cacheable;

mod cacheable;
#[cfg(test)]
mod test;
#[cfg(test)]
mod bench;

/// The two-level LRU cache
#[allow(dead_code)]
pub struct Cache<C: Cacheable> {
    register: Box<Register<C::UpperKey, *mut Register<C::LowerKey, C::Payload>>>,
    registers: Box<[Register<C::LowerKey, C::Payload>]>
}

impl<C: Cacheable> Cache<C> {
    /// Create a new LRU cache of caches
    ///
    /// `cache_size` specifies the number of caches in the second layer.
    /// `register_size` specifies the number of entries in each second-layer cache.
    pub fn new(cache_size: usize, register_size: usize) -> Cache<C> {
        let mut registers = Vec::with_capacity(cache_size);
        let mut register = Register::new(cache_size);
        for _ in 0..cache_size {
            registers.push(Register::<C::LowerKey, C::Payload>::new(register_size));
        }
        let mut registers_box = registers.into_boxed_slice();
        for i in 0..cache_size {
            register.entries[i].payload = &mut registers_box[i] as *mut Register<C::LowerKey, C::Payload>;
        }

        Cache{
            register: Box::new(register),
            registers: registers_box
        }
    }

    /// Set a payload beneath two keys
    ///
    /// The `cache_key` is more general, and can have multiple `register_keys` stored under it.
    #[inline]
    pub fn set(&mut self, upper_key: C::UpperKey, lower_key: C::LowerKey, payload: C::Payload) -> bool {
        match self.register.get(upper_key) {
            Some(pcache) => {
                let mut cache: &mut Register<C::LowerKey, C::Payload> = unsafe{ &mut **pcache };
                return cache.set(lower_key, Some(payload))
            },
            None => ()
        }

        self.register.set(upper_key, None);
        let mut cache: &mut Register<C::LowerKey, C::Payload> = unsafe{ &mut **self.register.get(upper_key).unwrap() };
        cache.reset();
        cache.set(lower_key, Some(payload))
    }

    /// Check if any payloads are set under a given `cache_key`, and return the number of payloads set
    #[inline]
    pub fn has(&mut self, upper_key: C::UpperKey) -> Option<usize> {
        self.register.get(upper_key).map(|pcache| unsafe{ &mut **pcache }.cur_size )
    }

    /// Get a payload set (if any) under a given set of keys
    #[inline]
    pub fn get(&mut self, upper_key: C::UpperKey, lower_key: C::LowerKey) -> Option<&C::Payload> {
        match self.register.get(upper_key) {
            Some(pcache) => {
                let cache: &mut Register<C::LowerKey, C::Payload> = unsafe{ &mut **pcache };
                cache.get(lower_key)
            },
            None => None
        }
    }
}

#[cfg(test)]
struct Types;

#[cfg(test)]
impl Cacheable for Types {
    type UpperKey = u8;
    type LowerKey = u8;
    type Payload = bool;
}

#[test]
fn initialize_registers() {
    let mut cache = Cache::<Types>::new(10, 10);
    let entries = cache.register.entries;
    let mut iter = entries.iter().enumerate();

    assert!(entries.len() == 10);
    loop {
        match iter.next() {
            Some((i, entry)) => {
                assert!(entry.payload == &mut cache.registers[i] as *mut Register<u8, bool>);
            },
            None => { break; }
        }
    }
}