make concurrent map able to give default values which depend on key

this allows to uphold more complex invariants
This commit is contained in:
Chris Beck
2025-12-15 10:26:49 -07:00
parent 6932407872
commit 4584ae23bd
4 changed files with 13 additions and 6 deletions
+10 -3
View File
@@ -11,6 +11,12 @@
//! sources, and insertions occur only a few times at the beginning of the process. //! sources, and insertions occur only a few times at the beginning of the process.
//! Then almost all accesses are to existing elements, and from that point on, //! Then almost all accesses are to existing elements, and from that point on,
//! only read locks are taken when using this API. //! only read locks are taken when using this API.
//!
//! The API also allows to call "retain" if the map gets too big and it needs
//! to be pruned in some manner.
//!
//! This is used instead of dash_map and once_map to avoid unnecessary complexity
//! and dependencies, and give exactly the API needed in our application.
use std::{borrow::Borrow, collections::HashMap, hash::Hash, sync::RwLock}; use std::{borrow::Borrow, collections::HashMap, hash::Hash, sync::RwLock};
@@ -98,7 +104,7 @@ impl <K, V> Default for ConcurrentMap<K, V>
/// to pass the creation function on every access. /// to pass the creation function on every access.
pub struct LazyMap<K, V> { pub struct LazyMap<K, V> {
inner: ConcurrentMap<K, V>, inner: ConcurrentMap<K, V>,
factory: Box<dyn Fn() -> V + Send + Sync>, factory: Box<dyn Fn(&K) -> V + Send + Sync>,
} }
impl<K, V> LazyMap<K, V> impl<K, V> LazyMap<K, V>
@@ -106,7 +112,7 @@ where
K: Eq + Hash + Clone, K: Eq + Hash + Clone,
{ {
/// Create a new lazy map with the given factory for creating initial values. /// Create a new lazy map with the given factory for creating initial values.
pub fn new(factory: impl Fn() -> V + Send + Sync + 'static) -> Self { pub fn new(factory: impl Fn(&K) -> V + Send + Sync + 'static) -> Self {
Self { Self {
inner: ConcurrentMap::new(), inner: ConcurrentMap::new(),
factory: Box::new(factory), factory: Box::new(factory),
@@ -119,7 +125,8 @@ where
Q: Borrow<K>, Q: Borrow<K>,
A: FnOnce(&V) -> R, A: FnOnce(&V) -> R,
{ {
self.inner.get_or_insert_with(key, &self.factory, access) let key = key.borrow();
self.inner.get_or_insert_with(key, || (self.factory)(key), access)
} }
/// Access all entries in the map with a read lock. /// Access all entries in the map with a read lock.
+1 -1
View File
@@ -115,7 +115,7 @@ impl LogHandler {
Self { Self {
config, config,
signal_alert_mq_tx, signal_alert_mq_tx,
log_buffers: LazyMap::new(move || LogBuffer::new(buffer_size)), log_buffers: LazyMap::new(move |_key| LogBuffer::new(buffer_size)),
routes, routes,
overall_limits, overall_limits,
} }
@@ -36,7 +36,7 @@ impl LimiterSet {
global_limiters: Vec<(LogFilter, Limiter)>, global_limiters: Vec<(LogFilter, Limiter)>,
) -> Self { ) -> Self {
Self { Self {
limiters: LazyMap::new(make_limiters), limiters: LazyMap::new(move |_key| make_limiters()),
global_limiters, global_limiters,
} }
} }
+1 -1
View File
@@ -178,7 +178,7 @@ pub struct SourceLocationRateLimiter {
impl SourceLocationRateLimiter { impl SourceLocationRateLimiter {
pub fn new(threshold: RateThreshold, max_entries: usize) -> Self { pub fn new(threshold: RateThreshold, max_entries: usize) -> Self {
Self { Self {
limiters: LazyMap::new(move || MultiRateLimiter::from(threshold)), limiters: LazyMap::new(move |_key| MultiRateLimiter::from(threshold)),
threshold, threshold,
max_entries, max_entries,
} }