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
//! A high-performance, thread-safe HashMap and LRU cache with fine-grained per-key locking.
//!
//! # Overview
//!
//! This crate provides two concurrent map implementations:
//!
//! - [`LockMap`]: A thread-safe HashMap with per-key level locking
//! - [`LruLockMap`]: A thread-safe LRU cache with per-key locking and automatic eviction
//!
//! Both data structures use internal sharding for high concurrency and allow you to
//! hold an exclusive lock on a specific key for complex atomic operations, minimizing
//! contention across different keys.
//!
//! # Features
//!
//! - **Per-key locking**: Acquire exclusive locks for specific keys; operations on different keys run in parallel
//! - **Sharding architecture**: Internal sharding reduces contention on the map structure itself
//! - **Single hash computation**: Key and pre-computed hash stored together; each operation hashes once
//! - **No key duplication**: Uses [`hashbrown::HashTable`] so each key is stored only once
//! - **Deadlock prevention**: `LockMap` provides [`batch_lock`](LockMap::batch_lock) for safe multi-key locking
//! - **LRU eviction**: `LruLockMap` automatically evicts least recently used entries when capacity is exceeded
//! - **Non-blocking eviction**: In-use entries are skipped during eviction; traversal continues to the next candidate
//!
//! # Examples
//!
//! ## LockMap
//!
//! ```
//! use lockmap::LockMap;
//!
//! let map = LockMap::<String, u32>::new();
//!
//! map.insert("key".to_string(), 42);
//! assert_eq!(map.get("key"), Some(42));
//!
//! {
//! let mut entry = map.entry("key2".to_string());
//! entry.insert(123);
//! }
//!
//! assert_eq!(map.remove("key"), Some(42));
//! ```
//!
//! ## LruLockMap
//!
//! ```
//! use lockmap::LruLockMap;
//!
//! let cache = LruLockMap::<String, u32>::new(1000);
//!
//! cache.insert("key".to_string(), 42);
//! assert_eq!(cache.get("key"), Some(42));
//!
//! {
//! let mut entry = cache.entry("key2".to_string());
//! entry.insert(123);
//! }
//!
//! assert_eq!(cache.remove("key"), Some(42));
//! ```
pub use ;
pub use ;