1extern crate alloc;
20
21#[cfg(feature = "std")]
22extern crate std;
23
24use alloc::boxed::Box;
25use alloc::vec::Vec;
26use core::borrow::Borrow;
27use core::hash::{BuildHasher, Hash};
28use core::sync::atomic::Ordering;
29use foldhash::fast::FixedState;
30use kovan::{Atomic, Shared, pin, retire};
31
32const BUCKET_COUNT: usize = 524_288;
38
39struct Backoff {
41 step: u32,
42}
43
44impl Backoff {
45 #[inline(always)]
46 fn new() -> Self {
47 Self { step: 0 }
48 }
49
50 #[inline(always)]
51 fn spin(&mut self) {
52 for _ in 0..(1 << self.step.min(6)) {
53 core::hint::spin_loop();
54 }
55 if self.step <= 6 {
56 self.step += 1;
57 }
58 }
59}
60
61struct Node<K, V> {
64 hash: u64,
65 key: K,
66 value: V,
67 next: Atomic<Node<K, V>>,
68}
69
70pub struct HashMap<K: 'static, V: 'static, S = FixedState> {
72 buckets: Box<[Atomic<Node<K, V>>]>,
73 mask: usize,
74 hasher: S,
75}
76
77#[cfg(feature = "std")]
78impl<K, V> HashMap<K, V, FixedState>
79where
80 K: Hash + Eq + Clone + 'static,
81 V: Clone + 'static,
82{
83 pub fn new() -> Self {
85 Self::with_hasher(FixedState::default())
86 }
87}
88
89impl<K, V, S> HashMap<K, V, S>
90where
91 K: Hash + Eq + Clone + 'static,
92 V: Clone + 'static,
93 S: BuildHasher,
94{
95 pub fn with_hasher(hasher: S) -> Self {
97 let mut buckets = Vec::with_capacity(BUCKET_COUNT);
98 for _ in 0..BUCKET_COUNT {
99 buckets.push(Atomic::null());
100 }
101
102 Self {
103 buckets: buckets.into_boxed_slice(),
104 mask: BUCKET_COUNT - 1,
105 hasher,
106 }
107 }
108
109 #[inline(always)]
110 fn get_bucket_idx(&self, hash: u64) -> usize {
111 (hash as usize) & self.mask
112 }
113
114 #[inline(always)]
115 fn get_bucket(&self, idx: usize) -> &Atomic<Node<K, V>> {
116 unsafe { self.buckets.get_unchecked(idx) }
117 }
118
119 pub fn get<Q>(&self, key: &Q) -> Option<V>
121 where
122 K: Borrow<Q>,
123 Q: Hash + Eq + ?Sized,
124 {
125 let hash = self.hasher.hash_one(key);
126 let idx = self.get_bucket_idx(hash);
127 let bucket = self.get_bucket(idx);
128
129 let guard = pin();
130 let mut current = bucket.load(Ordering::Acquire, &guard);
131
132 while !current.is_null() {
133 unsafe {
134 let node = current.deref();
135 if node.hash == hash && node.key.borrow() == key {
137 return Some(node.value.clone());
138 }
139 current = node.next.load(Ordering::Acquire, &guard);
140 }
141 }
142 None
143 }
144
145 pub fn contains_key<Q>(&self, key: &Q) -> bool
147 where
148 K: Borrow<Q>,
149 Q: Hash + Eq + ?Sized,
150 {
151 self.get(key).is_some()
152 }
153
154 pub fn insert(&self, key: K, value: V) -> Option<V> {
156 let hash = self.hasher.hash_one(&key);
157 let idx = self.get_bucket_idx(hash);
158 let bucket = self.get_bucket(idx);
159 let mut backoff = Backoff::new();
160
161 let guard = pin();
162
163 'outer: loop {
164 let mut prev_link = bucket;
166 let mut current = prev_link.load(Ordering::Acquire, &guard);
167
168 while !current.is_null() {
169 unsafe {
170 let node = current.deref();
171
172 if node.hash == hash && node.key == key {
173 let next = node.next.load(Ordering::Relaxed, &guard);
175 let old_value = node.value.clone();
176
177 let new_node = Box::into_raw(Box::new(Node {
179 hash,
180 key: key.clone(),
181 value: value.clone(),
182 next: Atomic::new(next.as_raw()),
183 }));
184
185 match prev_link.compare_exchange(
186 current,
187 Shared::from_raw(new_node),
188 Ordering::Release,
189 Ordering::Relaxed,
190 &guard,
191 ) {
192 Ok(_) => {
193 retire(current.as_raw());
194 return Some(old_value);
195 }
196 Err(_) => {
197 drop(Box::from_raw(new_node));
199 backoff.spin();
200 continue 'outer;
201 }
202 }
203 }
204
205 prev_link = &node.next;
206 current = node.next.load(Ordering::Acquire, &guard);
207 }
208 }
209
210 let new_node_ptr = Box::into_raw(Box::new(Node {
213 hash,
214 key: key.clone(),
215 value: value.clone(),
216 next: Atomic::null(),
217 }));
218
219 match prev_link.compare_exchange(
221 unsafe { Shared::from_raw(core::ptr::null_mut()) },
222 unsafe { Shared::from_raw(new_node_ptr) },
223 Ordering::Release,
224 Ordering::Relaxed,
225 &guard,
226 ) {
227 Ok(_) => return None,
228 Err(actual_val) => {
229 unsafe {
233 let actual_node = actual_val.deref();
234 if actual_node.hash == hash && actual_node.key == key {
235 drop(Box::from_raw(new_node_ptr));
237 backoff.spin();
238 continue 'outer;
239 }
240 }
241
242 unsafe {
244 drop(Box::from_raw(new_node_ptr));
245 }
246 backoff.spin();
247 continue 'outer;
248 }
249 }
250 }
251 }
252
253 pub fn insert_if_absent(&self, key: K, value: V) -> Option<V> {
256 let hash = self.hasher.hash_one(&key);
257 let idx = self.get_bucket_idx(hash);
258 let bucket = self.get_bucket(idx);
259 let mut backoff = Backoff::new();
260
261 let guard = pin();
262
263 'outer: loop {
264 let mut prev_link = bucket;
266 let mut current = prev_link.load(Ordering::Acquire, &guard);
267
268 while !current.is_null() {
269 unsafe {
270 let node = current.deref();
271
272 if node.hash == hash && node.key == key {
273 return Some(node.value.clone());
275 }
276
277 prev_link = &node.next;
278 current = node.next.load(Ordering::Acquire, &guard);
279 }
280 }
281
282 let new_node_ptr = Box::into_raw(Box::new(Node {
284 hash,
285 key: key.clone(),
286 value: value.clone(),
287 next: Atomic::null(),
288 }));
289
290 match prev_link.compare_exchange(
292 unsafe { Shared::from_raw(core::ptr::null_mut()) },
293 unsafe { Shared::from_raw(new_node_ptr) },
294 Ordering::Release,
295 Ordering::Relaxed,
296 &guard,
297 ) {
298 Ok(_) => return None,
299 Err(actual_val) => {
300 unsafe {
302 let actual_node = actual_val.deref();
303 if actual_node.hash == hash && actual_node.key == key {
304 drop(Box::from_raw(new_node_ptr));
306 return Some(actual_node.value.clone());
307 }
308 }
309
310 unsafe {
312 drop(Box::from_raw(new_node_ptr));
313 }
314 backoff.spin();
315 continue 'outer;
316 }
317 }
318 }
319 }
320
321 pub fn remove<Q>(&self, key: &Q) -> Option<V>
323 where
324 K: Borrow<Q>,
325 Q: Hash + Eq + ?Sized,
326 {
327 let hash = self.hasher.hash_one(key);
328 let idx = self.get_bucket_idx(hash);
329 let bucket = self.get_bucket(idx);
330 let mut backoff = Backoff::new();
331
332 let guard = pin();
333
334 loop {
335 let mut prev_link = bucket;
336 let mut current = prev_link.load(Ordering::Acquire, &guard);
337
338 while !current.is_null() {
339 unsafe {
340 let node = current.deref();
341
342 if node.hash == hash && node.key.borrow() == key {
343 let next = node.next.load(Ordering::Acquire, &guard);
344 let old_value = node.value.clone();
345
346 match prev_link.compare_exchange(
347 current,
348 next,
349 Ordering::Release,
350 Ordering::Relaxed,
351 &guard,
352 ) {
353 Ok(_) => {
354 retire(current.as_raw());
355 return Some(old_value);
356 }
357 Err(_) => {
358 backoff.spin();
359 break; }
361 }
362 }
363
364 prev_link = &node.next;
365 current = node.next.load(Ordering::Acquire, &guard);
366 }
367 }
368
369 if current.is_null() {
370 return None;
371 }
372 }
373 }
374
375 pub fn clear(&self) {
377 let guard = pin();
378
379 for bucket in self.buckets.iter() {
380 loop {
381 let head = bucket.load(Ordering::Acquire, &guard);
382 if head.is_null() {
383 break;
384 }
385
386 match bucket.compare_exchange(
388 head,
389 unsafe { Shared::from_raw(core::ptr::null_mut()) },
390 Ordering::Release,
391 Ordering::Relaxed,
392 &guard,
393 ) {
394 Ok(_) => {
395 unsafe {
397 let mut current = head;
398 while !current.is_null() {
399 let node = current.deref();
400 let next = node.next.load(Ordering::Relaxed, &guard);
401 retire(current.as_raw());
402 current = next;
403 }
404 }
405 break;
406 }
407 Err(_) => {
408 continue;
410 }
411 }
412 }
413 }
414 }
415
416 pub fn is_empty(&self) -> bool {
418 self.len() == 0
419 }
420
421 pub fn len(&self) -> usize {
424 let mut count = 0;
425 let guard = pin();
426 for bucket in self.buckets.iter() {
427 let mut current = bucket.load(Ordering::Acquire, &guard);
428 while !current.is_null() {
429 unsafe {
430 let node = current.deref();
431 count += 1;
432 current = node.next.load(Ordering::Acquire, &guard);
433 }
434 }
435 }
436 count
437 }
438
439 pub fn iter(&self) -> Iter<'_, K, V, S> {
442 Iter {
443 map: self,
444 bucket_idx: 0,
445 current: core::ptr::null(),
446 guard: pin(),
447 }
448 }
449
450 pub fn keys(&self) -> Keys<'_, K, V, S> {
453 Keys { iter: self.iter() }
454 }
455
456 pub fn hasher(&self) -> &S {
458 &self.hasher
459 }
460}
461
462pub struct Iter<'a, K: 'static, V: 'static, S> {
464 map: &'a HashMap<K, V, S>,
465 bucket_idx: usize,
466 current: *const Node<K, V>,
467 guard: kovan::Guard,
468}
469
470impl<'a, K, V, S> Iterator for Iter<'a, K, V, S>
471where
472 K: Clone,
473 V: Clone,
474{
475 type Item = (K, V);
476
477 fn next(&mut self) -> Option<Self::Item> {
478 loop {
479 if !self.current.is_null() {
480 unsafe {
481 let node = &*self.current;
482 self.current = node.next.load(Ordering::Acquire, &self.guard).as_raw();
484 return Some((node.key.clone(), node.value.clone()));
485 }
486 }
487
488 if self.bucket_idx >= self.map.buckets.len() {
490 return None;
491 }
492
493 let bucket = unsafe { self.map.buckets.get_unchecked(self.bucket_idx) };
494 self.bucket_idx += 1;
495 self.current = bucket.load(Ordering::Acquire, &self.guard).as_raw();
496 }
497 }
498}
499
500pub struct Keys<'a, K: 'static, V: 'static, S> {
502 iter: Iter<'a, K, V, S>,
503}
504
505impl<'a, K, V, S> Iterator for Keys<'a, K, V, S>
506where
507 K: Clone,
508 V: Clone,
509{
510 type Item = K;
511
512 fn next(&mut self) -> Option<Self::Item> {
513 self.iter.next().map(|(k, _)| k)
514 }
515}
516
517impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S>
518where
519 K: Hash + Eq + Clone + 'static,
520 V: Clone + 'static,
521 S: BuildHasher,
522{
523 type Item = (K, V);
524 type IntoIter = Iter<'a, K, V, S>;
525
526 fn into_iter(self) -> Self::IntoIter {
527 self.iter()
528 }
529}
530
531#[cfg(feature = "std")]
532impl<K, V> Default for HashMap<K, V, FixedState>
533where
534 K: Hash + Eq + Clone + 'static,
535 V: Clone + 'static,
536{
537 fn default() -> Self {
538 Self::new()
539 }
540}
541
542unsafe impl<K: Send, V: Send, S: Send> Send for HashMap<K, V, S> {}
544unsafe impl<K: Sync, V: Sync, S: Sync> Sync for HashMap<K, V, S> {}
545
546impl<K, V, S> Drop for HashMap<K, V, S> {
547 fn drop(&mut self) {
548 let guard = pin();
549
550 for bucket in self.buckets.iter() {
551 let mut current = bucket.load(Ordering::Acquire, &guard);
552
553 unsafe {
554 while !current.is_null() {
555 let node = current.deref();
556 let next = node.next.load(Ordering::Relaxed, &guard);
557 retire(current.as_raw());
559 current = next;
560 }
561 }
562 }
563 }
564}
565
566#[cfg(test)]
567mod tests {
568 use super::*;
569
570 #[test]
571 fn test_insert_and_get() {
572 let map = HashMap::new();
573 assert_eq!(map.insert(1, 100), None);
574 assert_eq!(map.get(&1), Some(100));
575 assert_eq!(map.get(&2), None);
576 }
577
578 #[test]
579 fn test_insert_replace() {
580 let map = HashMap::new();
581 assert_eq!(map.insert(1, 100), None);
582 assert_eq!(map.insert(1, 200), Some(100));
583 assert_eq!(map.get(&1), Some(200));
584 }
585
586 #[test]
587 fn test_concurrent_inserts() {
588 use alloc::sync::Arc;
589 extern crate std;
590 use std::thread;
591
592 let map = Arc::new(HashMap::new());
593 let mut handles = alloc::vec::Vec::new();
594
595 for thread_id in 0..4 {
596 let map_clone = Arc::clone(&map);
597 let handle = thread::spawn(move || {
598 for i in 0..1000 {
599 let key = thread_id * 1000 + i;
600 map_clone.insert(key, key * 2);
601 }
602 });
603 handles.push(handle);
604 }
605
606 for handle in handles {
607 handle.join().unwrap();
608 }
609
610 for thread_id in 0..4 {
611 for i in 0..1000 {
612 let key = thread_id * 1000 + i;
613 assert_eq!(map.get(&key), Some(key * 2));
614 }
615 }
616 }
617}