Skip to content

Commit 4dc7bbd

Browse files
committed
master: impl HashMap wrapper with timed entries
1 parent b1a507b commit 4dc7bbd

File tree

3 files changed

+181
-133
lines changed

3 files changed

+181
-133
lines changed

master/src/hash_map.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use std::{borrow::Borrow, collections::hash_map::Entry, hash::Hash, ops::Deref};
2+
3+
use ahash::AHashMap;
4+
5+
use crate::{periodic::Periodic, time::RelativeTime};
6+
7+
/// HashMap entry to keep tracking creation time.
8+
#[derive(Copy, Clone, Debug)]
9+
pub struct Timed<T> {
10+
time: RelativeTime,
11+
pub value: T,
12+
}
13+
14+
impl<T> Timed<T> {
15+
pub fn new(value: T) -> Self {
16+
Self {
17+
time: RelativeTime::now(),
18+
value,
19+
}
20+
}
21+
22+
fn is_valid(&self, now: RelativeTime, secs: u32) -> bool {
23+
now.duration_since(self.time).as_secs() < secs as u64
24+
}
25+
}
26+
27+
impl<T> Deref for Timed<T> {
28+
type Target = T;
29+
30+
fn deref(&self) -> &Self::Target {
31+
&self.value
32+
}
33+
}
34+
35+
impl<T> From<T> for Timed<T> {
36+
fn from(value: T) -> Self {
37+
Self::new(value)
38+
}
39+
}
40+
41+
pub struct TimedHashMap<K, V> {
42+
timeout: u32,
43+
map: Periodic<AHashMap<K, Timed<V>>>,
44+
}
45+
46+
impl<K: Eq + Hash, V> Default for TimedHashMap<K, V> {
47+
fn default() -> Self {
48+
Self::new(10)
49+
}
50+
}
51+
52+
impl<K: Eq + Hash, V> TimedHashMap<K, V> {
53+
pub fn new(timeout: u32) -> Self {
54+
Self {
55+
timeout,
56+
map: Default::default(),
57+
}
58+
}
59+
60+
pub fn set_timeout(&mut self, timeout: u32) {
61+
self.timeout = timeout;
62+
}
63+
64+
pub fn len(&self) -> usize {
65+
self.map.len()
66+
}
67+
68+
pub fn clear(&mut self) {
69+
self.map.clear();
70+
}
71+
72+
fn cleanup(&mut self) {
73+
self.map.maybe_run(|map| {
74+
let now = RelativeTime::now();
75+
map.retain(|_, v| v.is_valid(now, self.timeout));
76+
});
77+
}
78+
79+
pub fn insert(&mut self, k: K, v: V) {
80+
self.map.insert(k, Timed::new(v));
81+
82+
// try to remove outdated entries
83+
self.cleanup();
84+
}
85+
86+
pub fn remove<Q>(&mut self, k: &Q) -> Option<V>
87+
where
88+
K: Borrow<Q>,
89+
Q: Hash + Eq + ?Sized,
90+
{
91+
self.map.remove(k).and_then(|i| {
92+
if i.is_valid(RelativeTime::now(), self.timeout) {
93+
Some(i.value)
94+
} else {
95+
None
96+
}
97+
})
98+
}
99+
100+
pub fn entry(&mut self, key: K) -> Entry<'_, K, Timed<V>> {
101+
self.map.entry(key)
102+
}
103+
104+
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
105+
let now = RelativeTime::now();
106+
self.map.iter().filter_map(move |(k, i)| {
107+
if i.is_valid(now, self.timeout) {
108+
Some((k, &i.value))
109+
} else {
110+
None
111+
}
112+
})
113+
}
114+
115+
pub fn keys(&self) -> impl Iterator<Item = &K> {
116+
self.iter().map(|(k, _)| k)
117+
}
118+
119+
pub fn get<Q>(&self, k: &Q) -> Option<&V>
120+
where
121+
K: Borrow<Q>,
122+
Q: Hash + Eq + ?Sized,
123+
{
124+
self.map.get(k).and_then(|i| {
125+
if i.is_valid(RelativeTime::now(), self.timeout) {
126+
Some(&i.value)
127+
} else {
128+
None
129+
}
130+
})
131+
}
132+
}

master/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![deny(unsafe_code)]
22

3+
mod hash_map;
34
mod master_server;
45
mod periodic;
56
mod stats;
@@ -8,7 +9,7 @@ mod time;
89

910
pub mod config;
1011

11-
use crate::{periodic::Periodic, stats::Stats, str_arr::StrArr, time::RelativeTime};
12+
use crate::{stats::Stats, str_arr::StrArr};
1213

1314
pub use crate::{
1415
config::Config,

0 commit comments

Comments
 (0)