scc/hash_set.rs
1//! [`HashSet`] is an asynchronous/concurrent hash set.
2
3#![deny(unsafe_code)]
4
5use std::collections::hash_map::RandomState;
6use std::fmt::{self, Debug};
7use std::hash::{BuildHasher, Hash};
8use std::mem::swap;
9use std::ops::{Deref, RangeInclusive};
10
11use super::hash_map;
12use super::hash_table::HashTable;
13use super::{Equivalent, HashMap};
14
15/// Scalable asynchronous/concurrent hash set.
16///
17/// [`HashSet`] is an asynchronous/concurrent hash set based on [`HashMap`].
18pub struct HashSet<K, H = RandomState>
19where
20 H: BuildHasher,
21{
22 map: HashMap<K, (), H>,
23}
24
25/// [`ConsumableEntry`] is a view into an occupied entry in a [`HashSet`] when iterating over
26/// entries in it.
27pub struct ConsumableEntry<'w, K> {
28 consumable: hash_map::ConsumableEntry<'w, K, ()>,
29}
30
31/// [`Reserve`] keeps the capacity of the associated [`HashSet`] higher than a certain level.
32///
33/// The [`HashSet`] does not shrink the capacity below the reserved capacity.
34pub type Reserve<'h, K, H = RandomState> = super::hash_map::Reserve<'h, K, (), H>;
35
36impl<K, H> HashSet<K, H>
37where
38 H: BuildHasher,
39{
40 /// Creates an empty [`HashSet`] with the given [`BuildHasher`].
41 ///
42 /// # Examples
43 ///
44 /// ```
45 /// use scc::HashSet;
46 /// use std::collections::hash_map::RandomState;
47 ///
48 /// let hashset: HashSet<u64, RandomState> = HashSet::with_hasher(RandomState::new());
49 /// ```
50 #[cfg(not(feature = "loom"))]
51 #[inline]
52 pub const fn with_hasher(build_hasher: H) -> Self {
53 Self {
54 map: HashMap::with_hasher(build_hasher),
55 }
56 }
57
58 /// Creates an empty [`HashSet`] with the given [`BuildHasher`].
59 #[cfg(feature = "loom")]
60 #[inline]
61 pub fn with_hasher(build_hasher: H) -> Self {
62 Self {
63 map: HashMap::with_hasher(build_hasher),
64 }
65 }
66
67 /// Creates an empty [`HashSet`] with the specified capacity and [`BuildHasher`].
68 ///
69 /// The actual capacity is equal to or greater than `capacity` unless it is greater than
70 /// `1 << (usize::BITS - 1)`.
71 ///
72 /// # Examples
73 ///
74 /// ```
75 /// use scc::HashSet;
76 /// use std::collections::hash_map::RandomState;
77 ///
78 /// let hashset: HashSet<u64, RandomState> =
79 /// HashSet::with_capacity_and_hasher(1000, RandomState::new());
80 ///
81 /// let result = hashset.capacity();
82 /// assert_eq!(result, 1024);
83 /// ```
84 #[inline]
85 pub fn with_capacity_and_hasher(capacity: usize, build_hasher: H) -> Self {
86 Self {
87 map: HashMap::with_capacity_and_hasher(capacity, build_hasher),
88 }
89 }
90}
91
92impl<K, H> HashSet<K, H>
93where
94 K: Eq + Hash,
95 H: BuildHasher,
96{
97 /// Temporarily increases the minimum capacity of the [`HashSet`].
98 ///
99 /// A [`Reserve`] is returned if the [`HashSet`] could increase the minimum capacity while the
100 /// increased capacity is not exclusively owned by the returned [`Reserve`], allowing others to
101 /// benefit from it. The memory for the additional space may not be immediately allocated if
102 /// the [`HashSet`] is empty or currently being resized, however once the memory is reserved
103 /// eventually, the capacity will not shrink below the additional capacity until the returned
104 /// [`Reserve`] is dropped.
105 ///
106 /// # Errors
107 ///
108 /// Returns `None` if a too large number is given.
109 ///
110 /// # Examples
111 ///
112 /// ```
113 /// use scc::HashSet;
114 ///
115 /// let hashset: HashSet<usize> = HashSet::with_capacity(1000);
116 /// assert_eq!(hashset.capacity(), 1024);
117 ///
118 /// let reserved = hashset.reserve(10000);
119 /// assert!(reserved.is_some());
120 /// assert_eq!(hashset.capacity(), 16384);
121 ///
122 /// assert!(hashset.reserve(usize::MAX).is_none());
123 /// assert_eq!(hashset.capacity(), 16384);
124 ///
125 /// for i in 0..16 {
126 /// assert!(hashset.insert_sync(i).is_ok());
127 /// }
128 /// drop(reserved);
129 ///
130 /// assert_eq!(hashset.capacity(), 1024);
131 /// ```
132 #[inline]
133 pub fn reserve(&self, capacity: usize) -> Option<Reserve<'_, K, H>> {
134 self.map.reserve(capacity)
135 }
136
137 /// Inserts a key into the [`HashSet`].
138 ///
139 /// # Errors
140 ///
141 /// Returns an error along with the supplied key if the key exists.
142 ///
143 /// # Examples
144 ///
145 /// ```
146 /// use scc::HashSet;
147 ///
148 /// let hashset: HashSet<u64> = HashSet::default();
149 /// let future_insert = hashset.insert_async(11);
150 /// ```
151 #[inline]
152 pub async fn insert_async(&self, key: K) -> Result<(), K> {
153 self.map.insert_async(key, ()).await.map_err(|(k, ())| k)
154 }
155
156 /// Inserts a key into the [`HashSet`].
157 ///
158 /// # Errors
159 ///
160 /// Returns an error along with the supplied key if the key exists.
161 ///
162 /// # Examples
163 ///
164 /// ```
165 /// use scc::HashSet;
166 ///
167 /// let hashset: HashSet<u64> = HashSet::default();
168 ///
169 /// assert!(hashset.insert_sync(1).is_ok());
170 /// assert_eq!(hashset.insert_sync(1).unwrap_err(), 1);
171 /// ```
172 #[inline]
173 pub fn insert_sync(&self, key: K) -> Result<(), K> {
174 if let Err((k, ())) = self.map.insert_sync(key, ()) {
175 return Err(k);
176 }
177 Ok(())
178 }
179
180 /// Adds a key to the set, replacing the existing key, if any, that is equal to the given one.
181 ///
182 /// Returns the replaced key, if any.
183 ///
184 /// # Examples
185 ///
186 /// ```
187 /// use std::cmp::{Eq, PartialEq};
188 /// use std::hash::{Hash, Hasher};
189 ///
190 /// use scc::HashSet;
191 ///
192 /// #[derive(Debug)]
193 /// struct MaybeEqual(u64, u64);
194 ///
195 /// impl Eq for MaybeEqual {}
196 ///
197 /// impl Hash for MaybeEqual {
198 /// fn hash<H: Hasher>(&self, state: &mut H) {
199 /// // Do not read `self.1`.
200 /// self.0.hash(state);
201 /// }
202 /// }
203 ///
204 /// impl PartialEq for MaybeEqual {
205 /// fn eq(&self, other: &Self) -> bool {
206 /// // Do not compare `self.1`.
207 /// self.0 == other.0
208 /// }
209 /// }
210 ///
211 /// let hashset: HashSet<MaybeEqual> = HashSet::default();
212 ///
213 /// assert!(hashset.replace_sync(MaybeEqual(11, 7)).is_none());
214 /// assert_eq!(hashset.replace_sync(MaybeEqual(11, 11)), Some(MaybeEqual(11, 7)));
215 /// ```
216 #[inline]
217 pub async fn replace_async(&self, mut key: K) -> Option<K> {
218 let hash = self.map.hash(&key);
219 let mut locked_bucket = self.map.writer_async(hash).await;
220 let mut entry_ptr = locked_bucket.search(&key, hash);
221 if entry_ptr.is_valid() {
222 let k = locked_bucket.entry_mut(&mut entry_ptr).0;
223 swap(k, &mut key);
224 Some(key)
225 } else {
226 locked_bucket.insert(hash, (key, ()));
227 None
228 }
229 }
230
231 /// Adds a key to the set, replacing the existing key, if any, that is equal to the given one.
232 ///
233 /// Returns the replaced key, if any.
234 ///
235 /// # Examples
236 ///
237 /// ```
238 /// use std::cmp::{Eq, PartialEq};
239 /// use std::hash::{Hash, Hasher};
240 ///
241 /// use scc::HashSet;
242 ///
243 /// #[derive(Debug)]
244 /// struct MaybeEqual(u64, u64);
245 ///
246 /// impl Eq for MaybeEqual {}
247 ///
248 /// impl Hash for MaybeEqual {
249 /// fn hash<H: Hasher>(&self, state: &mut H) {
250 /// // Do not read `self.1`.
251 /// self.0.hash(state);
252 /// }
253 /// }
254 ///
255 /// impl PartialEq for MaybeEqual {
256 /// fn eq(&self, other: &Self) -> bool {
257 /// // Do not compare `self.1`.
258 /// self.0 == other.0
259 /// }
260 /// }
261 ///
262 /// let hashset: HashSet<MaybeEqual> = HashSet::default();
263 ///
264 /// async {
265 /// assert!(hashset.replace_async(MaybeEqual(11, 7)).await.is_none());
266 /// assert_eq!(hashset.replace_async(MaybeEqual(11, 11)).await, Some(MaybeEqual(11, 7)));
267 /// };
268 /// ```
269 #[inline]
270 pub fn replace_sync(&self, mut key: K) -> Option<K> {
271 let hash = self.map.hash(&key);
272 let mut locked_bucket = self.map.writer_sync(hash);
273 let mut entry_ptr = locked_bucket.search(&key, hash);
274 if entry_ptr.is_valid() {
275 let k = locked_bucket.entry_mut(&mut entry_ptr).0;
276 swap(k, &mut key);
277 Some(key)
278 } else {
279 locked_bucket.insert(hash, (key, ()));
280 None
281 }
282 }
283
284 /// Removes a key if the key exists.
285 ///
286 /// Returns `None` if the key does not exist.
287 ///
288 /// # Examples
289 ///
290 /// ```
291 /// use scc::HashSet;
292 ///
293 /// let hashset: HashSet<u64> = HashSet::default();
294 /// let future_insert = hashset.insert_async(11);
295 /// let future_remove = hashset.remove_async(&11);
296 /// ```
297 #[inline]
298 pub async fn remove_async<Q>(&self, key: &Q) -> Option<K>
299 where
300 Q: Equivalent<K> + Hash + ?Sized,
301 {
302 self.map
303 .remove_if_async(key, |()| true)
304 .await
305 .map(|(k, ())| k)
306 }
307
308 /// Removes a key if the key exists.
309 ///
310 /// Returns `None` if the key does not exist.
311 ///
312 /// # Examples
313 ///
314 /// ```
315 /// use scc::HashSet;
316 ///
317 /// let hashset: HashSet<u64> = HashSet::default();
318 ///
319 /// assert!(hashset.remove_sync(&1).is_none());
320 /// assert!(hashset.insert_sync(1).is_ok());
321 /// assert_eq!(hashset.remove_sync(&1).unwrap(), 1);
322 /// ```
323 #[inline]
324 pub fn remove_sync<Q>(&self, key: &Q) -> Option<K>
325 where
326 Q: Equivalent<K> + Hash + ?Sized,
327 {
328 self.map.remove_sync(key).map(|(k, ())| k)
329 }
330
331 /// Removes a key if the key exists and the given condition is met.
332 ///
333 /// Returns `None` if the key does not exist or the condition was not met.
334 ///
335 /// # Examples
336 ///
337 /// ```
338 /// use scc::HashSet;
339 ///
340 /// let hashset: HashSet<u64> = HashSet::default();
341 /// let future_insert = hashset.insert_async(11);
342 /// let future_remove = hashset.remove_if_async(&11, || true);
343 /// ```
344 #[inline]
345 pub async fn remove_if_async<Q, F: FnOnce() -> bool>(&self, key: &Q, condition: F) -> Option<K>
346 where
347 Q: Equivalent<K> + Hash + ?Sized,
348 {
349 self.map
350 .remove_if_async(key, |()| condition())
351 .await
352 .map(|(k, ())| k)
353 }
354
355 /// Removes a key if the key exists and the given condition is met.
356 ///
357 /// Returns `None` if the key does not exist or the condition was not met.
358 ///
359 /// # Examples
360 ///
361 /// ```
362 /// use scc::HashSet;
363 ///
364 /// let hashset: HashSet<u64> = HashSet::default();
365 ///
366 /// assert!(hashset.insert_sync(1).is_ok());
367 /// assert!(hashset.remove_if_sync(&1, || false).is_none());
368 /// assert_eq!(hashset.remove_if_sync(&1, || true).unwrap(), 1);
369 /// ```
370 #[inline]
371 pub fn remove_if_sync<Q, F: FnOnce() -> bool>(&self, key: &Q, condition: F) -> Option<K>
372 where
373 Q: Equivalent<K> + Hash + ?Sized,
374 {
375 self.map
376 .remove_if_sync(key, |()| condition())
377 .map(|(k, ())| k)
378 }
379
380 /// Reads a key.
381 ///
382 /// Returns `None` if the key does not exist.
383 ///
384 /// # Examples
385 ///
386 /// ```
387 /// use scc::HashSet;
388 ///
389 /// let hashset: HashSet<u64> = HashSet::default();
390 /// let future_insert = hashset.insert_async(11);
391 /// let future_read = hashset.read_async(&11, |k| *k);
392 /// ```
393 #[inline]
394 pub async fn read_async<Q, R, F: FnOnce(&K) -> R>(&self, key: &Q, reader: F) -> Option<R>
395 where
396 Q: Equivalent<K> + Hash + ?Sized,
397 {
398 self.map.read_async(key, |k, ()| reader(k)).await
399 }
400
401 /// Reads a key.
402 ///
403 /// Returns `None` if the key does not exist.
404 ///
405 /// # Examples
406 ///
407 /// ```
408 /// use scc::HashSet;
409 ///
410 /// let hashset: HashSet<u64> = HashSet::default();
411 ///
412 /// assert!(hashset.read_sync(&1, |_| true).is_none());
413 /// assert!(hashset.insert_sync(1).is_ok());
414 /// assert!(hashset.read_sync(&1, |_| true).unwrap());
415 /// ```
416 #[inline]
417 pub fn read_sync<Q, R, F: FnOnce(&K) -> R>(&self, key: &Q, reader: F) -> Option<R>
418 where
419 Q: Equivalent<K> + Hash + ?Sized,
420 {
421 self.map.read_sync(key, |k, ()| reader(k))
422 }
423
424 /// Returns `true` if the [`HashSet`] contains the specified key.
425 ///
426 /// # Examples
427 ///
428 /// ```
429 /// use scc::HashSet;
430 ///
431 /// let hashset: HashSet<u64> = HashSet::default();
432 ///
433 /// let future_contains = hashset.contains_async(&1);
434 /// ```
435 #[inline]
436 pub async fn contains_async<Q>(&self, key: &Q) -> bool
437 where
438 Q: Equivalent<K> + Hash + ?Sized,
439 {
440 self.map.contains_async(key).await
441 }
442
443 /// Returns `true` if the [`HashSet`] contains the specified key.
444 ///
445 /// # Examples
446 ///
447 /// ```
448 /// use scc::HashSet;
449 ///
450 /// let hashset: HashSet<u64> = HashSet::default();
451 ///
452 /// assert!(!hashset.contains_sync(&1));
453 /// assert!(hashset.insert_sync(1).is_ok());
454 /// assert!(hashset.contains_sync(&1));
455 /// ```
456 #[inline]
457 pub fn contains_sync<Q>(&self, key: &Q) -> bool
458 where
459 Q: Equivalent<K> + Hash + ?Sized,
460 {
461 self.read_sync(key, |_| ()).is_some()
462 }
463
464 /// Iterates over entries asynchronously for reading.
465 ///
466 /// Stops iterating when the closure returns `false`, and this method also returns `false`.
467 ///
468 /// # Examples
469 ///
470 /// ```
471 /// use scc::HashSet;
472 ///
473 /// let hashset: HashSet<u64> = HashSet::default();
474 ///
475 /// assert!(hashset.insert_sync(1).is_ok());
476 ///
477 /// async {
478 /// let result = hashset.iter_async(|k| {
479 /// true
480 /// }).await;
481 /// assert!(result);
482 /// };
483 /// ```
484 #[inline]
485 pub async fn iter_async<F: FnMut(&K) -> bool>(&self, mut f: F) -> bool {
486 self.map.iter_async(|k, ()| f(k)).await
487 }
488
489 /// Iterates over entries synchronously for reading.
490 ///
491 /// Stops iterating when the closure returns `false`, and this method also returns `false`.
492 ///
493 /// # Examples
494 ///
495 /// ```
496 /// use scc::HashSet;
497 ///
498 /// let hashset: HashSet<u64> = HashSet::default();
499 ///
500 /// assert!(hashset.insert_sync(1).is_ok());
501 /// assert!(hashset.insert_sync(2).is_ok());
502 ///
503 /// let mut acc = 0;
504 /// let result = hashset.iter_sync(|k| {
505 /// acc += *k;
506 /// true
507 /// });
508 ///
509 /// assert!(result);
510 /// assert_eq!(acc, 3);
511 /// ```
512 #[inline]
513 pub fn iter_sync<F: FnMut(&K) -> bool>(&self, mut f: F) -> bool {
514 self.map.iter_sync(|k, ()| f(k))
515 }
516
517 /// Iterates over entries asynchronously for modification.
518 ///
519 /// This method stops iterating when the closure returns `false`, and also returns `false` in
520 /// that case.
521 ///
522 /// # Examples
523 ///
524 /// ```
525 /// use scc::HashSet;
526 ///
527 /// let hashset: HashSet<u64> = HashSet::default();
528 ///
529 /// assert!(hashset.insert_sync(1).is_ok());
530 /// assert!(hashset.insert_sync(2).is_ok());
531 ///
532 /// async {
533 /// let result = hashset.iter_mut_async(|e| {
534 /// if *e == 1 {
535 /// e.consume();
536 /// return false;
537 /// }
538 /// true
539 /// }).await;
540 ///
541 /// assert!(!result);
542 /// assert_eq!(hashset.len(), 1);
543 /// };
544 /// ```
545 #[inline]
546 pub async fn iter_mut_async<F: FnMut(ConsumableEntry<'_, K>) -> bool>(&self, mut f: F) -> bool {
547 self.map
548 .iter_mut_async(|consumable| f(ConsumableEntry { consumable }))
549 .await
550 }
551
552 /// Iterates over entries synchronously for modification.
553 ///
554 /// This method stops iterating when the closure returns `false`, and also returns `false` in
555 /// that case.
556 ///
557 /// # Examples
558 ///
559 /// ```
560 /// use scc::HashSet;
561 ///
562 /// let hashset: HashSet<u64> = HashSet::default();
563 ///
564 /// assert!(hashset.insert_sync(1).is_ok());
565 /// assert!(hashset.insert_sync(2).is_ok());
566 /// assert!(hashset.insert_sync(3).is_ok());
567 ///
568 /// let result = hashset.iter_mut_sync(|e| {
569 /// if *e == 1 {
570 /// e.consume();
571 /// return false;
572 /// }
573 /// true
574 /// });
575 ///
576 /// assert!(!result);
577 /// assert!(!hashset.contains_sync(&1));
578 /// assert_eq!(hashset.len(), 2);
579 /// ```
580 #[inline]
581 pub fn iter_mut_sync<F: FnMut(ConsumableEntry<'_, K>) -> bool>(&self, mut f: F) -> bool {
582 self.map
583 .iter_mut_sync(|consumable| f(ConsumableEntry { consumable }))
584 }
585
586 /// Retains keys that satisfy the given predicate.
587 ///
588 /// # Examples
589 ///
590 /// ```
591 /// use scc::HashSet;
592 ///
593 /// let hashset: HashSet<u64> = HashSet::default();
594 ///
595 /// let future_insert = hashset.insert_async(1);
596 /// let future_retain = hashset.retain_async(|k| *k == 1);
597 /// ```
598 #[inline]
599 pub async fn retain_async<F: FnMut(&K) -> bool>(&self, mut filter: F) {
600 self.map.retain_async(|k, ()| filter(k)).await;
601 }
602
603 /// Retains keys that satisfy the given predicate.
604 ///
605 /// # Examples
606 ///
607 /// ```
608 /// use scc::HashSet;
609 ///
610 /// let hashset: HashSet<u64> = HashSet::default();
611 ///
612 /// assert!(hashset.insert_sync(1).is_ok());
613 /// assert!(hashset.insert_sync(2).is_ok());
614 /// assert!(hashset.insert_sync(3).is_ok());
615 ///
616 /// hashset.retain_sync(|k| *k == 1);
617 ///
618 /// assert!(hashset.contains_sync(&1));
619 /// assert!(!hashset.contains_sync(&2));
620 /// assert!(!hashset.contains_sync(&3));
621 /// ```
622 #[inline]
623 pub fn retain_sync<F: FnMut(&K) -> bool>(&self, mut pred: F) {
624 self.iter_mut_sync(|e| {
625 if !pred(&*e) {
626 drop(e.consume());
627 }
628 true
629 });
630 }
631
632 /// Clears the [`HashSet`] by removing all keys.
633 ///
634 /// # Examples
635 ///
636 /// ```
637 /// use scc::HashSet;
638 ///
639 /// let hashset: HashSet<u64> = HashSet::default();
640 ///
641 /// let future_insert = hashset.insert_async(1);
642 /// let future_clear = hashset.clear_async();
643 /// ```
644 #[inline]
645 pub async fn clear_async(&self) {
646 self.map.clear_async().await;
647 }
648
649 /// Clears the [`HashSet`] by removing all keys.
650 ///
651 /// # Examples
652 ///
653 /// ```
654 /// use scc::HashSet;
655 ///
656 /// let hashset: HashSet<u64> = HashSet::default();
657 ///
658 /// assert!(hashset.insert_sync(1).is_ok());
659 /// hashset.clear_sync();
660 ///
661 /// assert!(!hashset.contains_sync(&1));
662 /// ```
663 #[inline]
664 pub fn clear_sync(&self) {
665 self.map.clear_sync();
666 }
667
668 /// Returns the number of entries in the [`HashSet`].
669 ///
670 /// It reads the entire metadata area of the bucket array to calculate the number of valid
671 /// entries, making its time complexity `O(N)`. Furthermore, it may overcount entries if an old
672 /// bucket array has yet to be dropped.
673 ///
674 /// # Examples
675 ///
676 /// ```
677 /// use scc::HashSet;
678 ///
679 /// let hashset: HashSet<u64> = HashSet::default();
680 ///
681 /// assert!(hashset.insert_sync(1).is_ok());
682 /// assert_eq!(hashset.len(), 1);
683 /// ```
684 #[inline]
685 pub fn len(&self) -> usize {
686 self.map.len()
687 }
688
689 /// Returns `true` if the [`HashSet`] is empty.
690 ///
691 /// # Examples
692 ///
693 /// ```
694 /// use scc::HashSet;
695 ///
696 /// let hashset: HashSet<u64> = HashSet::default();
697 ///
698 /// assert!(hashset.is_empty());
699 /// assert!(hashset.insert_sync(1).is_ok());
700 /// assert!(!hashset.is_empty());
701 /// ```
702 #[inline]
703 pub fn is_empty(&self) -> bool {
704 self.map.is_empty()
705 }
706
707 /// Returns the capacity of the [`HashSet`].
708 ///
709 /// # Examples
710 ///
711 /// ```
712 /// use scc::HashSet;
713 ///
714 /// let hashset_default: HashSet<u64> = HashSet::default();
715 /// assert_eq!(hashset_default.capacity(), 0);
716 ///
717 /// assert!(hashset_default.insert_sync(1).is_ok());
718 /// assert_eq!(hashset_default.capacity(), 64);
719 ///
720 /// let hashset: HashSet<u64> = HashSet::with_capacity(1000);
721 /// assert_eq!(hashset.capacity(), 1024);
722 /// ```
723 #[inline]
724 pub fn capacity(&self) -> usize {
725 self.map.capacity()
726 }
727
728 /// Returns the current capacity range of the [`HashSet`].
729 ///
730 /// # Examples
731 ///
732 /// ```
733 /// use scc::HashSet;
734 ///
735 /// let hashset: HashSet<u64> = HashSet::default();
736 ///
737 /// assert_eq!(hashset.capacity_range(), 0..=(1_usize << (usize::BITS - 2)));
738 ///
739 /// let reserved = hashset.reserve(1000);
740 /// assert_eq!(hashset.capacity_range(), 1000..=(1_usize << (usize::BITS - 2)));
741 /// ```
742 #[inline]
743 pub fn capacity_range(&self) -> RangeInclusive<usize> {
744 self.map.capacity_range()
745 }
746
747 /// Returns the index of the bucket that may contain the key.
748 ///
749 /// The method returns the index of the bucket associated with the key. The number of buckets
750 /// can be calculated by dividing the capacity by `32`.
751 ///
752 /// # Examples
753 ///
754 /// ```
755 /// use scc::HashSet;
756 ///
757 /// let hashset: HashSet<u64> = HashSet::with_capacity(1024);
758 ///
759 /// let bucket_index = hashset.bucket_index(&11);
760 /// assert!(bucket_index < hashset.capacity() / 32);
761 /// ```
762 #[inline]
763 pub fn bucket_index<Q>(&self, key: &Q) -> usize
764 where
765 Q: Equivalent<K> + Hash + ?Sized,
766 {
767 self.map.bucket_index(key)
768 }
769}
770
771impl<K, H> Clone for HashSet<K, H>
772where
773 K: Clone + Eq + Hash,
774 H: BuildHasher + Clone,
775{
776 #[inline]
777 fn clone(&self) -> Self {
778 Self {
779 map: self.map.clone(),
780 }
781 }
782}
783
784impl<K, H> Debug for HashSet<K, H>
785where
786 K: Debug + Eq + Hash,
787 H: BuildHasher,
788{
789 #[inline]
790 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
791 let mut d = f.debug_set();
792 self.iter_sync(|k| {
793 d.entry(k);
794 true
795 });
796 d.finish()
797 }
798}
799
800impl<K: Eq + Hash> HashSet<K, RandomState> {
801 /// Creates an empty default [`HashSet`].
802 ///
803 /// # Examples
804 ///
805 /// ```
806 /// use scc::HashSet;
807 ///
808 /// let hashset: HashSet<u64> = HashSet::new();
809 ///
810 /// let result = hashset.capacity();
811 /// assert_eq!(result, 0);
812 /// ```
813 #[inline]
814 #[must_use]
815 pub fn new() -> Self {
816 Self::default()
817 }
818
819 /// Creates an empty [`HashSet`] with the specified capacity.
820 ///
821 /// The actual capacity is equal to or greater than `capacity` unless it is greater than
822 /// `1 << (usize::BITS - 1)`.
823 ///
824 /// # Examples
825 ///
826 /// ```
827 /// use scc::HashSet;
828 ///
829 /// let hashset: HashSet<u64> = HashSet::with_capacity(1000);
830 ///
831 /// let result = hashset.capacity();
832 /// assert_eq!(result, 1024);
833 /// ```
834 #[inline]
835 #[must_use]
836 pub fn with_capacity(capacity: usize) -> Self {
837 Self {
838 map: HashMap::with_capacity(capacity),
839 }
840 }
841}
842
843impl<K, H> Default for HashSet<K, H>
844where
845 H: BuildHasher + Default,
846{
847 /// Creates an empty default [`HashSet`].
848 ///
849 /// The default capacity is `0`.
850 ///
851 /// # Examples
852 ///
853 /// ```
854 /// use scc::HashSet;
855 ///
856 /// let hashset: HashSet<u64> = HashSet::default();
857 ///
858 /// let result = hashset.capacity();
859 /// assert_eq!(result, 0);
860 /// ```
861 #[inline]
862 fn default() -> Self {
863 Self {
864 map: HashMap::default(),
865 }
866 }
867}
868
869impl<K, H> FromIterator<K> for HashSet<K, H>
870where
871 K: Eq + Hash,
872 H: BuildHasher + Default,
873{
874 #[inline]
875 fn from_iter<T: IntoIterator<Item = K>>(iter: T) -> Self {
876 let into_iter = iter.into_iter();
877 let hashset = Self::with_capacity_and_hasher(
878 HashMap::<K, (), H>::capacity_from_size_hint(into_iter.size_hint()),
879 H::default(),
880 );
881 into_iter.for_each(|k| {
882 let _result = hashset.insert_sync(k);
883 });
884 hashset
885 }
886}
887
888impl<K, H> PartialEq for HashSet<K, H>
889where
890 K: Eq + Hash,
891 H: BuildHasher,
892{
893 /// Compares two [`HashSet`] instances.
894 ///
895 /// ### Locking behavior
896 ///
897 /// Shared locks on buckets are acquired when comparing two instances of [`HashSet`], therefore
898 /// it may lead to a deadlock if the instances are being modified by another thread.
899 #[inline]
900 fn eq(&self, other: &Self) -> bool {
901 if self.iter_sync(|k| other.contains_sync(k)) {
902 return other.iter_sync(|k| self.contains_sync(k));
903 }
904 false
905 }
906}
907
908impl<K> ConsumableEntry<'_, K> {
909 /// Consumes the entry by moving out the key.
910 ///
911 /// # Examples
912 ///
913 /// ```
914 /// use scc::HashSet;
915 ///
916 /// let hashset: HashSet<u64> = HashSet::default();
917 ///
918 /// assert!(hashset.insert_sync(1).is_ok());
919 /// assert!(hashset.insert_sync(2).is_ok());
920 /// assert!(hashset.insert_sync(3).is_ok());
921 ///
922 /// let mut consumed = None;
923 ///
924 /// hashset.iter_mut_sync(|e| {
925 /// if *e == 1 {
926 /// consumed.replace(e.consume());
927 /// }
928 /// true
929 /// });
930 ///
931 /// assert!(!hashset.contains_sync(&1));
932 /// assert_eq!(consumed, Some(1));
933 /// ```
934 #[inline]
935 #[must_use]
936 pub fn consume(self) -> K {
937 self.consumable.consume().0
938 }
939}
940
941impl<K> Deref for ConsumableEntry<'_, K> {
942 type Target = K;
943
944 #[inline]
945 fn deref(&self) -> &Self::Target {
946 self.consumable.key()
947 }
948}