1#![warn(unsafe_op_in_unsafe_fn)]
6
7use crate::rcu_array::RcuArray;
8use crate::rcu_intrusive_list::{
9 Link, RcuIntrusiveList, RcuIntrusiveListCursor, RcuListAdapter, rcu_list_adapter,
10};
11use crate::rcu_list::RcuList;
12use fuchsia_rcu::{RcuDroppable, RcuReadScope};
13use std::borrow::Borrow;
14use std::hash::{BuildHasher, Hash, Hasher};
15use std::sync::atomic::{AtomicUsize, Ordering};
16
17const INITIAL_CAPACITY: usize = 16;
19
20#[derive(Debug, RcuDroppable)]
22struct Entry<K, V> {
23 key: K,
25
26 value: V,
28
29 collision_chain: Link,
31
32 insertion_chain: Link,
34}
35
36impl<K, V> Entry<K, V> {
37 fn new(key: K, value: V) -> Self {
39 Self {
40 key,
41 value,
42 collision_chain: Default::default(),
43 insertion_chain: Default::default(),
44 }
45 }
46}
47
48#[derive(Debug, RcuDroppable)]
50struct CollisionAdapter;
51
52impl<K, V> RcuListAdapter<Entry<K, V>> for CollisionAdapter {
53 rcu_list_adapter!(Entry<K, V>, collision_chain);
54}
55
56#[derive(Debug, RcuDroppable)]
58struct InsertionAdapter;
59
60impl<K, V> RcuListAdapter<Entry<K, V>> for InsertionAdapter {
61 rcu_list_adapter!(Entry<K, V>, insertion_chain);
62}
63
64pub enum InsertionResult<V> {
66 Inserted(usize),
70
71 Updated(V),
75}
76
77type Bucket<K, V> = RcuList<Entry<K, V>, CollisionAdapter>;
81
82#[derive(RcuDroppable)]
88pub struct RcuRawHashMap<K, V, S = rapidhash::RapidBuildHasher>
89where
90 K: Eq + Hash + Clone + RcuDroppable + Sync,
91 V: Clone + RcuDroppable + Sync,
92 S: BuildHasher + Send + Sync + 'static,
93{
94 table: RcuArray<Bucket<K, V>>,
96
97 num_entries: AtomicUsize,
99
100 insertion_chain: RcuIntrusiveList<Entry<K, V>, InsertionAdapter>,
102
103 hash_builder: S,
105}
106
107impl<K, V> Default for RcuRawHashMap<K, V, rapidhash::RapidBuildHasher>
108where
109 K: Eq + Hash + Clone + RcuDroppable + Sync,
110 V: Clone + RcuDroppable + Sync,
111{
112 fn default() -> Self {
113 Self::with_capacity_and_hasher(0, rapidhash::RapidBuildHasher::default())
114 }
115}
116
117impl<K, V> RcuRawHashMap<K, V, rapidhash::RapidBuildHasher>
118where
119 K: Eq + Hash + Clone + RcuDroppable + Sync,
120 V: Clone + RcuDroppable + Sync,
121{
122 pub fn with_capacity(capacity: usize) -> Self {
124 Self::with_capacity_and_hasher(capacity, rapidhash::RapidBuildHasher::default())
125 }
126}
127
128impl<K, V, S> RcuRawHashMap<K, V, S>
129where
130 K: Eq + Hash + Clone + RcuDroppable + Sync,
131 V: Clone + RcuDroppable + Sync,
132 S: BuildHasher + Send + Sync + 'static,
133{
134 pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
136 let mut table = Vec::new();
137 table.resize_with((capacity + 1) / 2, Default::default);
138 Self {
139 table: RcuArray::from(table),
140 num_entries: AtomicUsize::new(0),
141 insertion_chain: Default::default(),
142 hash_builder,
143 }
144 }
145
146 pub fn with_hasher(hash_builder: S) -> Self {
148 Self::with_capacity_and_hasher(0, hash_builder)
149 }
150
151 fn hash_key<Q>(&self, key: &Q) -> u64
153 where
154 Q: ?Sized + Hash,
155 {
156 let mut hasher = self.hash_builder.build_hasher();
157 key.hash(&mut hasher);
158 hasher.finish()
159 }
160
161 fn get_bucket<'a, Q>(&self, table: &'a [Bucket<K, V>], key: &Q) -> &'a Bucket<K, V>
163 where
164 K: Borrow<Q>,
165 Q: ?Sized + Hash,
166 {
167 let hash = self.hash_key(key);
168 let index = hash as usize % table.len();
169 &table[index]
170 }
171
172 fn read_bucket<'a, Q>(&self, scope: &'a RcuReadScope, key: &Q) -> Option<&'a Bucket<K, V>>
174 where
175 K: Borrow<Q>,
176 Q: ?Sized + Hash,
177 {
178 let table = self.table.as_slice(scope);
179 if table.is_empty() {
180 return None;
181 }
182 Some(self.get_bucket(table, key))
183 }
184
185 pub fn get<'a, Q>(&self, scope: &'a RcuReadScope, key: &Q) -> Option<&'a V>
189 where
190 K: Borrow<Q>,
191 Q: ?Sized + Hash + Eq,
192 {
193 let bucket = self.read_bucket(scope, key)?;
194 bucket.iter(scope).find(|entry| entry.key.borrow() == key).map(|entry| &entry.value)
195 }
196
197 pub fn len(&self) -> usize {
201 self.num_entries.load(Ordering::Relaxed)
202 }
203
204 pub unsafe fn insert(&self, scope: &RcuReadScope, key: K, value: V) -> InsertionResult<V> {
218 let mut table = self.table.as_slice(scope);
219 if self.needs_to_grow(table) {
220 table = unsafe { self.grow(&scope, table) };
223 }
224 let bucket = self.get_bucket(table, &key);
225 let mut cursor = bucket.cursor(&scope);
226 while let Some(entry) = cursor.current() {
227 if entry.key == key {
228 let old_value = entry.value.clone();
229 unsafe {
232 let removed_entry = cursor.remove();
233 self.insertion_chain.remove(&scope, removed_entry);
234 let entry = bucket.push_front(&scope, Entry::new(key, value));
235 self.insertion_chain.push_back(&scope, entry);
236 };
237 return InsertionResult::Updated(old_value);
238 }
239 cursor.advance();
240 }
241
242 unsafe {
245 let entry = bucket.push_front(&scope, Entry::new(key, value));
246 self.insertion_chain.push_back(&scope, entry);
247 }
248 let count = self.num_entries.fetch_add(1, Ordering::Relaxed);
249 InsertionResult::Inserted(count + 1)
250 }
251
252 pub unsafe fn remove<Q>(&self, key: &Q) -> Option<V>
262 where
263 K: Borrow<Q>,
264 Q: ?Sized + Hash + Eq,
265 {
266 let scope = RcuReadScope::new();
267 let bucket = self.read_bucket(&scope, key)?;
268 let mut cursor = bucket.cursor(&scope);
269 while let Some(entry) = cursor.current() {
270 if entry.key.borrow() == key {
271 let old_value = entry.value.clone();
272 unsafe {
275 let removed_entry = cursor.remove();
276 self.insertion_chain.remove(&scope, removed_entry);
277 };
278 self.num_entries.fetch_sub(1, Ordering::Relaxed);
279 return Some(old_value);
280 }
281 cursor.advance();
282 }
283 None
284 }
285
286 fn needs_to_grow(&self, table: &[Bucket<K, V>]) -> bool {
288 table.is_empty() || self.num_entries.load(Ordering::Relaxed) > table.len() * 2
289 }
290
291 #[must_use]
300 unsafe fn grow<'a>(
301 &self,
302 scope: &'a RcuReadScope,
303 old_table: &[Bucket<K, V>],
304 ) -> &'a [Bucket<K, V>] {
305 let new_size = if old_table.is_empty() { INITIAL_CAPACITY } else { old_table.len() * 2 };
306 let mut new_table = Vec::new();
307 let new_insertion_chain = RcuIntrusiveList::default();
308 new_table.resize_with(new_size, Default::default);
309
310 for entry in self.insertion_chain.iter(scope) {
311 let bucket = self.get_bucket(&new_table, &entry.key);
312 let key = entry.key.clone();
313 let value = entry.value.clone();
314 unsafe {
316 let entry = bucket.push_front(&scope, Entry::new(key, value));
317 new_insertion_chain.push_back(&scope, entry);
318 };
319 }
320
321 self.table.update(new_table);
322 unsafe {
324 self.insertion_chain.update(&scope, new_insertion_chain);
325 }
326 self.table.as_slice(scope)
327 }
328
329 pub fn cursor<'a>(&'a self, scope: &'a RcuReadScope) -> RcuRawHashMapCursor<'a, K, V, S> {
333 RcuRawHashMapCursor { inner: self.insertion_chain.cursor(scope), map: self }
334 }
335
336 pub fn keys<'a>(&'a self, scope: &'a RcuReadScope) -> impl Iterator<Item = &'a K> {
338 self.insertion_chain.iter(scope).map(|entry| &entry.key)
339 }
340}
341
342impl<K, V, S> std::fmt::Debug for RcuRawHashMap<K, V, S>
344where
345 K: Eq + Hash + Clone + RcuDroppable + Sync + std::fmt::Debug,
346 V: Clone + RcuDroppable + Sync + std::fmt::Debug,
347 S: std::hash::BuildHasher + Send + Sync + 'static,
348{
349 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
350 f.debug_struct("RcuRawHashMap")
351 .field("table", &self.table)
352 .field("num_entries", &self.num_entries)
353 .field("insertion_chain", &self.insertion_chain)
354 .field("hash_builder", &std::any::type_name::<S>())
355 .finish_non_exhaustive()
356 }
357}
358
359pub struct RcuRawHashMapCursor<'a, K, V, S = rapidhash::RapidBuildHasher>
363where
364 K: Eq + Hash + Clone + RcuDroppable + Sync,
365 V: Clone + RcuDroppable + Sync,
366 S: BuildHasher + Send + Sync + 'static,
367{
368 inner: RcuIntrusiveListCursor<'a, Entry<K, V>, InsertionAdapter>,
369 map: &'a RcuRawHashMap<K, V, S>,
370}
371
372impl<'a, K, V, S> RcuRawHashMapCursor<'a, K, V, S>
373where
374 K: Eq + Hash + Clone + RcuDroppable + Sync,
375 V: Clone + RcuDroppable + Sync,
376 S: BuildHasher + Send + Sync + 'static,
377{
378 pub fn current(&self) -> Option<(&'a K, &'a V)> {
380 self.inner.current().map(|entry| (&entry.key, &entry.value))
381 }
382
383 pub fn advance(&mut self) {
385 self.inner.advance()
386 }
387
388 pub unsafe fn remove(&mut self) -> Option<V> {
399 if let Some((key, _)) = self.current() {
400 self.advance();
401 unsafe { self.map.remove(key) }
403 } else {
404 None
405 }
406 }
407}
408
409#[cfg(test)]
410mod tests {
411 use super::*;
412 use fuchsia_rcu::rcu_run_callbacks;
413
414 #[test]
415 fn test_rcu_hash_map_custom_hasher() {
416 use std::collections::hash_map::DefaultHasher;
417 use std::hash::BuildHasherDefault;
418 let hasher = BuildHasherDefault::<DefaultHasher>::default();
419 let map = RcuRawHashMap::with_capacity_and_hasher(10, hasher);
420 let scope = RcuReadScope::new();
421 unsafe {
422 map.insert(&scope, 1, 10);
423 }
424 assert_eq!(map.get(&scope, &1), Some(&10));
425 }
426
427 #[test]
428 fn test_rcu_hash_map_insert_and_get() {
429 let map = RcuRawHashMap::default();
430 let scope = RcuReadScope::new();
431 unsafe {
432 map.insert(&scope, 1, 10);
433 map.insert(&scope, 2, 20);
434 }
435
436 assert_eq!(map.get(&scope, &1), Some(&10));
437 assert_eq!(map.get(&scope, &2), Some(&20));
438 assert_eq!(map.get(&scope, &3), None);
439
440 std::mem::drop(scope);
441 rcu_run_callbacks();
442 }
443
444 #[test]
445 fn test_rcu_hash_map_remove() {
446 let map = RcuRawHashMap::default();
447 let scope = RcuReadScope::new();
448 unsafe {
449 map.insert(&scope, 1, 10);
450 map.insert(&scope, 2, 20);
451 }
452
453 assert_eq!(map.get(&scope, &1), Some(&10));
454
455 unsafe {
456 assert_eq!(map.remove(&1), Some(10));
457 }
458
459 assert_eq!(map.get(&scope, &1), None);
460 assert_eq!(map.get(&scope, &2), Some(&20));
461
462 std::mem::drop(scope);
463 rcu_run_callbacks();
464 }
465
466 #[test]
467 fn test_rcu_hash_map_insert_update() {
468 let map = RcuRawHashMap::default();
469 let scope = RcuReadScope::new();
470 unsafe {
471 map.insert(&scope, 1, 10);
472 }
473
474 assert_eq!(map.get(&scope, &1), Some(&10));
475
476 let result = unsafe { map.insert(&scope, 1, 100) };
477 assert!(matches!(result, InsertionResult::Updated(10)));
478
479 assert_eq!(map.get(&scope, &1), Some(&100));
480
481 std::mem::drop(scope);
482 rcu_run_callbacks();
483 }
484
485 #[test]
486 fn test_rcu_hash_map_cursor() {
487 let map = RcuRawHashMap::default();
488 let scope = RcuReadScope::new();
489 unsafe {
490 map.insert(&scope, 1, 10);
491 map.insert(&scope, 2, 20);
492 map.insert(&scope, 3, 30);
493 }
494
495 let mut cursor = map.cursor(&scope);
496
497 assert_eq!(cursor.current(), Some((&1, &10)));
498 cursor.advance();
499 assert_eq!(cursor.current(), Some((&2, &20)));
500
501 unsafe {
502 cursor.remove();
503 }
504
505 assert_eq!(cursor.current(), Some((&3, &30)));
506 assert_eq!(map.get(&scope, &2), None);
507
508 cursor.advance();
509 assert_eq!(cursor.current(), None);
510
511 std::mem::drop(scope);
512 rcu_run_callbacks();
513 }
514
515 #[test]
516 fn test_rcu_hash_map_grow_maintains_order() {
517 let map = RcuRawHashMap::default();
518 let scope = RcuReadScope::new();
519 let num_elements = INITIAL_CAPACITY * 3;
520 let mut expected_order = Vec::new();
521
522 for i in 0..num_elements {
523 unsafe {
524 map.insert(&scope, i, i * 10);
525 }
526 expected_order.push((i, i * 10));
527 }
528
529 let mut cursor = map.cursor(&scope);
530 let mut actual_order = Vec::new();
531
532 while let Some((key, value)) = cursor.current() {
533 actual_order.push((*key, *value));
534 cursor.advance();
535 }
536
537 assert_eq!(actual_order, expected_order);
538
539 std::mem::drop(scope);
540 rcu_run_callbacks();
541 }
542 #[test]
543 fn test_rcu_hash_map_grow_overwrites_maintain_order() {
544 let map = RcuRawHashMap::default();
545 let scope = RcuReadScope::new();
546 let num_elements = INITIAL_CAPACITY * 3;
547 let mut expected_order = Vec::new();
548
549 for i in 0..num_elements {
550 unsafe {
551 map.insert(&scope, i, i * 10);
552 }
553 expected_order.push((i, i * 10));
554 }
555
556 unsafe {
558 map.insert(&scope, 5, 500);
559 map.insert(&scope, INITIAL_CAPACITY * 3, (INITIAL_CAPACITY * 3) * 10); }
561 expected_order.retain(|(k, _)| *k != 5);
562 expected_order.push((5, 500));
563 expected_order.push((INITIAL_CAPACITY * 3, (INITIAL_CAPACITY * 3) * 10));
564
565 let mut cursor = map.cursor(&scope);
566 let mut actual_order = Vec::new();
567
568 while let Some((key, value)) = cursor.current() {
569 actual_order.push((*key, *value));
570 cursor.advance();
571 }
572
573 assert_eq!(actual_order, expected_order);
574
575 std::mem::drop(scope);
576 rcu_run_callbacks();
577 }
578
579 #[test]
580 fn test_rcu_hash_map_grow() {
581 let map = RcuRawHashMap::default();
582 let scope = RcuReadScope::new();
583 for i in 0..(INITIAL_CAPACITY * 3) {
584 unsafe {
585 map.insert(&scope, i, i * 10);
586 }
587 }
588
589 for i in 0..(INITIAL_CAPACITY * 3) {
590 assert_eq!(map.get(&scope, &i), Some(&(i * 10)));
591 }
592
593 std::mem::drop(scope);
594 rcu_run_callbacks();
595 }
596
597 #[test]
598 fn test_rcu_hash_map_capacity_zero() {
599 let map = RcuRawHashMap::with_capacity(0);
600 let scope = RcuReadScope::new();
601
602 assert_eq!(map.get(&scope, &1), None);
603
604 unsafe {
605 map.insert(&scope, 1, 10);
606 }
607 assert_eq!(map.get(&scope, &1), Some(&10));
608
609 unsafe {
610 assert_eq!(map.remove(&1), Some(10));
611 }
612 assert_eq!(map.get(&scope, &1), None);
613
614 std::mem::drop(scope);
615 rcu_run_callbacks();
616 }
617}