lock_free/
hashmap_fast.rs1use std::sync::atomic::{AtomicU64, AtomicPtr, Ordering};
7use std::ptr::null_mut;
8use std::hash::{Hash, Hasher};
9use std::collections::hash_map::DefaultHasher;
10use std::marker::PhantomData;
11
12const EMPTY: u64 = 0;
14const TOMBSTONE: u64 = 1;
15const OCCUPIED_FLAG: u64 = 2;
16
17const CACHE_LINE: usize = 128;
19
20const DEFAULT_CAPACITY: usize = 1024;
22
23#[repr(align(64))]
25struct Entry<K, V> {
26 hash_state: AtomicU64,
28 key: AtomicPtr<K>,
30 value: AtomicPtr<V>,
32}
33
34impl<K, V> Entry<K, V> {
35 fn new() -> Self {
36 Self {
37 hash_state: AtomicU64::new(EMPTY),
38 key: AtomicPtr::new(null_mut()),
39 value: AtomicPtr::new(null_mut()),
40 }
41 }
42}
43
44pub struct FastHashMap<K, V> {
46 entries: Box<[Entry<K, V>]>,
48 mask: usize,
50 size: AtomicU64,
52 _phantom: PhantomData<(K, V)>,
54}
55
56impl<K: Hash + Eq + Clone, V: Clone> FastHashMap<K, V> {
57 pub fn new() -> Self {
59 Self::with_capacity(DEFAULT_CAPACITY)
60 }
61
62 pub fn with_capacity(capacity: usize) -> Self {
64 let capacity = capacity.next_power_of_two();
65 let mut entries = Vec::with_capacity(capacity);
66
67 for _ in 0..capacity {
68 entries.push(Entry::new());
69 }
70
71 Self {
72 entries: entries.into_boxed_slice(),
73 mask: capacity - 1,
74 size: AtomicU64::new(0),
75 _phantom: PhantomData,
76 }
77 }
78
79 #[inline]
81 fn hash_key(key: &K) -> u64 {
82 let mut hasher = DefaultHasher::new();
83 key.hash(&mut hasher);
84 hasher.finish()
85 }
86
87 pub fn insert(&self, key: K, value: V) -> Option<V> {
89 let hash = Self::hash_key(&key);
90 let hash_with_flag = hash | OCCUPIED_FLAG;
91 let mut index = (hash as usize) & self.mask;
92 let start_index = index;
93
94 loop {
95 let entry = &self.entries[index];
96 let current_hash = entry.hash_state.load(Ordering::Acquire);
97
98 if current_hash == EMPTY || current_hash == TOMBSTONE {
99 match entry.hash_state.compare_exchange(
101 current_hash,
102 hash_with_flag,
103 Ordering::AcqRel,
104 Ordering::Acquire
105 ) {
106 Ok(_) => {
107 let key_ptr = Box::into_raw(Box::new(key));
109 let value_ptr = Box::into_raw(Box::new(value));
110
111 entry.key.store(key_ptr, Ordering::Release);
112 entry.value.store(value_ptr, Ordering::Release);
113
114 if current_hash == EMPTY {
115 self.size.fetch_add(1, Ordering::Relaxed);
116 }
117 return None;
118 }
119 Err(_) => {
120 }
122 }
123 } else if current_hash == hash_with_flag {
124 let key_ptr = entry.key.load(Ordering::Acquire);
126 if !key_ptr.is_null() {
127 let stored_key = unsafe { &*key_ptr };
128 if stored_key == &key {
129 let new_value_ptr = Box::into_raw(Box::new(value));
131 let old_value_ptr = entry.value.swap(new_value_ptr, Ordering::AcqRel);
132
133 if !old_value_ptr.is_null() {
134 let old_value = unsafe { Box::from_raw(old_value_ptr) };
135 return Some(*old_value);
136 }
137 return None;
138 }
139 }
140 }
141
142 index = (index + 1) & self.mask;
144
145 if index == start_index {
147 return None;
149 }
150 }
151 }
152
153 pub fn get(&self, key: &K) -> Option<V> {
155 let hash = Self::hash_key(key);
156 let hash_with_flag = hash | OCCUPIED_FLAG;
157 let mut index = (hash as usize) & self.mask;
158 let start_index = index;
159
160 loop {
161 let entry = &self.entries[index];
162 let current_hash = entry.hash_state.load(Ordering::Acquire);
163
164 if current_hash == EMPTY {
165 return None;
166 }
167
168 if current_hash == hash_with_flag {
169 let key_ptr = entry.key.load(Ordering::Acquire);
170 if !key_ptr.is_null() {
171 let stored_key = unsafe { &*key_ptr };
172 if stored_key == key {
173 let value_ptr = entry.value.load(Ordering::Acquire);
174 if !value_ptr.is_null() {
175 let value = unsafe { &*value_ptr };
176 return Some(value.clone());
177 }
178 }
179 }
180 }
181
182 index = (index + 1) & self.mask;
183 if index == start_index {
184 return None;
185 }
186 }
187 }
188
189 pub fn remove(&self, key: &K) -> Option<V> {
191 let hash = Self::hash_key(key);
192 let hash_with_flag = hash | OCCUPIED_FLAG;
193 let mut index = (hash as usize) & self.mask;
194 let start_index = index;
195
196 loop {
197 let entry = &self.entries[index];
198 let current_hash = entry.hash_state.load(Ordering::Acquire);
199
200 if current_hash == EMPTY {
201 return None;
202 }
203
204 if current_hash == hash_with_flag {
205 let key_ptr = entry.key.load(Ordering::Acquire);
206 if !key_ptr.is_null() {
207 let stored_key = unsafe { &*key_ptr };
208 if stored_key == key {
209 match entry.hash_state.compare_exchange(
211 hash_with_flag,
212 TOMBSTONE,
213 Ordering::AcqRel,
214 Ordering::Acquire
215 ) {
216 Ok(_) => {
217 let key_ptr = entry.key.swap(null_mut(), Ordering::AcqRel);
219 let value_ptr = entry.value.swap(null_mut(), Ordering::AcqRel);
220
221 self.size.fetch_sub(1, Ordering::Relaxed);
222
223 if !key_ptr.is_null() {
224 unsafe { let _ = Box::from_raw(key_ptr); }
225 }
226
227 if !value_ptr.is_null() {
228 let value = unsafe { Box::from_raw(value_ptr) };
229 return Some(*value);
230 }
231 }
232 Err(_) => {
233 return None;
235 }
236 }
237 }
238 }
239 }
240
241 index = (index + 1) & self.mask;
242 if index == start_index {
243 return None;
244 }
245 }
246 }
247
248 pub fn contains_key(&self, key: &K) -> bool {
250 let hash = Self::hash_key(key);
251 let hash_with_flag = hash | OCCUPIED_FLAG;
252 let mut index = (hash as usize) & self.mask;
253 let start_index = index;
254
255 loop {
256 let entry = &self.entries[index];
257 let current_hash = entry.hash_state.load(Ordering::Acquire);
258
259 if current_hash == EMPTY {
260 return false;
261 }
262
263 if current_hash == hash_with_flag {
264 let key_ptr = entry.key.load(Ordering::Acquire);
265 if !key_ptr.is_null() {
266 let stored_key = unsafe { &*key_ptr };
267 if stored_key == key {
268 return true;
269 }
270 }
271 }
272
273 index = (index + 1) & self.mask;
274 if index == start_index {
275 return false;
276 }
277 }
278 }
279
280 pub fn len(&self) -> usize {
282 self.size.load(Ordering::Relaxed) as usize
283 }
284
285 pub fn is_empty(&self) -> bool {
287 self.len() == 0
288 }
289}
290
291unsafe impl<K: Send, V: Send> Send for FastHashMap<K, V> {}
292unsafe impl<K: Send + Sync, V: Send + Sync> Sync for FastHashMap<K, V> {}
293
294impl<K, V> Drop for FastHashMap<K, V> {
295 fn drop(&mut self) {
296 for entry in self.entries.iter() {
297 let key_ptr = entry.key.load(Ordering::Acquire);
298 let value_ptr = entry.value.load(Ordering::Acquire);
299
300 if !key_ptr.is_null() {
301 unsafe { let _ = Box::from_raw(key_ptr); }
302 }
303
304 if !value_ptr.is_null() {
305 unsafe { let _ = Box::from_raw(value_ptr); }
306 }
307 }
308 }
309}