aboutsummaryrefslogtreecommitdiff
path: root/ops/src/ageset.rs
blob: c97240fba5da4d05371521b7b5fa796abd46b9e8 (plain)
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
use std::collections::HashSet;
use std::hash::Hash;

use blist::BList;

/// So... this is a rather weird thing.
/// It allows to semi-efficiently check the oldest (earliest insertion)
/// elements for certain criteria and remove them in the order of insertion
/// if the criteria is met.
pub struct AgeSet<T> {
    fifo: BList<T>,
    set: HashSet<T>,
}

impl<T> AgeSet<T>
    where T: Eq + Hash + Clone
{
    pub fn new() -> Self {
        AgeSet {
            fifo: BList::new(),
            set: HashSet::new(),
        }
    }

    pub fn contains(&self, t: &T) -> bool {
        self.set.contains(t)
    }

    pub fn prune<F>(&mut self, kill: F)
        where F: Fn(&T) -> bool
    {
        while let Some(ref e) = self.fifo.front().map(T::clone) {
            if kill(&e) {
                let removed = self.fifo.pop_front().unwrap();
                self.set.remove(&e);
                assert!(*e == removed);
            } else {
                break;
            }
        }
    }

    pub fn push(&mut self, t: T) {
        self.fifo.push_back(t.clone());
        self.set.insert(t);
    }
}