handoff_counter 0.8.5

Handoff Counters
Documentation
use std::collections::HashMap;
use std::hash::Hash;
use std::cmp::max;

#[derive(Clone, Debug)]
pub struct Counter<Id: Hash + Eq + Copy> {
    id: Id,
    tier: usize,
    val: u64,
    below: u64,
    vals: HashMap<Id, u64>,
    sck: u64,
    dck: u64,
    slots: HashMap<Id, (u64, u64)>,
    tokens: HashMap<(Id, Id), (u64, u64, u64)>
}

impl<Id: Hash + Eq + Copy> Counter<Id> {

    pub fn new(id: Id, tier: usize) -> Counter<Id> {
        let mut c = Counter {
            id: id,
            tier: tier,
            val: 0,
            below: 0,
            vals: if tier == 0 { HashMap::with_capacity(8) }
                  else { HashMap::with_capacity(1) },
            sck: 0,
            dck: 0,
            slots: HashMap::new(),
            tokens: HashMap::with_capacity(1)
        };
        c.vals.insert(id, 0);
        c
    }

    pub fn id(&self) -> Id { self.id }

    pub fn tier(&self) -> usize { self.tier }

    pub fn value(&self) -> u64 { self.val }

    pub fn vals(&self) -> &HashMap<Id, u64> { &self.vals }

    pub fn slots(&self) -> &HashMap<Id, (u64, u64)> { &self.slots }

    pub fn tokens(&self) -> &HashMap<(Id, Id), (u64, u64, u64)> { &self.tokens }

    pub fn needs_to_handoff(&self) -> bool {
        self.vals[&self.id] > 0 || !self.tokens.is_empty()
    }

    pub fn incr(&mut self) {
        self.val += 1;
        let mut v = self.vals.get_mut(&self.id).unwrap();
        *v += 1;
    }

    pub fn view(&self, id: Id, tier: usize) -> Self {
        let mut slots: HashMap<Id, (u64, u64)> = HashMap::with_capacity(1);
        if self.tier < tier {
            match self.slots.get(&id) {
                Some(&v) => { slots.insert(id, v); }
                None => {}
            }
        } else if self.tier == tier {
            slots = self.slots.clone();
        }
        Counter {
            id : self.id,
            tier: self.tier,
            val: self.val,
            below: self.below,
            vals: self.vals.clone(),
            sck: self.sck,
            dck: self.dck,
            slots: slots,
            tokens: self.tokens.clone(),
        }
    }

    pub fn cleaning_view(&self) -> Self {
        let mut c = self.clone();
        c.vals.insert(self.id, 0);
        c
    }

    pub fn merge(&mut self, other: &Self) {
        self.fill_slots(other);
        self.discard_slot(other);
        self.create_slot(other);
        self.merge_vectors(other);
        self.aggregate(other);
        self.discard_tokens(other);
        self.create_token(other);
        self.cache_tokens(other);
    }

    fn fill_slots(&mut self, other: &Self) {
        let v = self.vals.get_mut(&self.id).unwrap();
        for (&(src, dst), &(sck, dck, n)) in &other.tokens {
            if dst == self.id {
                if let Some(&(s,d)) = self.slots.get(&src) {
                    if (s,d) == (sck, dck) {
                        *v += n;
                        self.slots.remove(&src);
                    }
                };
            }
        }
    }

    fn discard_slot(&mut self, other: &Self) {
        if let Some(&(sck, _)) = self.slots.get(&other.id) {
            if other.sck > sck {
                self.slots.remove(&other.id);
            }
        }
    }

    fn create_slot(&mut self, other: &Self) {
        if self.tier < other.tier &&
           other.vals[&other.id] > 0 &&
           !self.slots.contains_key(&other.id) {
               self.slots.insert(other.id, (other.sck, self.dck));
               self.dck += 1;
        }
    }

    fn merge_vectors(&mut self, other: &Self) {
        if self.tier == 0 && other.tier == 0 {
            for (&k2,&v2) in &other.vals {
                let v = self.vals.entry(k2).or_insert(0);
                *v = max(*v, v2);
            }
        }
    }

    fn aggregate(&mut self, other: &Self) {
        let b = if self.tier == other.tier {
            max(self.below, other.below)
        } else if self.tier > other.tier {
            max(self.below, other.val)
        } else {
            self.below
        };
        let v = if self.tier == 0 {
            self.vals.values().fold(0, |s,&v| s+v)
        } else if self.tier == other.tier {
            max(max(self.val, other.val), b +
                self.vals[&self.id] + other.vals[&other.id])
        } else {
            max(self.val, b + self.vals[&self.id])
        };
        self.below = b;
        self.val = v;
    }

    fn discard_tokens(&mut self, other: &Self) {
        let tok =
            self.tokens.drain().filter(|&((src, dst), (_, dck, _))| {
                !(dst == other.id &&
                  match other.slots.get(&src) {
                      Some(&(_, d)) => d > dck,
                      None => other.dck > dck
                  })
            }).collect();
        self.tokens = tok;
    }

    fn create_token(&mut self, other: &Self) {
        match other.slots.get(&self.id) {
            Some(&(s, d)) if s == self.sck => {
                let v = self.vals.insert(self.id, 0).unwrap();
                self.tokens.insert((self.id, other.id), (s, d, v));
                self.sck += 1;
            }
            _ => {}
        }
    }

    fn cache_tokens(&mut self, other: &Self) {
        if self.tier < other.tier {
            for (&(src,dst), &v) in &other.tokens {
                if src == other.id && dst != self.id {
                    let e = self.tokens.entry((src, dst)).or_insert(v);
                    if e.0 < v.0 {
                        *e = v;
                    }
                }
            }
        }
    }

}