scc2/hash_index.rs
1//! [`HashIndex`] is a read-optimized concurrent and asynchronous hash map.
2
3use super::ebr::{AtomicShared, Guard, Shared};
4use super::hash_table::bucket::{Bucket, EntryPtr, Locker, OPTIMISTIC};
5use super::hash_table::bucket_array::BucketArray;
6use super::hash_table::{HashTable, LockedEntry};
7use super::wait_queue::AsyncWait;
8use super::Equivalent;
9use std::collections::hash_map::RandomState;
10use std::fmt::{self, Debug};
11use std::hash::{BuildHasher, Hash};
12use std::iter::FusedIterator;
13use std::ops::{Deref, RangeInclusive};
14use std::panic::UnwindSafe;
15use std::pin::Pin;
16use std::ptr;
17use std::sync::atomic::AtomicUsize;
18use std::sync::atomic::Ordering::{Acquire, Relaxed};
19
20/// Scalable concurrent hash index.
21///
22/// [`HashIndex`] is a concurrent and asynchronous hash map data structure optimized for parallel
23/// read operations. The key characteristics of [`HashIndex`] are similar to that of
24/// [`HashMap`](super::HashMap) except its read operations are lock-free.
25///
26/// ## The key differences between [`HashIndex`] and [`HashMap`](crate::HashMap).
27///
28/// * Lock-free-read: read and scan operations are never blocked and do not modify shared data.
29/// * Immutability: the data in the container is immutable until it becomes unreachable.
30/// * Linearizability: linearizability of read operations relies on the CPU architecture.
31///
32/// ## The key statistics for [`HashIndex`]
33///
34/// * The expected size of metadata for a single key-value pair: 2-byte.
35/// * The expected number of atomic write operations required for an operation on a single key: 2.
36/// * The expected number of atomic variables accessed during a single key operation: 2.
37/// * The number of entries managed by a single bucket without a linked list: 32.
38/// * The expected maximum linked list length when resize is triggered: log(capacity) / 8.
39///
40/// ### Unwind safety
41///
42/// [`HashIndex`] is impervious to out-of-memory errors and panics in user-specified code on one
43/// condition; `H::Hasher::hash`, `K::drop` and `V::drop` must not panic.
44pub struct HashIndex<K, V, H = RandomState>
45where
46 H: BuildHasher,
47{
48 array: AtomicShared<BucketArray<K, V, (), OPTIMISTIC>>,
49 minimum_capacity: AtomicUsize,
50 build_hasher: H,
51}
52
53/// [`Entry`] represents a single entry in a [`HashIndex`].
54pub enum Entry<'h, K, V, H = RandomState>
55where
56 H: BuildHasher,
57{
58 /// An occupied entry.
59 Occupied(OccupiedEntry<'h, K, V, H>),
60
61 /// A vacant entry.
62 Vacant(VacantEntry<'h, K, V, H>),
63}
64
65/// [`OccupiedEntry`] is a view into an occupied entry in a [`HashIndex`].
66pub struct OccupiedEntry<'h, K, V, H = RandomState>
67where
68 H: BuildHasher,
69{
70 hashindex: &'h HashIndex<K, V, H>,
71 locked_entry: LockedEntry<'h, K, V, (), OPTIMISTIC>,
72}
73
74/// [`VacantEntry`] is a view into a vacant entry in a [`HashIndex`].
75pub struct VacantEntry<'h, K, V, H = RandomState>
76where
77 H: BuildHasher,
78{
79 hashindex: &'h HashIndex<K, V, H>,
80 key: K,
81 hash: u64,
82 locked_entry: LockedEntry<'h, K, V, (), OPTIMISTIC>,
83}
84
85/// [`Reserve`] keeps the capacity of the associated [`HashIndex`] higher than a certain level.
86///
87/// The [`HashIndex`] does not shrink the capacity below the reserved capacity.
88pub struct Reserve<'h, K, V, H = RandomState>
89where
90 K: 'static + Clone + Eq + Hash,
91 V: 'static + Clone,
92 H: BuildHasher,
93{
94 hashindex: &'h HashIndex<K, V, H>,
95 additional: usize,
96}
97
98/// An iterator over the entries of a [`HashIndex`].
99///
100/// An [`Iter`] iterates over all the entries that survive the [`Iter`].
101pub struct Iter<'h, 'g, K, V, H = RandomState>
102where
103 H: BuildHasher,
104{
105 hashindex: &'h HashIndex<K, V, H>,
106 current_array: Option<&'g BucketArray<K, V, (), OPTIMISTIC>>,
107 current_index: usize,
108 current_bucket: Option<&'g Bucket<K, V, (), OPTIMISTIC>>,
109 current_entry_ptr: EntryPtr<'g, K, V, OPTIMISTIC>,
110 guard: &'g Guard,
111}
112
113impl<K, V, H> HashIndex<K, V, H>
114where
115 H: BuildHasher,
116{
117 /// Creates an empty [`HashIndex`] with the given [`BuildHasher`].
118 ///
119 /// # Examples
120 ///
121 /// ```
122 /// use scc2::HashIndex;
123 /// use std::collections::hash_map::RandomState;
124 ///
125 /// let hashindex: HashIndex<u64, u32, RandomState> =
126 /// HashIndex::with_hasher(RandomState::new());
127 /// ```
128 #[cfg(not(feature = "loom"))]
129 #[inline]
130 pub const fn with_hasher(build_hasher: H) -> Self {
131 Self {
132 array: AtomicShared::null(),
133 minimum_capacity: AtomicUsize::new(0),
134 build_hasher,
135 }
136 }
137
138 /// Creates an empty [`HashIndex`] with the given [`BuildHasher`].
139 #[cfg(feature = "loom")]
140 #[inline]
141 pub fn with_hasher(build_hasher: H) -> Self {
142 Self {
143 array: AtomicShared::null(),
144 minimum_capacity: AtomicUsize::new(0),
145 build_hasher,
146 }
147 }
148
149 /// Creates an empty [`HashIndex`] with the specified capacity and [`BuildHasher`].
150 ///
151 /// The actual capacity is equal to or greater than the specified capacity.
152 ///
153 /// # Examples
154 ///
155 /// ```
156 /// use scc2::HashIndex;
157 /// use std::collections::hash_map::RandomState;
158 ///
159 /// let hashindex: HashIndex<u64, u32, RandomState> =
160 /// HashIndex::with_capacity_and_hasher(1000, RandomState::new());
161 ///
162 /// let result = hashindex.capacity();
163 /// assert_eq!(result, 1024);
164 /// ```
165 #[inline]
166 pub fn with_capacity_and_hasher(capacity: usize, build_hasher: H) -> Self {
167 let (array, minimum_capacity) = if capacity == 0 {
168 (AtomicShared::null(), AtomicUsize::new(0))
169 } else {
170 let array = unsafe {
171 Shared::new_unchecked(BucketArray::<K, V, (), OPTIMISTIC>::new(
172 capacity,
173 AtomicShared::null(),
174 ))
175 };
176 let minimum_capacity = array.num_entries();
177 (
178 AtomicShared::from(array),
179 AtomicUsize::new(minimum_capacity),
180 )
181 };
182 Self {
183 array,
184 minimum_capacity,
185 build_hasher,
186 }
187 }
188}
189
190impl<K, V, H> HashIndex<K, V, H>
191where
192 K: 'static + Clone + Eq + Hash,
193 V: 'static + Clone,
194 H: BuildHasher,
195{
196 /// Temporarily increases the minimum capacity of the [`HashIndex`].
197 ///
198 /// A [`Reserve`] is returned if the [`HashIndex`] could increase the minimum capacity while
199 /// the increased capacity is not exclusively owned by the returned [`Reserve`], allowing
200 /// others to benefit from it. The memory for the additional space may not be immediately
201 /// allocated if the [`HashIndex`] is empty or currently being resized, however once the memory
202 /// is reserved eventually, the capacity will not shrink below the additional capacity until
203 /// the returned [`Reserve`] is dropped.
204 ///
205 /// # Errors
206 ///
207 /// Returns `None` if a too large number is given.
208 ///
209 /// # Examples
210 ///
211 /// ```
212 /// use scc2::HashIndex;
213 ///
214 /// let hashindex: HashIndex<usize, usize> = HashIndex::with_capacity(1000);
215 /// assert_eq!(hashindex.capacity(), 1024);
216 ///
217 /// let reserved = hashindex.reserve(10000);
218 /// assert!(reserved.is_some());
219 /// assert_eq!(hashindex.capacity(), 16384);
220 ///
221 /// assert!(hashindex.reserve(usize::MAX).is_none());
222 /// assert_eq!(hashindex.capacity(), 16384);
223 ///
224 /// for i in 0..16 {
225 /// assert!(hashindex.insert(i, i).is_ok());
226 /// }
227 /// drop(reserved);
228 ///
229 /// assert_eq!(hashindex.capacity(), 1024);
230 /// ```
231 #[inline]
232 pub fn reserve(&self, additional_capacity: usize) -> Option<Reserve<K, V, H>> {
233 let additional = self.reserve_capacity(additional_capacity);
234 if additional == 0 {
235 None
236 } else {
237 Some(Reserve {
238 hashindex: self,
239 additional,
240 })
241 }
242 }
243
244 /// Gets the entry associated with the given key in the map for in-place manipulation.
245 ///
246 /// # Examples
247 ///
248 /// ```
249 /// use scc2::HashIndex;
250 ///
251 /// let hashindex: HashIndex<char, u32> = HashIndex::default();
252 ///
253 /// for ch in "a short treatise on fungi".chars() {
254 /// unsafe {
255 /// hashindex.entry(ch).and_modify(|counter| *counter += 1).or_insert(1);
256 /// }
257 /// }
258 ///
259 /// assert_eq!(hashindex.peek_with(&'s', |_, v| *v), Some(2));
260 /// assert_eq!(hashindex.peek_with(&'t', |_, v| *v), Some(3));
261 /// assert!(hashindex.peek_with(&'y', |_, v| *v).is_none());
262 /// ```
263 #[inline]
264 pub fn entry(&self, key: K) -> Entry<K, V, H> {
265 let guard = Guard::new();
266 let hash = self.hash(&key);
267 let locked_entry = unsafe {
268 self.reserve_entry(&key, hash, &mut (), self.prolonged_guard_ref(&guard))
269 .ok()
270 .unwrap_unchecked()
271 };
272 if locked_entry.entry_ptr.is_valid() {
273 Entry::Occupied(OccupiedEntry {
274 hashindex: self,
275 locked_entry,
276 })
277 } else {
278 Entry::Vacant(VacantEntry {
279 hashindex: self,
280 key,
281 hash,
282 locked_entry,
283 })
284 }
285 }
286
287 /// Gets the entry associated with the given key in the map for in-place manipulation.
288 ///
289 /// It is an asynchronous method returning an `impl Future` for the caller to await.
290 ///
291 /// # Examples
292 ///
293 /// ```
294 /// use scc2::HashIndex;
295 ///
296 /// let hashindex: HashIndex<char, u32> = HashIndex::default();
297 ///
298 /// let future_entry = hashindex.entry_async('b');
299 /// ```
300 #[inline]
301 pub async fn entry_async(&self, key: K) -> Entry<K, V, H> {
302 let hash = self.hash(&key);
303 loop {
304 let mut async_wait = AsyncWait::default();
305 let mut async_wait_pinned = Pin::new(&mut async_wait);
306 {
307 let guard = Guard::new();
308 if let Ok(locked_entry) = self.reserve_entry(
309 &key,
310 hash,
311 &mut async_wait_pinned,
312 self.prolonged_guard_ref(&guard),
313 ) {
314 if locked_entry.entry_ptr.is_valid() {
315 return Entry::Occupied(OccupiedEntry {
316 hashindex: self,
317 locked_entry,
318 });
319 }
320 return Entry::Vacant(VacantEntry {
321 hashindex: self,
322 key,
323 hash,
324 locked_entry,
325 });
326 }
327 }
328 async_wait_pinned.await;
329 }
330 }
331
332 /// Gets the first occupied entry for in-place manipulation.
333 ///
334 /// The returned [`OccupiedEntry`] in combination with [`OccupiedEntry::next`] or
335 /// [`OccupiedEntry::next_async`] can act as a mutable iterator over entries.
336 ///
337 /// # Examples
338 ///
339 /// ```
340 /// use scc2::HashIndex;
341 ///
342 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
343 ///
344 /// assert!(hashindex.insert(1, 0).is_ok());
345 ///
346 /// let mut first_entry = hashindex.first_entry().unwrap();
347 /// unsafe {
348 /// *first_entry.get_mut() = 2;
349 /// }
350 ///
351 /// assert!(first_entry.next().is_none());
352 /// assert_eq!(hashindex.peek_with(&1, |_, v| *v), Some(2));
353 /// ```
354 #[inline]
355 pub fn first_entry(&self) -> Option<OccupiedEntry<K, V, H>> {
356 let guard = Guard::new();
357 let prolonged_guard = self.prolonged_guard_ref(&guard);
358 if let Some(locked_entry) = self.lock_first_entry(prolonged_guard) {
359 return Some(OccupiedEntry {
360 hashindex: self,
361 locked_entry,
362 });
363 }
364 None
365 }
366
367 /// Gets the first occupied entry for in-place manipulation.
368 ///
369 /// The returned [`OccupiedEntry`] in combination with [`OccupiedEntry::next`] or
370 /// [`OccupiedEntry::next_async`] can act as a mutable iterator over entries.
371 ///
372 /// It is an asynchronous method returning an `impl Future` for the caller to await.
373 ///
374 /// # Examples
375 ///
376 /// ```
377 /// use scc2::HashIndex;
378 ///
379 /// let hashindex: HashIndex<char, u32> = HashIndex::default();
380 ///
381 /// let future_entry = hashindex.first_entry_async();
382 /// ```
383 #[inline]
384 pub async fn first_entry_async(&self) -> Option<OccupiedEntry<K, V, H>> {
385 if let Some(locked_entry) = LockedEntry::first_entry_async(self).await {
386 return Some(OccupiedEntry {
387 hashindex: self,
388 locked_entry,
389 });
390 }
391 None
392 }
393
394 /// Finds any entry satisfying the supplied predicate for in-place manipulation.
395 ///
396 /// The returned [`OccupiedEntry`] in combination with [`OccupiedEntry::next`] or
397 /// [`OccupiedEntry::next_async`] can act as a mutable iterator over entries.
398 ///
399 /// # Examples
400 ///
401 /// ```
402 /// use scc2::HashIndex;
403 ///
404 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
405 ///
406 /// assert!(hashindex.insert(1, 0).is_ok());
407 /// assert!(hashindex.insert(2, 3).is_ok());
408 ///
409 /// let mut entry = hashindex.any_entry(|k, _| *k == 2).unwrap();
410 /// assert_eq!(*entry.get(), 3);
411 /// ```
412 #[inline]
413 pub fn any_entry<P: FnMut(&K, &V) -> bool>(&self, pred: P) -> Option<OccupiedEntry<K, V, H>> {
414 let guard = Guard::new();
415 let prolonged_guard = self.prolonged_guard_ref(&guard);
416 let locked_entry = self.find_entry(pred, prolonged_guard)?;
417 Some(OccupiedEntry {
418 hashindex: self,
419 locked_entry,
420 })
421 }
422
423 /// Finds any entry satisfying the supplied predicate for in-place manipulation.
424 ///
425 /// The returned [`OccupiedEntry`] in combination with [`OccupiedEntry::next`] or
426 /// [`OccupiedEntry::next_async`] can act as a mutable iterator over entries.
427 ///
428 /// It is an asynchronous method returning an `impl Future` for the caller to await.
429 ///
430 /// # Examples
431 ///
432 /// ```
433 /// use scc2::HashIndex;
434 ///
435 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
436 ///
437 /// let future_entry = hashindex.any_entry_async(|k, _| *k == 2);
438 /// ```
439 #[inline]
440 pub async fn any_entry_async<P: FnMut(&K, &V) -> bool>(
441 &self,
442 mut pred: P,
443 ) -> Option<OccupiedEntry<K, V, H>> {
444 if let Some(locked_entry) = LockedEntry::first_entry_async(self).await {
445 let mut entry = OccupiedEntry {
446 hashindex: self,
447 locked_entry,
448 };
449 loop {
450 if pred(entry.key(), entry.get()) {
451 return Some(entry);
452 }
453 entry = entry.next()?;
454 }
455 }
456 None
457 }
458
459 /// Inserts a key-value pair into the [`HashIndex`].
460 ///
461 /// # Errors
462 ///
463 /// Returns an error along with the supplied key-value pair if the key exists.
464 ///
465 /// # Examples
466 ///
467 /// ```
468 /// use scc2::HashIndex;
469 ///
470 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
471 ///
472 /// assert!(hashindex.insert(1, 0).is_ok());
473 /// assert_eq!(hashindex.insert(1, 1).unwrap_err(), (1, 1));
474 /// ```
475 #[inline]
476 pub fn insert(&self, key: K, val: V) -> Result<(), (K, V)> {
477 let guard = Guard::new();
478 let hash = self.hash(&key);
479 if let Ok(Some((k, v))) = self.insert_entry(key, val, hash, &mut (), &guard) {
480 Err((k, v))
481 } else {
482 Ok(())
483 }
484 }
485
486 /// Inserts a key-value pair into the [`HashIndex`].
487 ///
488 /// It is an asynchronous method returning an `impl Future` for the caller to await.
489 ///
490 /// # Errors
491 ///
492 /// Returns an error along with the supplied key-value pair if the key exists.
493 ///
494 /// # Examples
495 ///
496 /// ```
497 /// use scc2::HashIndex;
498 ///
499 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
500 /// let future_insert = hashindex.insert_async(11, 17);
501 /// ```
502 #[inline]
503 pub async fn insert_async(&self, mut key: K, mut val: V) -> Result<(), (K, V)> {
504 let hash = self.hash(&key);
505 loop {
506 let mut async_wait = AsyncWait::default();
507 let mut async_wait_pinned = Pin::new(&mut async_wait);
508 match self.insert_entry(key, val, hash, &mut async_wait_pinned, &Guard::new()) {
509 Ok(Some(returned)) => return Err(returned),
510 Ok(None) => return Ok(()),
511 Err(returned) => {
512 key = returned.0;
513 val = returned.1;
514 }
515 }
516 async_wait_pinned.await;
517 }
518 }
519
520 /// Removes a key-value pair if the key exists.
521 ///
522 /// Returns `false` if the key does not exist.
523 ///
524 /// Returns `true` if the key existed and the condition was met after marking the entry
525 /// unreachable; the memory will be reclaimed later.
526 ///
527 /// # Examples
528 ///
529 /// ```
530 /// use scc2::HashIndex;
531 ///
532 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
533 ///
534 /// assert!(!hashindex.remove(&1));
535 /// assert!(hashindex.insert(1, 0).is_ok());
536 /// assert!(hashindex.remove(&1));
537 /// ```
538 #[inline]
539 pub fn remove<Q>(&self, key: &Q) -> bool
540 where
541 Q: Equivalent<K> + Hash + ?Sized,
542 {
543 self.remove_if(key, |_| true)
544 }
545
546 /// Removes a key-value pair if the key exists.
547 ///
548 /// Returns `false` if the key does not exist. It is an asynchronous method returning an
549 /// `impl Future` for the caller to await.
550 ///
551 /// Returns `true` if the key existed and the condition was met after marking the entry
552 /// unreachable; the memory will be reclaimed later.
553 ///
554 /// # Examples
555 ///
556 /// ```
557 /// use scc2::HashIndex;
558 ///
559 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
560 /// let future_insert = hashindex.insert_async(11, 17);
561 /// let future_remove = hashindex.remove_async(&11);
562 /// ```
563 #[inline]
564 pub async fn remove_async<Q>(&self, key: &Q) -> bool
565 where
566 Q: Equivalent<K> + Hash + ?Sized,
567 {
568 self.remove_if_async(key, |_| true).await
569 }
570
571 /// Removes a key-value pair if the key exists and the given condition is met.
572 ///
573 /// Returns `false` if the key does not exist or the condition was not met.
574 ///
575 /// Returns `true` if the key existed and the condition was met after marking the entry
576 /// unreachable; the memory will be reclaimed later.
577 ///
578 /// # Examples
579 ///
580 /// ```
581 /// use scc2::HashIndex;
582 ///
583 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
584 ///
585 /// assert!(hashindex.insert(1, 0).is_ok());
586 /// assert!(!hashindex.remove_if(&1, |v| *v == 1));
587 /// assert!(hashindex.remove_if(&1, |v| *v == 0));
588 /// ```
589 #[inline]
590 pub fn remove_if<Q, F: FnOnce(&V) -> bool>(&self, key: &Q, condition: F) -> bool
591 where
592 Q: Equivalent<K> + Hash + ?Sized,
593 {
594 self.remove_entry(
595 key,
596 self.hash(key),
597 |v: &mut V| condition(v),
598 |r| r.is_some(),
599 &mut (),
600 &Guard::new(),
601 )
602 .ok()
603 .map_or(false, |r| r)
604 }
605
606 /// Removes a key-value pair if the key exists and the given condition is met.
607 ///
608 /// Returns `false` if the key does not exist or the condition was not met. It is an
609 /// asynchronous method returning an `impl Future` for the caller to await.
610 ///
611 /// Returns `true` if the key existed and the condition was met after marking the entry
612 /// unreachable; the memory will be reclaimed later.
613 ///
614 /// # Examples
615 ///
616 /// ```
617 /// use scc2::HashIndex;
618 ///
619 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
620 /// let future_insert = hashindex.insert_async(11, 17);
621 /// let future_remove = hashindex.remove_if_async(&11, |_| true);
622 /// ```
623 #[inline]
624 pub async fn remove_if_async<Q, F: FnOnce(&V) -> bool>(&self, key: &Q, condition: F) -> bool
625 where
626 Q: Equivalent<K> + Hash + ?Sized,
627 {
628 let hash = self.hash(key);
629 let mut condition = |v: &mut V| condition(v);
630 loop {
631 let mut async_wait = AsyncWait::default();
632 let mut async_wait_pinned = Pin::new(&mut async_wait);
633 match self.remove_entry(
634 key,
635 hash,
636 condition,
637 |r| r.is_some(),
638 &mut async_wait_pinned,
639 &Guard::new(),
640 ) {
641 Ok(r) => return r,
642 Err(c) => condition = c,
643 }
644 async_wait_pinned.await;
645 }
646 }
647
648 /// Gets an [`OccupiedEntry`] corresponding to the key for in-place modification.
649 ///
650 /// [`OccupiedEntry`] exclusively owns the entry, preventing others from gaining access to it:
651 /// use [`peek`](Self::peek) if read-only access is sufficient.
652 ///
653 /// Returns `None` if the key does not exist.
654 ///
655 /// # Examples
656 ///
657 /// ```
658 /// use scc2::HashIndex;
659 ///
660 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
661 ///
662 /// assert!(hashindex.get(&1).is_none());
663 /// assert!(hashindex.insert(1, 10).is_ok());
664 /// assert_eq!(*hashindex.get(&1).unwrap().get(), 10);
665 /// assert_eq!(*hashindex.get(&1).unwrap(), 10);
666 /// ```
667 #[inline]
668 pub fn get<Q>(&self, key: &Q) -> Option<OccupiedEntry<K, V, H>>
669 where
670 Q: Equivalent<K> + Hash + ?Sized,
671 {
672 let guard = Guard::new();
673 let locked_entry = self
674 .get_entry(
675 key,
676 self.hash(key),
677 &mut (),
678 self.prolonged_guard_ref(&guard),
679 )
680 .ok()
681 .flatten()?;
682 Some(OccupiedEntry {
683 hashindex: self,
684 locked_entry,
685 })
686 }
687
688 /// Gets an [`OccupiedEntry`] corresponding to the key for in-place modification.
689 ///
690 /// [`OccupiedEntry`] exclusively owns the entry, preventing others from gaining access to it:
691 /// use [`peek`](Self::peek) if read-only access is sufficient.
692 ///
693 /// Returns `None` if the key does not exist. It is an asynchronous method returning an
694 /// `impl Future` for the caller to await.
695 ///
696 /// # Examples
697 ///
698 /// ```
699 /// use scc2::HashIndex;
700 ///
701 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
702 /// let future_insert = hashindex.insert_async(11, 17);
703 /// let future_get = hashindex.get_async(&11);
704 /// ```
705 #[inline]
706 pub async fn get_async<Q>(&self, key: &Q) -> Option<OccupiedEntry<K, V, H>>
707 where
708 Q: Equivalent<K> + Hash + ?Sized,
709 {
710 let hash = self.hash(key);
711 loop {
712 let mut async_wait = AsyncWait::default();
713 let mut async_wait_pinned = Pin::new(&mut async_wait);
714 if let Ok(result) = self.get_entry(
715 key,
716 hash,
717 &mut async_wait_pinned,
718 self.prolonged_guard_ref(&Guard::new()),
719 ) {
720 if let Some(locked_entry) = result {
721 return Some(OccupiedEntry {
722 hashindex: self,
723 locked_entry,
724 });
725 }
726 return None;
727 }
728 async_wait_pinned.await;
729 }
730 }
731
732 /// Returns a guarded reference to the value for the specified key without acquiring locks.
733 ///
734 /// Returns `None` if the key does not exist. The returned reference can survive as long as the
735 /// associated [`Guard`] is alive.
736 ///
737 /// # Examples
738 ///
739 /// ```
740 /// use scc2::ebr::Guard;
741 /// use scc2::HashIndex;
742 ///
743 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
744 ///
745 /// assert!(hashindex.insert(1, 10).is_ok());
746 ///
747 /// let guard = Guard::new();
748 /// let value_ref = hashindex.peek(&1, &guard).unwrap();
749 /// assert_eq!(*value_ref, 10);
750 /// ```
751 #[inline]
752 pub fn peek<'g, Q>(&self, key: &Q, guard: &'g Guard) -> Option<&'g V>
753 where
754 Q: Equivalent<K> + Hash + ?Sized,
755 {
756 self.peek_entry(key, self.hash(key), guard).map(|(_, v)| v)
757 }
758
759 /// Peeks a key-value pair without acquiring locks.
760 ///
761 /// Returns `None` if the key does not exist.
762 ///
763 /// # Examples
764 ///
765 /// ```
766 /// use scc2::HashIndex;
767 ///
768 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
769 ///
770 /// assert!(hashindex.peek_with(&1, |_, v| *v).is_none());
771 /// assert!(hashindex.insert(1, 10).is_ok());
772 /// assert_eq!(hashindex.peek_with(&1, |_, v| *v).unwrap(), 10);
773 /// ```
774 #[inline]
775 pub fn peek_with<Q, R, F: FnOnce(&K, &V) -> R>(&self, key: &Q, reader: F) -> Option<R>
776 where
777 Q: Equivalent<K> + Hash + ?Sized,
778 {
779 let guard = Guard::new();
780 self.peek_entry(key, self.hash(key), &guard)
781 .map(|(k, v)| reader(k, v))
782 }
783
784 /// Returns `true` if the [`HashIndex`] contains a value for the specified key.
785 ///
786 /// # Examples
787 ///
788 /// ```
789 /// use scc2::HashIndex;
790 ///
791 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
792 ///
793 /// assert!(!hashindex.contains(&1));
794 /// assert!(hashindex.insert(1, 0).is_ok());
795 /// assert!(hashindex.contains(&1));
796 /// ```
797 #[inline]
798 pub fn contains<Q>(&self, key: &Q) -> bool
799 where
800 Q: Equivalent<K> + Hash + ?Sized,
801 {
802 self.peek_with(key, |_, _| ()).is_some()
803 }
804
805 /// Retains the entries specified by the predicate.
806 ///
807 /// Entries that have existed since the invocation of the method are guaranteed to be visited
808 /// if they are not removed, however the same entry can be visited more than once if the
809 /// [`HashIndex`] gets resized by another thread.
810 ///
811 /// # Examples
812 ///
813 /// ```
814 /// use scc2::HashIndex;
815 ///
816 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
817 ///
818 /// assert!(hashindex.insert(1, 0).is_ok());
819 /// assert!(hashindex.insert(2, 1).is_ok());
820 /// assert!(hashindex.insert(3, 2).is_ok());
821 ///
822 /// hashindex.retain(|k, v| *k == 1 && *v == 0);
823 ///
824 /// assert!(hashindex.contains(&1));
825 /// assert!(!hashindex.contains(&2));
826 /// assert!(!hashindex.contains(&3));
827 /// ```
828 #[inline]
829 pub fn retain<F: FnMut(&K, &V) -> bool>(&self, mut pred: F) {
830 self.retain_entries(|k, v| pred(k, v));
831 }
832
833 /// Retains the entries specified by the predicate.
834 ///
835 /// Entries that have existed since the invocation of the method are guaranteed to be visited
836 /// if they are not removed, however the same entry can be visited more than once if the
837 /// [`HashIndex`] gets resized by another thread.
838 ///
839 /// It is an asynchronous method returning an `impl Future` for the caller to await.
840 ///
841 /// # Examples
842 ///
843 /// ```
844 /// use scc2::HashIndex;
845 ///
846 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
847 ///
848 /// let future_insert = hashindex.insert_async(1, 0);
849 /// let future_retain = hashindex.retain_async(|k, v| *k == 1);
850 /// ```
851 #[inline]
852 pub async fn retain_async<F: FnMut(&K, &V) -> bool>(&self, mut pred: F) {
853 let mut removed = false;
854 let mut current_array_holder = self.array.get_shared(Acquire, &Guard::new());
855 while let Some(current_array) = current_array_holder.take() {
856 self.cleanse_old_array_async(¤t_array).await;
857 for index in 0..current_array.num_buckets() {
858 loop {
859 let mut async_wait = AsyncWait::default();
860 let mut async_wait_pinned = Pin::new(&mut async_wait);
861 {
862 let guard = Guard::new();
863 let bucket = current_array.bucket_mut(index);
864 if let Ok(locker) =
865 Locker::try_lock_or_wait(bucket, &mut async_wait_pinned, &guard)
866 {
867 if let Some(mut locker) = locker {
868 let data_block_mut = current_array.data_block_mut(index);
869 let mut entry_ptr = EntryPtr::new(&guard);
870 while entry_ptr.move_to_next(&locker, &guard) {
871 let (k, v) = entry_ptr.get(data_block_mut);
872 if !pred(k, v) {
873 locker.mark_removed(&mut entry_ptr, &guard);
874 removed = true;
875 }
876 }
877 }
878 break;
879 };
880 }
881 async_wait_pinned.await;
882 }
883 }
884
885 if let Some(new_current_array) = self.array.get_shared(Acquire, &Guard::new()) {
886 if new_current_array.as_ptr() == current_array.as_ptr() {
887 break;
888 }
889 current_array_holder.replace(new_current_array);
890 continue;
891 }
892 break;
893 }
894
895 if removed {
896 self.try_resize(0, &Guard::new());
897 }
898 }
899
900 /// Clears the [`HashIndex`] by removing all key-value pairs.
901 ///
902 /// # Examples
903 ///
904 /// ```
905 /// use scc2::HashIndex;
906 ///
907 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
908 ///
909 /// assert!(hashindex.insert(1, 0).is_ok());
910 /// hashindex.clear();
911 ///
912 /// assert!(!hashindex.contains(&1));
913 /// ```
914 pub fn clear(&self) {
915 self.retain(|_, _| false);
916 }
917
918 /// Clears the [`HashIndex`] by removing all key-value pairs.
919 ///
920 /// It is an asynchronous method returning an `impl Future` for the caller to await.
921 ///
922 /// # Examples
923 ///
924 /// ```
925 /// use scc2::HashIndex;
926 ///
927 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
928 ///
929 /// let future_insert = hashindex.insert_async(1, 0);
930 /// let future_retain = hashindex.clear_async();
931 /// ```
932 pub async fn clear_async(&self) {
933 self.retain_async(|_, _| false).await;
934 }
935
936 /// Returns the number of entries in the [`HashIndex`].
937 ///
938 /// It reads the entire metadata area of the bucket array to calculate the number of valid
939 /// entries, making its time complexity `O(N)`. Furthermore, it may overcount entries if an old
940 /// bucket array has yet to be dropped.
941 ///
942 /// # Examples
943 ///
944 /// ```
945 /// use scc2::HashIndex;
946 ///
947 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
948 ///
949 /// assert!(hashindex.insert(1, 0).is_ok());
950 /// assert_eq!(hashindex.len(), 1);
951 /// ```
952 #[inline]
953 pub fn len(&self) -> usize {
954 self.num_entries(&Guard::new())
955 }
956
957 /// Returns `true` if the [`HashIndex`] is empty.
958 ///
959 /// # Examples
960 ///
961 /// ```
962 /// use scc2::HashIndex;
963 ///
964 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
965 ///
966 /// assert!(hashindex.is_empty());
967 /// assert!(hashindex.insert(1, 0).is_ok());
968 /// assert!(!hashindex.is_empty());
969 /// ```
970 #[inline]
971 pub fn is_empty(&self) -> bool {
972 !self.has_entry(&Guard::new())
973 }
974
975 /// Returns the capacity of the [`HashIndex`].
976 ///
977 /// # Examples
978 ///
979 /// ```
980 /// use scc2::HashIndex;
981 ///
982 /// let hashindex_default: HashIndex<u64, u32> = HashIndex::default();
983 /// assert_eq!(hashindex_default.capacity(), 0);
984 ///
985 /// assert!(hashindex_default.insert(1, 0).is_ok());
986 /// assert_eq!(hashindex_default.capacity(), 64);
987 ///
988 /// let hashindex: HashIndex<u64, u32> = HashIndex::with_capacity(1000);
989 /// assert_eq!(hashindex.capacity(), 1024);
990 /// ```
991 #[inline]
992 pub fn capacity(&self) -> usize {
993 self.num_slots(&Guard::new())
994 }
995
996 /// Returns the current capacity range of the [`HashIndex`].
997 ///
998 /// # Examples
999 ///
1000 /// ```
1001 /// use scc2::HashIndex;
1002 ///
1003 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1004 ///
1005 /// assert_eq!(hashindex.capacity_range(), 0..=(1_usize << (usize::BITS - 1)));
1006 ///
1007 /// let reserved = hashindex.reserve(1000);
1008 /// assert_eq!(hashindex.capacity_range(), 1000..=(1_usize << (usize::BITS - 1)));
1009 /// ```
1010 #[inline]
1011 pub fn capacity_range(&self) -> RangeInclusive<usize> {
1012 self.minimum_capacity.load(Relaxed)..=self.maximum_capacity()
1013 }
1014
1015 /// Returns the index of the bucket that may contain the key.
1016 ///
1017 /// The method returns the index of the bucket associated with the key. The number of buckets
1018 /// can be calculated by dividing `32` into the capacity.
1019 ///
1020 /// # Examples
1021 ///
1022 /// ```
1023 /// use scc2::HashIndex;
1024 ///
1025 /// let hashindex: HashIndex<u64, u32> = HashIndex::with_capacity(1024);
1026 ///
1027 /// let bucket_index = hashindex.bucket_index(&11);
1028 /// assert!(bucket_index < hashindex.capacity() / 32);
1029 /// ```
1030 #[inline]
1031 pub fn bucket_index<Q>(&self, key: &Q) -> usize
1032 where
1033 Q: Equivalent<K> + Hash + ?Sized,
1034 {
1035 self.calculate_bucket_index(key)
1036 }
1037
1038 /// Returns an [`Iter`].
1039 ///
1040 /// It is guaranteed to go through all the key-value pairs pertaining in the [`HashIndex`]
1041 /// at the moment, however the same key-value pair can be visited more than once if the
1042 /// [`HashIndex`] is being resized.
1043 ///
1044 /// It requires the user to supply a reference to a [`Guard`].
1045 ///
1046 /// # Examples
1047 ///
1048 /// ```
1049 /// use scc2::ebr::Guard;
1050 /// use scc2::HashIndex;
1051 ///
1052 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1053 ///
1054 /// assert!(hashindex.insert(1, 0).is_ok());
1055 ///
1056 /// let guard = Guard::new();
1057 ///
1058 /// let mut iter = hashindex.iter(&guard);
1059 /// let entry_ref = iter.next().unwrap();
1060 /// assert_eq!(iter.next(), None);
1061 ///
1062 /// for iter in hashindex.iter(&guard) {
1063 /// assert_eq!(iter, (&1, &0));
1064 /// }
1065 ///
1066 /// drop(hashindex);
1067 ///
1068 /// assert_eq!(entry_ref, (&1, &0));
1069 /// ```
1070 #[inline]
1071 pub fn iter<'h, 'g>(&'h self, guard: &'g Guard) -> Iter<'h, 'g, K, V, H> {
1072 Iter {
1073 hashindex: self,
1074 current_array: None,
1075 current_index: 0,
1076 current_bucket: None,
1077 current_entry_ptr: EntryPtr::new(guard),
1078 guard,
1079 }
1080 }
1081
1082 /// Clears the old array asynchronously.
1083 async fn cleanse_old_array_async(&self, current_array: &BucketArray<K, V, (), OPTIMISTIC>) {
1084 while current_array.has_old_array() {
1085 let mut async_wait = AsyncWait::default();
1086 let mut async_wait_pinned = Pin::new(&mut async_wait);
1087 if self.incremental_rehash::<K, _, false>(
1088 current_array,
1089 &mut async_wait_pinned,
1090 &Guard::new(),
1091 ) == Ok(true)
1092 {
1093 break;
1094 }
1095 async_wait_pinned.await;
1096 }
1097 }
1098}
1099
1100impl<K, V, H> Clone for HashIndex<K, V, H>
1101where
1102 K: 'static + Clone + Eq + Hash,
1103 V: 'static + Clone,
1104 H: BuildHasher + Clone,
1105{
1106 #[inline]
1107 fn clone(&self) -> Self {
1108 let self_clone = Self::with_capacity_and_hasher(self.capacity(), self.hasher().clone());
1109 for (k, v) in self.iter(&Guard::new()) {
1110 let _reuslt = self_clone.insert(k.clone(), v.clone());
1111 }
1112 self_clone
1113 }
1114}
1115
1116impl<K, V, H> Debug for HashIndex<K, V, H>
1117where
1118 K: 'static + Clone + Debug + Eq + Hash,
1119 V: 'static + Clone + Debug,
1120 H: BuildHasher,
1121{
1122 #[inline]
1123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1124 let guard = Guard::new();
1125 f.debug_map().entries(self.iter(&guard)).finish()
1126 }
1127}
1128
1129impl<K, V> HashIndex<K, V, RandomState>
1130where
1131 K: 'static + Clone + Eq + Hash,
1132 V: 'static + Clone,
1133{
1134 /// Creates an empty default [`HashIndex`].
1135 ///
1136 /// # Examples
1137 ///
1138 /// ```
1139 /// use scc2::HashIndex;
1140 ///
1141 /// let hashindex: HashIndex<u64, u32> = HashIndex::new();
1142 ///
1143 /// let result = hashindex.capacity();
1144 /// assert_eq!(result, 0);
1145 /// ```
1146 #[inline]
1147 #[must_use]
1148 pub fn new() -> Self {
1149 Self::default()
1150 }
1151
1152 /// Creates an empty [`HashIndex`] with the specified capacity.
1153 ///
1154 /// The actual capacity is equal to or greater than the specified capacity.
1155 ///
1156 /// # Examples
1157 ///
1158 /// ```
1159 /// use scc2::HashIndex;
1160 ///
1161 /// let hashindex: HashIndex<u64, u32> = HashIndex::with_capacity(1000);
1162 ///
1163 /// let result = hashindex.capacity();
1164 /// assert_eq!(result, 1024);
1165 /// ```
1166 #[inline]
1167 #[must_use]
1168 pub fn with_capacity(capacity: usize) -> Self {
1169 Self::with_capacity_and_hasher(capacity, RandomState::new())
1170 }
1171}
1172
1173impl<K, V, H> Default for HashIndex<K, V, H>
1174where
1175 K: 'static,
1176 V: 'static,
1177 H: BuildHasher + Default,
1178{
1179 /// Creates an empty default [`HashIndex`].
1180 ///
1181 /// The default capacity is `64`.
1182 ///
1183 /// # Examples
1184 ///
1185 /// ```
1186 /// use scc2::HashIndex;
1187 ///
1188 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1189 ///
1190 /// let result = hashindex.capacity();
1191 /// assert_eq!(result, 0);
1192 /// ```
1193 #[inline]
1194 fn default() -> Self {
1195 Self::with_hasher(H::default())
1196 }
1197}
1198
1199impl<K, V, H> FromIterator<(K, V)> for HashIndex<K, V, H>
1200where
1201 K: 'static + Clone + Eq + Hash,
1202 V: 'static + Clone,
1203 H: BuildHasher + Default,
1204{
1205 #[inline]
1206 fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
1207 let into_iter = iter.into_iter();
1208 let hashindex = Self::with_capacity_and_hasher(
1209 Self::capacity_from_size_hint(into_iter.size_hint()),
1210 H::default(),
1211 );
1212 into_iter.for_each(|e| {
1213 let _result = hashindex.insert(e.0, e.1);
1214 });
1215 hashindex
1216 }
1217}
1218
1219impl<K, V, H> HashTable<K, V, H, (), OPTIMISTIC> for HashIndex<K, V, H>
1220where
1221 K: 'static + Clone + Eq + Hash,
1222 V: 'static + Clone,
1223 H: BuildHasher,
1224{
1225 #[inline]
1226 fn hasher(&self) -> &H {
1227 &self.build_hasher
1228 }
1229 #[inline]
1230 fn try_clone(entry: &(K, V)) -> Option<(K, V)> {
1231 Some((entry.0.clone(), entry.1.clone()))
1232 }
1233 #[inline]
1234 fn bucket_array(&self) -> &AtomicShared<BucketArray<K, V, (), OPTIMISTIC>> {
1235 &self.array
1236 }
1237 #[inline]
1238 fn minimum_capacity(&self) -> &AtomicUsize {
1239 &self.minimum_capacity
1240 }
1241 #[inline]
1242 fn maximum_capacity(&self) -> usize {
1243 1_usize << (usize::BITS - 1)
1244 }
1245}
1246
1247impl<K, V, H> PartialEq for HashIndex<K, V, H>
1248where
1249 K: 'static + Clone + Eq + Hash,
1250 V: 'static + Clone + PartialEq,
1251 H: BuildHasher,
1252{
1253 #[inline]
1254 fn eq(&self, other: &Self) -> bool {
1255 let guard = Guard::new();
1256 if !self
1257 .iter(&guard)
1258 .any(|(k, v)| other.peek_with(k, |_, ov| v == ov) != Some(true))
1259 {
1260 return !other
1261 .iter(&guard)
1262 .any(|(k, v)| self.peek_with(k, |_, sv| v == sv) != Some(true));
1263 }
1264 false
1265 }
1266}
1267
1268impl<'h, K, V, H> Entry<'h, K, V, H>
1269where
1270 K: 'static + Clone + Eq + Hash,
1271 V: 'static + Clone,
1272 H: BuildHasher,
1273{
1274 /// Ensures a value is in the entry by inserting the supplied instance if empty.
1275 ///
1276 /// # Examples
1277 ///
1278 /// ```
1279 /// use scc2::HashIndex;
1280 ///
1281 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1282 ///
1283 /// hashindex.entry(3).or_insert(7);
1284 /// assert_eq!(hashindex.peek_with(&3, |_, v| *v), Some(7));
1285 /// ```
1286 #[inline]
1287 pub fn or_insert(self, val: V) -> OccupiedEntry<'h, K, V, H> {
1288 self.or_insert_with(|| val)
1289 }
1290
1291 /// Ensures a value is in the entry by inserting the result of the supplied closure if empty.
1292 ///
1293 /// # Examples
1294 ///
1295 /// ```
1296 /// use scc2::HashIndex;
1297 ///
1298 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1299 ///
1300 /// hashindex.entry(19).or_insert_with(|| 5);
1301 /// assert_eq!(hashindex.peek_with(&19, |_, v| *v), Some(5));
1302 /// ```
1303 #[inline]
1304 pub fn or_insert_with<F: FnOnce() -> V>(self, constructor: F) -> OccupiedEntry<'h, K, V, H> {
1305 self.or_insert_with_key(|_| constructor())
1306 }
1307
1308 /// Ensures a value is in the entry by inserting the result of the supplied closure if empty.
1309 ///
1310 /// The reference to the moved key is provided, therefore cloning or copying the key is
1311 /// unnecessary.
1312 ///
1313 /// # Examples
1314 ///
1315 /// ```
1316 /// use scc2::HashIndex;
1317 ///
1318 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1319 ///
1320 /// hashindex.entry(11).or_insert_with_key(|k| if *k == 11 { 7 } else { 3 });
1321 /// assert_eq!(hashindex.peek_with(&11, |_, v| *v), Some(7));
1322 /// ```
1323 #[inline]
1324 pub fn or_insert_with_key<F: FnOnce(&K) -> V>(
1325 self,
1326 constructor: F,
1327 ) -> OccupiedEntry<'h, K, V, H> {
1328 match self {
1329 Self::Occupied(o) => o,
1330 Self::Vacant(v) => {
1331 let val = constructor(v.key());
1332 v.insert_entry(val)
1333 }
1334 }
1335 }
1336
1337 /// Returns a reference to the key of this entry.
1338 ///
1339 /// # Examples
1340 ///
1341 /// ```
1342 /// use scc2::HashIndex;
1343 ///
1344 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1345 /// assert_eq!(hashindex.entry(31).key(), &31);
1346 /// ```
1347 #[inline]
1348 pub fn key(&self) -> &K {
1349 match self {
1350 Self::Occupied(o) => o.key(),
1351 Self::Vacant(v) => v.key(),
1352 }
1353 }
1354
1355 /// Provides in-place mutable access to an occupied entry.
1356 ///
1357 /// # Safety
1358 ///
1359 /// The caller has to make sure that there are no readers of the entry, e.g., a reader keeping
1360 /// a reference to the entry via [`HashIndex::iter`], [`HashIndex::peek`], or
1361 /// [`HashIndex::peek_with`], unless an instance of `V` can be safely read when there is a
1362 /// single writer, e.g., `V = [u8; 32]`.
1363 ///
1364 /// # Examples
1365 ///
1366 /// ```
1367 /// use scc2::HashIndex;
1368 ///
1369 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1370 ///
1371 /// unsafe {
1372 /// hashindex.entry(37).and_modify(|v| { *v += 1 }).or_insert(47);
1373 /// }
1374 /// assert_eq!(hashindex.peek_with(&37, |_, v| *v), Some(47));
1375 ///
1376 /// unsafe {
1377 /// hashindex.entry(37).and_modify(|v| { *v += 1 }).or_insert(3);
1378 /// }
1379 /// assert_eq!(hashindex.peek_with(&37, |_, v| *v), Some(48));
1380 /// ```
1381 #[inline]
1382 #[must_use]
1383 pub unsafe fn and_modify<F>(self, f: F) -> Self
1384 where
1385 F: FnOnce(&mut V),
1386 {
1387 match self {
1388 Self::Occupied(mut o) => {
1389 f(o.get_mut());
1390 Self::Occupied(o)
1391 }
1392 Self::Vacant(_) => self,
1393 }
1394 }
1395}
1396
1397impl<'h, K, V, H> Entry<'h, K, V, H>
1398where
1399 K: 'static + Clone + Eq + Hash,
1400 V: 'static + Clone + Default,
1401 H: BuildHasher,
1402{
1403 /// Ensures a value is in the entry by inserting the default value if empty.
1404 ///
1405 /// # Examples
1406 ///
1407 /// ```
1408 /// use scc2::HashIndex;
1409 ///
1410 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1411 /// hashindex.entry(11).or_default();
1412 /// assert_eq!(hashindex.peek_with(&11, |_, v| *v), Some(0));
1413 /// ```
1414 #[inline]
1415 pub fn or_default(self) -> OccupiedEntry<'h, K, V, H> {
1416 match self {
1417 Self::Occupied(o) => o,
1418 Self::Vacant(v) => v.insert_entry(Default::default()),
1419 }
1420 }
1421}
1422
1423impl<K, V, H> Debug for Entry<'_, K, V, H>
1424where
1425 K: 'static + Clone + Debug + Eq + Hash,
1426 V: 'static + Clone + Debug,
1427 H: BuildHasher,
1428{
1429 #[inline]
1430 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1431 match self {
1432 Self::Vacant(v) => f.debug_tuple("Entry").field(v).finish(),
1433 Self::Occupied(o) => f.debug_tuple("Entry").field(o).finish(),
1434 }
1435 }
1436}
1437
1438impl<'h, K, V, H> OccupiedEntry<'h, K, V, H>
1439where
1440 K: 'static + Clone + Eq + Hash,
1441 V: 'static + Clone,
1442 H: BuildHasher,
1443{
1444 /// Gets a reference to the key in the entry.
1445 ///
1446 /// # Examples
1447 ///
1448 /// ```
1449 /// use scc2::HashIndex;
1450 ///
1451 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1452 ///
1453 /// assert_eq!(hashindex.entry(29).or_default().key(), &29);
1454 /// ```
1455 #[inline]
1456 #[must_use]
1457 pub fn key(&self) -> &K {
1458 &self
1459 .locked_entry
1460 .entry_ptr
1461 .get(self.locked_entry.data_block_mut)
1462 .0
1463 }
1464
1465 /// Marks that the entry is removed from the [`HashIndex`].
1466 ///
1467 /// # Examples
1468 ///
1469 /// ```
1470 /// use scc2::HashIndex;
1471 /// use scc2::hash_index::Entry;
1472 ///
1473 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1474 ///
1475 /// hashindex.entry(11).or_insert(17);
1476 ///
1477 /// if let Entry::Occupied(o) = hashindex.entry(11) {
1478 /// o.remove_entry();
1479 /// };
1480 /// assert_eq!(hashindex.peek_with(&11, |_, v| *v), None);
1481 /// ```
1482 #[inline]
1483 pub fn remove_entry(mut self) {
1484 let guard = Guard::new();
1485 self.locked_entry.locker.mark_removed(
1486 &mut self.locked_entry.entry_ptr,
1487 self.hashindex.prolonged_guard_ref(&guard),
1488 );
1489 if self.locked_entry.locker.num_entries() <= 1 || self.locked_entry.locker.need_rebuild() {
1490 let hashindex = self.hashindex;
1491 if let Some(current_array) = hashindex.bucket_array().load(Acquire, &guard).as_ref() {
1492 if !current_array.has_old_array() {
1493 let index = self.locked_entry.index;
1494 if current_array.within_sampling_range(index) {
1495 drop(self);
1496 hashindex.try_shrink_or_rebuild(current_array, index, &guard);
1497 }
1498 }
1499 }
1500 }
1501 }
1502
1503 /// Gets a reference to the value in the entry.
1504 ///
1505 /// # Examples
1506 ///
1507 /// ```
1508 /// use scc2::HashIndex;
1509 /// use scc2::hash_index::Entry;
1510 ///
1511 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1512 ///
1513 /// hashindex.entry(19).or_insert(11);
1514 ///
1515 /// if let Entry::Occupied(o) = hashindex.entry(19) {
1516 /// assert_eq!(o.get(), &11);
1517 /// };
1518 /// ```
1519 #[inline]
1520 #[must_use]
1521 pub fn get(&self) -> &V {
1522 &self
1523 .locked_entry
1524 .entry_ptr
1525 .get(self.locked_entry.data_block_mut)
1526 .1
1527 }
1528
1529 /// Gets a mutable reference to the value in the entry.
1530 ///
1531 /// # Safety
1532 ///
1533 /// The caller has to make sure that there are no readers of the entry, e.g., a reader keeping
1534 /// a reference to the entry via [`HashIndex::iter`], [`HashIndex::peek`], or
1535 /// [`HashIndex::peek_with`], unless an instance of `V` can be safely read when there is a
1536 /// single writer, e.g., `V = [u8; 32]`.
1537 ///
1538 /// # Examples
1539 ///
1540 /// ```
1541 /// use scc2::HashIndex;
1542 /// use scc2::hash_index::Entry;
1543 ///
1544 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1545 ///
1546 /// hashindex.entry(37).or_insert(11);
1547 ///
1548 /// if let Entry::Occupied(mut o) = hashindex.entry(37) {
1549 /// // Safety: `u32` can be safely read while being modified.
1550 /// unsafe { *o.get_mut() += 18; }
1551 /// assert_eq!(*o.get(), 29);
1552 /// }
1553 ///
1554 /// assert_eq!(hashindex.peek_with(&37, |_, v| *v), Some(29));
1555 /// ```
1556 #[inline]
1557 pub unsafe fn get_mut(&mut self) -> &mut V {
1558 &mut self
1559 .locked_entry
1560 .entry_ptr
1561 .get_mut(
1562 self.locked_entry.data_block_mut,
1563 &mut self.locked_entry.locker,
1564 )
1565 .1
1566 }
1567
1568 /// Updates the entry by inserting a new entry and marking the existing entry removed.
1569 ///
1570 /// # Examples
1571 ///
1572 /// ```
1573 /// use scc2::HashIndex;
1574 /// use scc2::hash_index::Entry;
1575 ///
1576 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1577 ///
1578 /// hashindex.entry(37).or_insert(11);
1579 ///
1580 /// if let Entry::Occupied(mut o) = hashindex.entry(37) {
1581 /// o.update(29);
1582 /// }
1583 ///
1584 /// assert_eq!(hashindex.peek_with(&37, |_, v| *v), Some(29));
1585 /// ```
1586 #[inline]
1587 pub fn update(mut self, val: V) {
1588 let key = self.key().clone();
1589 let partial_hash = self
1590 .locked_entry
1591 .entry_ptr
1592 .partial_hash(&self.locked_entry.locker);
1593 let guard = Guard::new();
1594 self.locked_entry.locker.insert_with(
1595 self.locked_entry.data_block_mut,
1596 partial_hash,
1597 || (key, val),
1598 self.hashindex.prolonged_guard_ref(&guard),
1599 );
1600 self.locked_entry.locker.mark_removed(
1601 &mut self.locked_entry.entry_ptr,
1602 self.hashindex.prolonged_guard_ref(&guard),
1603 );
1604 }
1605
1606 /// Gets the next closest occupied entry.
1607 ///
1608 /// [`HashIndex::first_entry`], [`HashIndex::first_entry_async`], and this method together
1609 /// enables the [`OccupiedEntry`] to effectively act as a mutable iterator over entries. The
1610 /// method never acquires more than one lock even when it searches other buckets for the next
1611 /// closest occupied entry.
1612 ///
1613 /// # Examples
1614 ///
1615 /// ```
1616 /// use scc2::HashIndex;
1617 /// use scc2::hash_index::Entry;
1618 ///
1619 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1620 ///
1621 /// assert!(hashindex.insert(1, 0).is_ok());
1622 /// assert!(hashindex.insert(2, 0).is_ok());
1623 ///
1624 /// let first_entry = hashindex.first_entry().unwrap();
1625 /// let first_key = *first_entry.key();
1626 /// let second_entry = first_entry.next().unwrap();
1627 /// let second_key = *second_entry.key();
1628 ///
1629 /// assert!(second_entry.next().is_none());
1630 /// assert_eq!(first_key + second_key, 3);
1631 /// ```
1632 #[inline]
1633 #[must_use]
1634 pub fn next(self) -> Option<Self> {
1635 let hashindex = self.hashindex;
1636 if let Some(locked_entry) = self.locked_entry.next(hashindex) {
1637 return Some(OccupiedEntry {
1638 hashindex,
1639 locked_entry,
1640 });
1641 }
1642 None
1643 }
1644
1645 /// Gets the next closest occupied entry.
1646 ///
1647 /// [`HashIndex::first_entry`], [`HashIndex::first_entry_async`], and this method together
1648 /// enables the [`OccupiedEntry`] to effectively act as a mutable iterator over entries. The
1649 /// method never acquires more than one lock even when it searches other buckets for the next
1650 /// closest occupied entry.
1651 ///
1652 /// It is an asynchronous method returning an `impl Future` for the caller to await.
1653 ///
1654 /// # Examples
1655 ///
1656 /// ```
1657 /// use scc2::HashIndex;
1658 /// use scc2::hash_index::Entry;
1659 ///
1660 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1661 ///
1662 /// assert!(hashindex.insert(1, 0).is_ok());
1663 /// assert!(hashindex.insert(2, 0).is_ok());
1664 ///
1665 /// let second_entry_future = hashindex.first_entry().unwrap().next_async();
1666 /// ```
1667 #[inline]
1668 pub async fn next_async(self) -> Option<OccupiedEntry<'h, K, V, H>> {
1669 let hashindex = self.hashindex;
1670 if let Some(locked_entry) = self.locked_entry.next_async(hashindex).await {
1671 return Some(OccupiedEntry {
1672 hashindex,
1673 locked_entry,
1674 });
1675 }
1676 None
1677 }
1678}
1679
1680impl<K, V, H> Debug for OccupiedEntry<'_, K, V, H>
1681where
1682 K: 'static + Clone + Debug + Eq + Hash,
1683 V: 'static + Clone + Debug,
1684 H: BuildHasher,
1685{
1686 #[inline]
1687 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1688 f.debug_struct("OccupiedEntry")
1689 .field("key", self.key())
1690 .field("value", self.get())
1691 .finish_non_exhaustive()
1692 }
1693}
1694
1695impl<K, V, H> Deref for OccupiedEntry<'_, K, V, H>
1696where
1697 K: 'static + Clone + Debug + Eq + Hash,
1698 V: 'static + Clone + Debug,
1699 H: BuildHasher,
1700{
1701 type Target = V;
1702
1703 #[inline]
1704 fn deref(&self) -> &Self::Target {
1705 self.get()
1706 }
1707}
1708
1709impl<'h, K, V, H> VacantEntry<'h, K, V, H>
1710where
1711 K: 'static + Clone + Eq + Hash,
1712 V: 'static + Clone,
1713 H: BuildHasher,
1714{
1715 /// Gets a reference to the key.
1716 ///
1717 /// # Examples
1718 ///
1719 /// ```
1720 /// use scc2::HashIndex;
1721 ///
1722 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1723 /// assert_eq!(hashindex.entry(11).key(), &11);
1724 /// ```
1725 #[inline]
1726 pub fn key(&self) -> &K {
1727 &self.key
1728 }
1729
1730 /// Takes ownership of the key.
1731 ///
1732 /// # Examples
1733 ///
1734 /// ```
1735 /// use scc2::HashIndex;
1736 /// use scc2::hash_index::Entry;
1737 ///
1738 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1739 ///
1740 /// if let Entry::Vacant(v) = hashindex.entry(17) {
1741 /// assert_eq!(v.into_key(), 17);
1742 /// };
1743 /// ```
1744 #[inline]
1745 pub fn into_key(self) -> K {
1746 self.key
1747 }
1748
1749 /// Sets the value of the entry with its key, and returns an [`OccupiedEntry`].
1750 ///
1751 /// # Examples
1752 ///
1753 /// ```
1754 /// use scc2::HashIndex;
1755 /// use scc2::hash_index::Entry;
1756 ///
1757 /// let hashindex: HashIndex<u64, u32> = HashIndex::default();
1758 ///
1759 /// if let Entry::Vacant(o) = hashindex.entry(19) {
1760 /// o.insert_entry(29);
1761 /// }
1762 ///
1763 /// assert_eq!(hashindex.peek_with(&19, |_, v| *v), Some(29));
1764 /// ```
1765 #[inline]
1766 pub fn insert_entry(mut self, val: V) -> OccupiedEntry<'h, K, V, H> {
1767 let guard = Guard::new();
1768 let entry_ptr = self.locked_entry.locker.insert_with(
1769 self.locked_entry.data_block_mut,
1770 BucketArray::<K, V, (), OPTIMISTIC>::partial_hash(self.hash),
1771 || (self.key, val),
1772 self.hashindex.prolonged_guard_ref(&guard),
1773 );
1774 OccupiedEntry {
1775 hashindex: self.hashindex,
1776 locked_entry: LockedEntry {
1777 index: self.locked_entry.index,
1778 data_block_mut: self.locked_entry.data_block_mut,
1779 locker: self.locked_entry.locker,
1780 entry_ptr,
1781 },
1782 }
1783 }
1784}
1785
1786impl<K, V, H> Debug for VacantEntry<'_, K, V, H>
1787where
1788 K: 'static + Clone + Debug + Eq + Hash,
1789 V: 'static + Clone + Debug,
1790 H: BuildHasher,
1791{
1792 #[inline]
1793 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1794 f.debug_tuple("VacantEntry").field(self.key()).finish()
1795 }
1796}
1797
1798impl<K, V, H> Reserve<'_, K, V, H>
1799where
1800 K: 'static + Clone + Eq + Hash,
1801 V: 'static + Clone,
1802 H: BuildHasher,
1803{
1804 /// Returns the number of reserved slots.
1805 #[inline]
1806 #[must_use]
1807 pub fn additional_capacity(&self) -> usize {
1808 self.additional
1809 }
1810}
1811
1812impl<K, V, H> AsRef<HashIndex<K, V, H>> for Reserve<'_, K, V, H>
1813where
1814 K: 'static + Clone + Eq + Hash,
1815 V: 'static + Clone,
1816 H: BuildHasher,
1817{
1818 #[inline]
1819 fn as_ref(&self) -> &HashIndex<K, V, H> {
1820 self.hashindex
1821 }
1822}
1823
1824impl<K, V, H> Debug for Reserve<'_, K, V, H>
1825where
1826 K: 'static + Clone + Eq + Hash,
1827 V: 'static + Clone,
1828 H: BuildHasher,
1829{
1830 #[inline]
1831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1832 f.debug_tuple("Reserve").field(&self.additional).finish()
1833 }
1834}
1835
1836impl<K, V, H> Deref for Reserve<'_, K, V, H>
1837where
1838 K: 'static + Clone + Eq + Hash,
1839 V: 'static + Clone,
1840 H: BuildHasher,
1841{
1842 type Target = HashIndex<K, V, H>;
1843
1844 #[inline]
1845 fn deref(&self) -> &Self::Target {
1846 self.hashindex
1847 }
1848}
1849
1850impl<K, V, H> Drop for Reserve<'_, K, V, H>
1851where
1852 K: 'static + Clone + Eq + Hash,
1853 V: 'static + Clone,
1854 H: BuildHasher,
1855{
1856 #[inline]
1857 fn drop(&mut self) {
1858 let result = self
1859 .hashindex
1860 .minimum_capacity
1861 .fetch_sub(self.additional, Relaxed);
1862 self.hashindex.try_resize(0, &Guard::new());
1863 debug_assert!(result >= self.additional);
1864 }
1865}
1866
1867impl<K, V, H> Debug for Iter<'_, '_, K, V, H>
1868where
1869 K: 'static + Clone + Eq + Hash,
1870 V: 'static + Clone,
1871 H: BuildHasher,
1872{
1873 #[inline]
1874 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1875 f.debug_struct("Iter")
1876 .field("current_index", &self.current_index)
1877 .field("current_entry_ptr", &self.current_entry_ptr)
1878 .finish()
1879 }
1880}
1881
1882impl<'g, K, V, H> Iterator for Iter<'_, 'g, K, V, H>
1883where
1884 K: 'static + Clone + Eq + Hash,
1885 V: 'static + Clone,
1886 H: BuildHasher,
1887{
1888 type Item = (&'g K, &'g V);
1889
1890 #[inline]
1891 fn next(&mut self) -> Option<Self::Item> {
1892 let mut array = if let Some(array) = self.current_array.as_ref().copied() {
1893 array
1894 } else {
1895 // Start scanning.
1896 let current_array = self
1897 .hashindex
1898 .bucket_array()
1899 .load(Acquire, self.guard)
1900 .as_ref()?;
1901 let old_array_ptr = current_array.old_array(self.guard);
1902 let array = if let Some(old_array) = old_array_ptr.as_ref() {
1903 old_array
1904 } else {
1905 current_array
1906 };
1907 self.current_array.replace(array);
1908 self.current_bucket.replace(array.bucket(0));
1909 self.current_entry_ptr = EntryPtr::new(self.guard);
1910 array
1911 };
1912
1913 // Go to the next bucket.
1914 loop {
1915 if let Some(bucket) = self.current_bucket.take() {
1916 // Go to the next entry in the bucket.
1917 if self.current_entry_ptr.move_to_next(bucket, self.guard) {
1918 let (k, v) = self
1919 .current_entry_ptr
1920 .get(array.data_block(self.current_index));
1921 self.current_bucket.replace(bucket);
1922 return Some((k, v));
1923 }
1924 }
1925 self.current_index += 1;
1926 if self.current_index == array.num_buckets() {
1927 let current_array = self
1928 .hashindex
1929 .bucket_array()
1930 .load(Acquire, self.guard)
1931 .as_ref()?;
1932 if self
1933 .current_array
1934 .as_ref()
1935 .copied()
1936 .map_or(false, |a| ptr::eq(a, current_array))
1937 {
1938 // Finished scanning the entire array.
1939 break;
1940 }
1941 let old_array_ptr = current_array.old_array(self.guard);
1942 if self
1943 .current_array
1944 .as_ref()
1945 .copied()
1946 .map_or(false, |a| ptr::eq(a, old_array_ptr.as_ptr()))
1947 {
1948 // Start scanning the current array.
1949 array = current_array;
1950 self.current_array.replace(array);
1951 self.current_index = 0;
1952 self.current_bucket.replace(array.bucket(0));
1953 self.current_entry_ptr = EntryPtr::new(self.guard);
1954 continue;
1955 }
1956
1957 // Start from the very beginning.
1958 array = if let Some(old_array) = old_array_ptr.as_ref() {
1959 old_array
1960 } else {
1961 current_array
1962 };
1963 self.current_array.replace(array);
1964 self.current_index = 0;
1965 self.current_bucket.replace(array.bucket(0));
1966 self.current_entry_ptr = EntryPtr::new(self.guard);
1967 continue;
1968 }
1969 self.current_bucket
1970 .replace(array.bucket(self.current_index));
1971 self.current_entry_ptr = EntryPtr::new(self.guard);
1972 }
1973 None
1974 }
1975}
1976
1977impl<K, V, H> FusedIterator for Iter<'_, '_, K, V, H>
1978where
1979 K: 'static + Clone + Eq + Hash,
1980 V: 'static + Clone,
1981 H: BuildHasher,
1982{
1983}
1984
1985impl<K, V, H> UnwindSafe for Iter<'_, '_, K, V, H>
1986where
1987 K: 'static + Clone + Eq + Hash + UnwindSafe,
1988 V: 'static + Clone + UnwindSafe,
1989 H: BuildHasher + UnwindSafe,
1990{
1991}