/rust/registry/src/index.crates.io-1949cf8c6b5b557f/papaya-0.2.3/src/set.rs
Line | Count | Source |
1 | | use crate::raw::utils::MapGuard; |
2 | | use crate::raw::{self, InsertResult}; |
3 | | use crate::Equivalent; |
4 | | use seize::{Collector, Guard, LocalGuard, OwnedGuard}; |
5 | | |
6 | | use crate::map::ResizeMode; |
7 | | use std::collections::hash_map::RandomState; |
8 | | use std::fmt; |
9 | | use std::hash::{BuildHasher, Hash}; |
10 | | use std::marker::PhantomData; |
11 | | |
12 | | /// A concurrent hash set. |
13 | | /// |
14 | | /// Most hash set operations require a [`Guard`](crate::Guard), which can be acquired through |
15 | | /// [`HashSet::guard`] or using the [`HashSet::pin`] API. See the [crate-level documentation](crate#usage) |
16 | | /// for details. |
17 | | pub struct HashSet<K, S = RandomState> { |
18 | | raw: raw::HashMap<K, (), S>, |
19 | | } |
20 | | |
21 | | // Safety: We only ever hand out &K through shared references to the map, |
22 | | // so normal Send/Sync rules apply. We never expose owned or mutable references |
23 | | // to keys or values. |
24 | | unsafe impl<K: Send, S: Send> Send for HashSet<K, S> {} |
25 | | unsafe impl<K: Sync, S: Sync> Sync for HashSet<K, S> {} |
26 | | |
27 | | /// A builder for a [`HashSet`]. |
28 | | /// |
29 | | /// # Examples |
30 | | /// |
31 | | /// ```rust |
32 | | /// use papaya::{HashSet, ResizeMode}; |
33 | | /// use seize::Collector; |
34 | | /// use std::collections::hash_map::RandomState; |
35 | | /// |
36 | | /// let set: HashSet<i32> = HashSet::builder() |
37 | | /// // Set the initial capacity. |
38 | | /// .capacity(2048) |
39 | | /// // Set the hasher. |
40 | | /// .hasher(RandomState::new()) |
41 | | /// // Set the resize mode. |
42 | | /// .resize_mode(ResizeMode::Blocking) |
43 | | /// // Set a custom garbage collector. |
44 | | /// .collector(Collector::new().batch_size(128)) |
45 | | /// // Construct the hash set. |
46 | | /// .build(); |
47 | | /// ``` |
48 | | pub struct HashSetBuilder<K, S = RandomState> { |
49 | | hasher: S, |
50 | | capacity: usize, |
51 | | collector: Collector, |
52 | | resize_mode: ResizeMode, |
53 | | _kv: PhantomData<K>, |
54 | | } |
55 | | |
56 | | impl<K> HashSetBuilder<K> { |
57 | | /// Set the hash builder used to hash keys. |
58 | | /// |
59 | | /// Warning: `hash_builder` is normally randomly generated, and is designed |
60 | | /// to allow HashSets to be resistant to attacks that cause many collisions |
61 | | /// and very poor performance. Setting it manually using this function can |
62 | | /// expose a DoS attack vector. |
63 | | /// |
64 | | /// The `hash_builder` passed should implement the [`BuildHasher`] trait for |
65 | | /// the HashSet to be useful, see its documentation for details. |
66 | 0 | pub fn hasher<S>(self, hasher: S) -> HashSetBuilder<K, S> { |
67 | 0 | HashSetBuilder { |
68 | 0 | hasher, |
69 | 0 | capacity: self.capacity, |
70 | 0 | collector: self.collector, |
71 | 0 | resize_mode: self.resize_mode, |
72 | 0 | _kv: PhantomData, |
73 | 0 | } |
74 | 0 | } |
75 | | } |
76 | | |
77 | | impl<K, S> HashSetBuilder<K, S> { |
78 | | /// Set the initial capacity of the set. |
79 | | /// |
80 | | /// The set should be able to hold at least `capacity` elements before resizing. |
81 | | /// However, the capacity is an estimate, and the set may prematurely resize due |
82 | | /// to poor hash distribution. If `capacity` is 0, the hash set will not allocate. |
83 | 0 | pub fn capacity(self, capacity: usize) -> HashSetBuilder<K, S> { |
84 | 0 | HashSetBuilder { |
85 | 0 | capacity, |
86 | 0 | hasher: self.hasher, |
87 | 0 | collector: self.collector, |
88 | 0 | resize_mode: self.resize_mode, |
89 | 0 | _kv: PhantomData, |
90 | 0 | } |
91 | 0 | } |
92 | | |
93 | | /// Set the resizing mode of the set. See [`ResizeMode`] for details. |
94 | 0 | pub fn resize_mode(self, resize_mode: ResizeMode) -> Self { |
95 | 0 | HashSetBuilder { |
96 | 0 | resize_mode, |
97 | 0 | hasher: self.hasher, |
98 | 0 | capacity: self.capacity, |
99 | 0 | collector: self.collector, |
100 | 0 | _kv: PhantomData, |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | | /// Set the [`seize::Collector`] used for garbage collection. |
105 | | /// |
106 | | /// This method may be useful when you want more control over garbage collection. |
107 | | /// |
108 | | /// Note that all `Guard` references used to access the set must be produced by |
109 | | /// the provided `collector`. |
110 | 0 | pub fn collector(self, collector: Collector) -> Self { |
111 | 0 | HashSetBuilder { |
112 | 0 | collector, |
113 | 0 | hasher: self.hasher, |
114 | 0 | capacity: self.capacity, |
115 | 0 | resize_mode: self.resize_mode, |
116 | 0 | _kv: PhantomData, |
117 | 0 | } |
118 | 0 | } |
119 | | |
120 | | /// Construct a [`HashSet`] from the builder, using the configured options. |
121 | 0 | pub fn build(self) -> HashSet<K, S> { |
122 | 0 | HashSet { |
123 | 0 | raw: raw::HashMap::new(self.capacity, self.hasher, self.collector, self.resize_mode), |
124 | 0 | } |
125 | 0 | } |
126 | | } |
127 | | |
128 | | impl<K, S> fmt::Debug for HashSetBuilder<K, S> { |
129 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
130 | 0 | f.debug_struct("HashSetBuilder") |
131 | 0 | .field("capacity", &self.capacity) |
132 | 0 | .field("collector", &self.collector) |
133 | 0 | .field("resize_mode", &self.resize_mode) |
134 | 0 | .finish() |
135 | 0 | } |
136 | | } |
137 | | |
138 | | impl<K> HashSet<K> { |
139 | | /// Creates an empty `HashSet`. |
140 | | /// |
141 | | /// The hash map is initially created with a capacity of 0, so it will not allocate |
142 | | /// until it is first inserted into. |
143 | | /// |
144 | | /// # Examples |
145 | | /// |
146 | | /// ``` |
147 | | /// use papaya::HashSet; |
148 | | /// let map: HashSet<&str> = HashSet::new(); |
149 | | /// ``` |
150 | 87 | pub fn new() -> HashSet<K> { |
151 | 87 | HashSet::with_capacity_and_hasher(0, RandomState::new()) |
152 | 87 | } <papaya::set::HashSet<bytes::bytes::Bytes>>::new Line | Count | Source | 150 | 87 | pub fn new() -> HashSet<K> { | 151 | 87 | HashSet::with_capacity_and_hasher(0, RandomState::new()) | 152 | 87 | } |
Unexecuted instantiation: <papaya::set::HashSet<_>>::new |
153 | | |
154 | | /// Creates an empty `HashSet` with the specified capacity. |
155 | | /// |
156 | | /// The set should be able to hold at least `capacity` elements before resizing. |
157 | | /// However, the capacity is an estimate, and the set may prematurely resize due |
158 | | /// to poor hash distribution. If `capacity` is 0, the hash set will not allocate. |
159 | | /// |
160 | | /// # Examples |
161 | | /// |
162 | | /// ``` |
163 | | /// use papaya::HashSet; |
164 | | /// let set: HashSet<&str> = HashSet::with_capacity(10); |
165 | | /// ``` |
166 | 0 | pub fn with_capacity(capacity: usize) -> HashSet<K> { |
167 | 0 | HashSet::with_capacity_and_hasher(capacity, RandomState::new()) |
168 | 0 | } |
169 | | |
170 | | /// Returns a builder for a `HashSet`. |
171 | | /// |
172 | | /// The builder can be used for more complex configuration, such as using |
173 | | /// a custom [`Collector`], or [`ResizeMode`]. |
174 | 0 | pub fn builder() -> HashSetBuilder<K> { |
175 | 0 | HashSetBuilder { |
176 | 0 | capacity: 0, |
177 | 0 | hasher: RandomState::default(), |
178 | 0 | collector: Collector::new(), |
179 | 0 | resize_mode: ResizeMode::default(), |
180 | 0 | _kv: PhantomData, |
181 | 0 | } |
182 | 0 | } |
183 | | } |
184 | | |
185 | | impl<K, S> Default for HashSet<K, S> |
186 | | where |
187 | | S: Default, |
188 | | { |
189 | 0 | fn default() -> Self { |
190 | 0 | HashSet::with_hasher(S::default()) |
191 | 0 | } |
192 | | } |
193 | | |
194 | | impl<K, S> HashSet<K, S> { |
195 | | /// Creates an empty `HashSet` which will use the given hash builder to hash |
196 | | /// keys. |
197 | | /// |
198 | | /// Warning: `hash_builder` is normally randomly generated, and is designed |
199 | | /// to allow HashSets to be resistant to attacks that cause many collisions |
200 | | /// and very poor performance. Setting it manually using this function can |
201 | | /// expose a DoS attack vector. |
202 | | /// |
203 | | /// The `hash_builder` passed should implement the [`BuildHasher`] trait for |
204 | | /// the HashSet to be useful, see its documentation for details. |
205 | | /// |
206 | | /// # Examples |
207 | | /// |
208 | | /// ``` |
209 | | /// use papaya::HashSet; |
210 | | /// use std::hash::RandomState; |
211 | | /// |
212 | | /// let s = RandomState::new(); |
213 | | /// let set = HashSet::with_hasher(s); |
214 | | /// set.pin().insert(1); |
215 | | /// ``` |
216 | 0 | pub fn with_hasher(hash_builder: S) -> HashSet<K, S> { |
217 | 0 | HashSet::with_capacity_and_hasher(0, hash_builder) |
218 | 0 | } |
219 | | |
220 | | /// Creates an empty `HashSet` with at least the specified capacity, using |
221 | | /// `hash_builder` to hash the keys. |
222 | | /// |
223 | | /// The set should be able to hold at least `capacity` elements before resizing. |
224 | | /// However, the capacity is an estimate, and the set may prematurely resize due |
225 | | /// to poor hash distribution. If `capacity` is 0, the hash set will not allocate. |
226 | | /// |
227 | | /// Warning: `hash_builder` is normally randomly generated, and is designed |
228 | | /// to allow HashSets to be resistant to attacks that cause many collisions |
229 | | /// and very poor performance. Setting it manually using this function can |
230 | | /// expose a DoS attack vector. |
231 | | /// |
232 | | /// The `hasher` passed should implement the [`BuildHasher`] trait for |
233 | | /// the HashSet to be useful, see its documentation for details. |
234 | | /// |
235 | | /// # Examples |
236 | | /// |
237 | | /// ``` |
238 | | /// use papaya::HashSet; |
239 | | /// use std::hash::RandomState; |
240 | | /// |
241 | | /// let s = RandomState::new(); |
242 | | /// let set = HashSet::with_capacity_and_hasher(10, s); |
243 | | /// set.pin().insert(1); |
244 | | /// ``` |
245 | 87 | pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashSet<K, S> { |
246 | 87 | HashSet { |
247 | 87 | raw: raw::HashMap::new( |
248 | 87 | capacity, |
249 | 87 | hash_builder, |
250 | 87 | Collector::default(), |
251 | 87 | ResizeMode::default(), |
252 | 87 | ), |
253 | 87 | } |
254 | 87 | } <papaya::set::HashSet<bytes::bytes::Bytes>>::with_capacity_and_hasher Line | Count | Source | 245 | 87 | pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashSet<K, S> { | 246 | 87 | HashSet { | 247 | 87 | raw: raw::HashMap::new( | 248 | 87 | capacity, | 249 | 87 | hash_builder, | 250 | 87 | Collector::default(), | 251 | 87 | ResizeMode::default(), | 252 | 87 | ), | 253 | 87 | } | 254 | 87 | } |
Unexecuted instantiation: <papaya::set::HashSet<_, _>>::with_capacity_and_hasher |
255 | | |
256 | | /// Returns a pinned reference to the set. |
257 | | /// |
258 | | /// The returned reference manages a guard internally, preventing garbage collection |
259 | | /// for as long as it is held. See the [crate-level documentation](crate#usage) for details. |
260 | | #[inline] |
261 | 171k | pub fn pin(&self) -> HashSetRef<'_, K, S, LocalGuard<'_>> { |
262 | 171k | HashSetRef { |
263 | 171k | guard: self.raw.guard(), |
264 | 171k | set: self, |
265 | 171k | } |
266 | 171k | } <papaya::set::HashSet<bytes::bytes::Bytes>>::pin Line | Count | Source | 261 | 171k | pub fn pin(&self) -> HashSetRef<'_, K, S, LocalGuard<'_>> { | 262 | 171k | HashSetRef { | 263 | 171k | guard: self.raw.guard(), | 264 | 171k | set: self, | 265 | 171k | } | 266 | 171k | } |
Unexecuted instantiation: <papaya::set::HashSet<_, _>>::pin |
267 | | |
268 | | /// Returns a pinned reference to the set. |
269 | | /// |
270 | | /// Unlike [`HashSet::pin`], the returned reference implements `Send` and `Sync`, |
271 | | /// allowing it to be held across `.await` points in work-stealing schedulers. |
272 | | /// This is especially useful for iterators. |
273 | | /// |
274 | | /// The returned reference manages a guard internally, preventing garbage collection |
275 | | /// for as long as it is held. See the [crate-level documentation](crate#usage) for details. |
276 | | #[inline] |
277 | 0 | pub fn pin_owned(&self) -> HashSetRef<'_, K, S, OwnedGuard<'_>> { |
278 | 0 | HashSetRef { |
279 | 0 | guard: self.raw.owned_guard(), |
280 | 0 | set: self, |
281 | 0 | } |
282 | 0 | } |
283 | | |
284 | | /// Returns a guard for use with this set. |
285 | | /// |
286 | | /// Note that holding on to a guard prevents garbage collection. |
287 | | /// See the [crate-level documentation](crate#usage) for details. |
288 | | #[inline] |
289 | 0 | pub fn guard(&self) -> LocalGuard<'_> { |
290 | 0 | self.raw.collector().enter() |
291 | 0 | } |
292 | | |
293 | | /// Returns an owned guard for use with this set. |
294 | | /// |
295 | | /// Owned guards implement `Send` and `Sync`, allowing them to be held across |
296 | | /// `.await` points in work-stealing schedulers. This is especially useful |
297 | | /// for iterators. |
298 | | /// |
299 | | /// Note that holding on to a guard prevents garbage collection. |
300 | | /// See the [crate-level documentation](crate#usage) for details. |
301 | | #[inline] |
302 | 0 | pub fn owned_guard(&self) -> OwnedGuard<'_> { |
303 | 0 | self.raw.collector().enter_owned() |
304 | 0 | } |
305 | | } |
306 | | |
307 | | impl<K, S> HashSet<K, S> |
308 | | where |
309 | | K: Hash + Eq, |
310 | | S: BuildHasher, |
311 | | { |
312 | | /// Returns the number of entries in the set. |
313 | | /// |
314 | | /// # Examples |
315 | | /// |
316 | | /// ``` |
317 | | /// use papaya::HashSet; |
318 | | /// |
319 | | /// let set = HashSet::new(); |
320 | | /// |
321 | | /// set.pin().insert(1); |
322 | | /// set.pin().insert(2); |
323 | | /// assert!(set.len() == 2); |
324 | | /// ``` |
325 | | #[inline] |
326 | 0 | pub fn len(&self) -> usize { |
327 | 0 | self.raw.len() |
328 | 0 | } |
329 | | |
330 | | /// Returns `true` if the set is empty. Otherwise returns `false`. |
331 | | /// |
332 | | /// # Examples |
333 | | /// |
334 | | /// ``` |
335 | | /// use papaya::HashSet; |
336 | | /// |
337 | | /// let set = HashSet::new(); |
338 | | /// assert!(set.is_empty()); |
339 | | /// set.pin().insert("a"); |
340 | | /// assert!(!set.is_empty()); |
341 | | /// ``` |
342 | | #[inline] |
343 | 0 | pub fn is_empty(&self) -> bool { |
344 | 0 | self.len() == 0 |
345 | 0 | } |
346 | | |
347 | | /// Returns `true` if the set contains a value for the specified key. |
348 | | /// |
349 | | /// The key may be any borrowed form of the set's key type, but |
350 | | /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for |
351 | | /// the key type. |
352 | | /// |
353 | | /// [`Eq`]: std::cmp::Eq |
354 | | /// [`Hash`]: std::hash::Hash |
355 | | /// |
356 | | /// |
357 | | /// # Examples |
358 | | /// |
359 | | /// ``` |
360 | | /// use papaya::HashSet; |
361 | | /// |
362 | | /// let set = HashSet::new(); |
363 | | /// set.pin().insert(1); |
364 | | /// assert_eq!(set.pin().contains(&1), true); |
365 | | /// assert_eq!(set.pin().contains(&2), false); |
366 | | /// ``` |
367 | | #[inline] |
368 | 0 | pub fn contains<Q>(&self, key: &Q, guard: &impl Guard) -> bool |
369 | 0 | where |
370 | 0 | Q: Equivalent<K> + Hash + ?Sized, |
371 | | { |
372 | 0 | self.get(key, self.raw.verify(guard)).is_some() |
373 | 0 | } |
374 | | |
375 | | /// Returns a reference to the value corresponding to the key. |
376 | | /// |
377 | | /// The key may be any borrowed form of the set's key type, but |
378 | | /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for |
379 | | /// the key type. |
380 | | /// |
381 | | /// [`Eq`]: std::cmp::Eq |
382 | | /// [`Hash`]: std::hash::Hash |
383 | | /// |
384 | | /// # Examples |
385 | | /// |
386 | | /// ``` |
387 | | /// use papaya::HashSet; |
388 | | /// |
389 | | /// let set = HashSet::new(); |
390 | | /// set.pin().insert(1); |
391 | | /// assert_eq!(set.pin().get(&1), Some(&1)); |
392 | | /// assert_eq!(set.pin().get(&2), None); |
393 | | /// ``` |
394 | | #[inline] |
395 | 0 | pub fn get<'g, Q>(&self, key: &Q, guard: &'g impl Guard) -> Option<&'g K> |
396 | 0 | where |
397 | 0 | Q: Equivalent<K> + Hash + ?Sized, |
398 | | { |
399 | 0 | match self.raw.get(key, self.raw.verify(guard)) { |
400 | 0 | Some((key, _)) => Some(key), |
401 | 0 | None => None, |
402 | | } |
403 | 0 | } |
404 | | |
405 | | /// Inserts a value into the set. |
406 | | /// |
407 | | /// If the set did not have this key present, `true` is returned. |
408 | | /// |
409 | | /// If the set did have this key present, `false` is returned and the old |
410 | | /// value is not updated. This matters for types that can be `==` without |
411 | | /// being identical. See the [standard library documentation] for details. |
412 | | /// |
413 | | /// [standard library documentation]: https://doc.rust-lang.org/std/collections/index.html#insert-and-complex-keys |
414 | | /// |
415 | | /// # Examples |
416 | | /// |
417 | | /// ``` |
418 | | /// use papaya::HashSet; |
419 | | /// |
420 | | /// let set = HashSet::new(); |
421 | | /// assert_eq!(set.pin().insert(37), true); |
422 | | /// assert_eq!(set.pin().is_empty(), false); |
423 | | /// |
424 | | /// set.pin().insert(37); |
425 | | /// assert_eq!(set.pin().insert(37), false); |
426 | | /// assert_eq!(set.pin().get(&37), Some(&37)); |
427 | | /// ``` |
428 | | #[inline] |
429 | 0 | pub fn insert(&self, key: K, guard: &impl Guard) -> bool { |
430 | 0 | match self.raw.insert(key, (), true, self.raw.verify(guard)) { |
431 | 0 | InsertResult::Inserted(_) => true, |
432 | 0 | InsertResult::Replaced(_) => false, |
433 | 0 | InsertResult::Error { .. } => unreachable!(), |
434 | | } |
435 | 0 | } |
436 | | |
437 | | /// Removes a key from the set, returning the value at the key if the key |
438 | | /// was previously in the set. |
439 | | /// |
440 | | /// The key may be any borrowed form of the set's key type, but |
441 | | /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for |
442 | | /// the key type. |
443 | | /// |
444 | | /// # Examples |
445 | | /// |
446 | | /// ``` |
447 | | /// use papaya::HashSet; |
448 | | /// |
449 | | /// let set = HashSet::new(); |
450 | | /// set.pin().insert(1); |
451 | | /// assert_eq!(set.pin().remove(&1), true); |
452 | | /// assert_eq!(set.pin().remove(&1), false); |
453 | | /// ``` |
454 | | #[inline] |
455 | 0 | pub fn remove<Q>(&self, key: &Q, guard: &impl Guard) -> bool |
456 | 0 | where |
457 | 0 | Q: Equivalent<K> + Hash + ?Sized, |
458 | | { |
459 | 0 | match self.raw.remove(key, self.raw.verify(guard)) { |
460 | 0 | Some((_, _)) => true, |
461 | 0 | None => false, |
462 | | } |
463 | 0 | } |
464 | | |
465 | | /// Tries to reserve capacity for `additional` more elements to be inserted |
466 | | /// in the `HashSet`. |
467 | | /// |
468 | | /// After calling this method, the set should be able to hold at least `capacity` elements |
469 | | /// before resizing. However, the capacity is an estimate, and the set may prematurely resize |
470 | | /// due to poor hash distribution. The collection may also reserve more space to avoid frequent |
471 | | /// reallocations. |
472 | | /// |
473 | | /// # Panics |
474 | | /// |
475 | | /// Panics if the new allocation size overflows `usize`. |
476 | | /// |
477 | | /// # Examples |
478 | | /// |
479 | | /// ``` |
480 | | /// use papaya::HashSet; |
481 | | /// |
482 | | /// let set: HashSet<&str> = HashSet::new(); |
483 | | /// set.pin().reserve(10); |
484 | | /// ``` |
485 | | #[inline] |
486 | 0 | pub fn reserve(&self, additional: usize, guard: &impl Guard) { |
487 | 0 | self.raw.reserve(additional, self.raw.verify(guard)) |
488 | 0 | } |
489 | | |
490 | | /// Clears the set, removing all values. |
491 | | /// |
492 | | /// Note that this method will block until any in-progress resizes are |
493 | | /// completed before proceeding. See the [consistency](crate#consistency) |
494 | | /// section for details. |
495 | | /// |
496 | | /// # Examples |
497 | | /// |
498 | | /// ``` |
499 | | /// use papaya::HashSet; |
500 | | /// |
501 | | /// let set = HashSet::new(); |
502 | | /// |
503 | | /// set.pin().insert(1); |
504 | | /// set.pin().clear(); |
505 | | /// assert!(set.pin().is_empty()); |
506 | | /// ``` |
507 | | #[inline] |
508 | 0 | pub fn clear(&self, guard: &impl Guard) { |
509 | 0 | self.raw.clear(self.raw.verify(guard)) |
510 | 0 | } |
511 | | |
512 | | /// Retains only the elements specified by the predicate. |
513 | | /// |
514 | | /// In other words, remove all values `v` for which `f(&v)` returns `false`. |
515 | | /// The elements are visited in unsorted (and unspecified) order. |
516 | | /// |
517 | | /// Note the function may be called more than once for a given key if its value is |
518 | | /// concurrently modified during removal. |
519 | | /// |
520 | | /// Additionally, this method will block until any in-progress resizes are |
521 | | /// completed before proceeding. See the [consistency](crate#consistency) |
522 | | /// section for details. |
523 | | /// |
524 | | /// # Examples |
525 | | /// |
526 | | /// ``` |
527 | | /// use papaya::HashSet; |
528 | | /// |
529 | | /// let mut set: HashSet<i32> = (0..8).collect(); |
530 | | /// set.pin().retain(|&v| v % 2 == 0); |
531 | | /// assert_eq!(set.len(), 4); |
532 | | /// assert_eq!(set.pin().contains(&1), false); |
533 | | /// assert_eq!(set.pin().contains(&2), true); |
534 | | /// ``` |
535 | | #[inline] |
536 | 0 | pub fn retain<F>(&mut self, mut f: F, guard: &impl Guard) |
537 | 0 | where |
538 | 0 | F: FnMut(&K) -> bool, |
539 | | { |
540 | 0 | self.raw.retain(|k, _| f(k), self.raw.verify(guard)) |
541 | 0 | } |
542 | | |
543 | | /// An iterator visiting all values in arbitrary order. |
544 | | /// |
545 | | /// Note that this method will block until any in-progress resizes are |
546 | | /// completed before proceeding. See the [consistency](crate#consistency) |
547 | | /// section for details. |
548 | | /// |
549 | | /// # Examples |
550 | | /// |
551 | | /// ``` |
552 | | /// use papaya::HashSet; |
553 | | /// |
554 | | /// let set = HashSet::from([ |
555 | | /// "a", |
556 | | /// "b", |
557 | | /// "c" |
558 | | /// ]); |
559 | | /// |
560 | | /// for val in set.pin().iter() { |
561 | | /// println!("val: {val}"); |
562 | | /// } |
563 | | #[inline] |
564 | 0 | pub fn iter<'g, G>(&self, guard: &'g G) -> Iter<'g, K, G> |
565 | 0 | where |
566 | 0 | G: Guard, |
567 | | { |
568 | 0 | Iter { |
569 | 0 | raw: self.raw.iter(self.raw.verify(guard)), |
570 | 0 | } |
571 | 0 | } |
572 | | } |
573 | | |
574 | | impl<K, S> PartialEq for HashSet<K, S> |
575 | | where |
576 | | K: Hash + Eq, |
577 | | S: BuildHasher, |
578 | | { |
579 | 0 | fn eq(&self, other: &Self) -> bool { |
580 | 0 | if self.len() != other.len() { |
581 | 0 | return false; |
582 | 0 | } |
583 | | |
584 | 0 | let (guard1, guard2) = (&self.guard(), &other.guard()); |
585 | | |
586 | 0 | let mut iter = self.iter(guard1); |
587 | 0 | iter.all(|key| other.get(key, guard2).is_some()) |
588 | 0 | } |
589 | | } |
590 | | |
591 | | impl<K, S> Eq for HashSet<K, S> |
592 | | where |
593 | | K: Hash + Eq, |
594 | | S: BuildHasher, |
595 | | { |
596 | | } |
597 | | |
598 | | impl<K, S> fmt::Debug for HashSet<K, S> |
599 | | where |
600 | | K: Hash + Eq + fmt::Debug, |
601 | | S: BuildHasher, |
602 | | { |
603 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
604 | 0 | let guard = self.guard(); |
605 | 0 | f.debug_set().entries(self.iter(&guard)).finish() |
606 | 0 | } |
607 | | } |
608 | | |
609 | | impl<K, S> Extend<K> for &HashSet<K, S> |
610 | | where |
611 | | K: Hash + Eq, |
612 | | S: BuildHasher, |
613 | | { |
614 | 0 | fn extend<T: IntoIterator<Item = K>>(&mut self, iter: T) { |
615 | | // from `hashbrown::HashSet::extend`: |
616 | | // Keys may be already present or show multiple times in the iterator. |
617 | | // Reserve the entire hint lower bound if the set is empty. |
618 | | // Otherwise reserve half the hint (rounded up), so the set |
619 | | // will only resize twice in the worst case. |
620 | 0 | let iter = iter.into_iter(); |
621 | 0 | let reserve = if self.is_empty() { |
622 | 0 | iter.size_hint().0 |
623 | | } else { |
624 | 0 | (iter.size_hint().0 + 1) / 2 |
625 | | }; |
626 | | |
627 | 0 | let guard = self.guard(); |
628 | 0 | self.reserve(reserve, &guard); |
629 | | |
630 | 0 | for key in iter { |
631 | 0 | self.insert(key, &guard); |
632 | 0 | } |
633 | 0 | } |
634 | | } |
635 | | |
636 | | impl<'a, K, S> Extend<&'a K> for &HashSet<K, S> |
637 | | where |
638 | | K: Copy + Hash + Eq + 'a, |
639 | | S: BuildHasher, |
640 | | { |
641 | 0 | fn extend<T: IntoIterator<Item = &'a K>>(&mut self, iter: T) { |
642 | 0 | self.extend(iter.into_iter().copied()); |
643 | 0 | } |
644 | | } |
645 | | |
646 | | impl<K, const N: usize> From<[K; N]> for HashSet<K, RandomState> |
647 | | where |
648 | | K: Hash + Eq, |
649 | | { |
650 | 0 | fn from(arr: [K; N]) -> Self { |
651 | 0 | HashSet::from_iter(arr) |
652 | 0 | } |
653 | | } |
654 | | |
655 | | impl<K, S> FromIterator<K> for HashSet<K, S> |
656 | | where |
657 | | K: Hash + Eq, |
658 | | S: BuildHasher + Default, |
659 | | { |
660 | 0 | fn from_iter<T: IntoIterator<Item = K>>(iter: T) -> Self { |
661 | 0 | let mut iter = iter.into_iter(); |
662 | | |
663 | 0 | if let Some(key) = iter.next() { |
664 | 0 | let (lower, _) = iter.size_hint(); |
665 | 0 | let set = HashSet::with_capacity_and_hasher(lower.saturating_add(1), S::default()); |
666 | | |
667 | | // Ideally we could use an unprotected guard here. However, `insert` |
668 | | // returns references to values that were replaced and retired, so |
669 | | // we need a "real" guard. A `raw_insert` method that strictly returns |
670 | | // pointers would fix this. |
671 | | { |
672 | 0 | let set = set.pin(); |
673 | 0 | set.insert(key); |
674 | 0 | for key in iter { |
675 | 0 | set.insert(key); |
676 | 0 | } |
677 | | } |
678 | | |
679 | 0 | set |
680 | | } else { |
681 | 0 | Self::default() |
682 | | } |
683 | 0 | } |
684 | | } |
685 | | |
686 | | impl<K, S> Clone for HashSet<K, S> |
687 | | where |
688 | | K: Clone + Hash + Eq, |
689 | | S: BuildHasher + Clone, |
690 | | { |
691 | 0 | fn clone(&self) -> HashSet<K, S> { |
692 | 0 | let other = HashSet::builder() |
693 | 0 | .capacity(self.len()) |
694 | 0 | .hasher(self.raw.hasher.clone()) |
695 | 0 | .collector(seize::Collector::new()) |
696 | 0 | .build(); |
697 | | |
698 | | { |
699 | 0 | let (guard1, guard2) = (&self.guard(), &other.guard()); |
700 | 0 | for key in self.iter(guard1) { |
701 | 0 | other.insert(key.clone(), guard2); |
702 | 0 | } |
703 | | } |
704 | | |
705 | 0 | other |
706 | 0 | } |
707 | | } |
708 | | |
709 | | /// A pinned reference to a [`HashSet`]. |
710 | | /// |
711 | | /// This type is created with [`HashSet::pin`] and can be used to easily access a [`HashSet`] |
712 | | /// without explicitly managing a guard. See the [crate-level documentation](crate#usage) for details. |
713 | | pub struct HashSetRef<'set, K, S, G> { |
714 | | guard: MapGuard<G>, |
715 | | set: &'set HashSet<K, S>, |
716 | | } |
717 | | |
718 | | impl<'set, K, S, G> HashSetRef<'set, K, S, G> |
719 | | where |
720 | | K: Hash + Eq, |
721 | | S: BuildHasher, |
722 | | G: Guard, |
723 | | { |
724 | | /// Returns a reference to the inner [`HashSet`]. |
725 | | #[inline] |
726 | 0 | pub fn set(&self) -> &'set HashSet<K, S> { |
727 | 0 | self.set |
728 | 0 | } |
729 | | |
730 | | /// Returns the number of entries in the set. |
731 | | /// |
732 | | /// See [`HashSet::len`] for details. |
733 | | #[inline] |
734 | 0 | pub fn len(&self) -> usize { |
735 | 0 | self.set.raw.len() |
736 | 0 | } Unexecuted instantiation: <papaya::set::HashSetRef<bytes::bytes::Bytes, std::hash::random::RandomState, seize::guard::LocalGuard>>::len Unexecuted instantiation: <papaya::set::HashSetRef<_, _, _>>::len |
737 | | |
738 | | /// Returns `true` if the set is empty. Otherwise returns `false`. |
739 | | /// |
740 | | /// See [`HashSet::is_empty`] for details. |
741 | | #[inline] |
742 | 0 | pub fn is_empty(&self) -> bool { |
743 | 0 | self.len() == 0 |
744 | 0 | } Unexecuted instantiation: <papaya::set::HashSetRef<bytes::bytes::Bytes, std::hash::random::RandomState, seize::guard::LocalGuard>>::is_empty Unexecuted instantiation: <papaya::set::HashSetRef<_, _, _>>::is_empty |
745 | | |
746 | | /// Returns `true` if the set contains a value for the specified key. |
747 | | /// |
748 | | /// See [`HashSet::contains`] for details. |
749 | | #[inline] |
750 | 0 | pub fn contains<Q>(&self, key: &Q) -> bool |
751 | 0 | where |
752 | 0 | Q: Equivalent<K> + Hash + ?Sized, |
753 | | { |
754 | 0 | self.get(key).is_some() |
755 | 0 | } Unexecuted instantiation: <papaya::set::HashSetRef<bytes::bytes::Bytes, std::hash::random::RandomState, seize::guard::LocalGuard>>::contains::<[u8]> Unexecuted instantiation: <papaya::set::HashSetRef<bytes::bytes::Bytes, std::hash::random::RandomState, seize::guard::LocalGuard>>::contains::<bytes::bytes::Bytes> Unexecuted instantiation: <papaya::set::HashSetRef<_, _, _>>::contains::<_> |
756 | | |
757 | | /// Returns a reference to the value corresponding to the key. |
758 | | /// |
759 | | /// See [`HashSet::get`] for details. |
760 | | #[inline] |
761 | 0 | pub fn get<Q>(&self, key: &Q) -> Option<&K> |
762 | 0 | where |
763 | 0 | Q: Equivalent<K> + Hash + ?Sized, |
764 | | { |
765 | 0 | match self.set.raw.get(key, &self.guard) { |
766 | 0 | Some((k, _)) => Some(k), |
767 | 0 | None => None, |
768 | | } |
769 | 0 | } Unexecuted instantiation: <papaya::set::HashSetRef<bytes::bytes::Bytes, std::hash::random::RandomState, seize::guard::LocalGuard>>::get::<[u8]> Unexecuted instantiation: <papaya::set::HashSetRef<bytes::bytes::Bytes, std::hash::random::RandomState, seize::guard::LocalGuard>>::get::<bytes::bytes::Bytes> Unexecuted instantiation: <papaya::set::HashSetRef<_, _, _>>::get::<_> |
770 | | |
771 | | /// Inserts a key-value pair into the set. |
772 | | /// |
773 | | /// See [`HashSet::insert`] for details. |
774 | | #[inline] |
775 | 0 | pub fn insert(&self, key: K) -> bool { |
776 | 0 | match self.set.raw.insert(key, (), true, &self.guard) { |
777 | 0 | InsertResult::Inserted(_) => true, |
778 | 0 | InsertResult::Replaced(_) => false, |
779 | 0 | InsertResult::Error { .. } => unreachable!(), |
780 | | } |
781 | 0 | } Unexecuted instantiation: <papaya::set::HashSetRef<bytes::bytes::Bytes, std::hash::random::RandomState, seize::guard::LocalGuard>>::insert Unexecuted instantiation: <papaya::set::HashSetRef<_, _, _>>::insert |
782 | | |
783 | | /// Removes a key from the set, returning the value at the key if the key |
784 | | /// was previously in the set. |
785 | | /// |
786 | | /// See [`HashSet::remove`] for details. |
787 | | #[inline] |
788 | 0 | pub fn remove<Q>(&self, key: &Q) -> bool |
789 | 0 | where |
790 | 0 | Q: Equivalent<K> + Hash + ?Sized, |
791 | | { |
792 | 0 | match self.set.raw.remove(key, &self.guard) { |
793 | 0 | Some((_, _)) => true, |
794 | 0 | None => false, |
795 | | } |
796 | 0 | } |
797 | | |
798 | | /// Clears the set, removing all values. |
799 | | /// |
800 | | /// See [`HashSet::clear`] for details. |
801 | | #[inline] |
802 | 171k | pub fn clear(&self) { |
803 | 171k | self.set.raw.clear(&self.guard) |
804 | 171k | } <papaya::set::HashSetRef<bytes::bytes::Bytes, std::hash::random::RandomState, seize::guard::LocalGuard>>::clear Line | Count | Source | 802 | 171k | pub fn clear(&self) { | 803 | 171k | self.set.raw.clear(&self.guard) | 804 | 171k | } |
Unexecuted instantiation: <papaya::set::HashSetRef<_, _, _>>::clear |
805 | | |
806 | | /// Retains only the elements specified by the predicate. |
807 | | /// |
808 | | /// See [`HashSet::retain`] for details. |
809 | | #[inline] |
810 | 0 | pub fn retain<F>(&mut self, mut f: F) |
811 | 0 | where |
812 | 0 | F: FnMut(&K) -> bool, |
813 | | { |
814 | 0 | self.set.raw.retain(|k, _| f(k), &self.guard) |
815 | 0 | } |
816 | | |
817 | | /// Tries to reserve capacity for `additional` more elements to be inserted |
818 | | /// in the set. |
819 | | /// |
820 | | /// See [`HashSet::reserve`] for details. |
821 | | #[inline] |
822 | 0 | pub fn reserve(&self, additional: usize) { |
823 | 0 | self.set.raw.reserve(additional, &self.guard) |
824 | 0 | } |
825 | | |
826 | | /// An iterator visiting all values in arbitrary order. |
827 | | /// The iterator element type is `(&K, &V)`. |
828 | | /// |
829 | | /// See [`HashSet::iter`] for details. |
830 | | #[inline] |
831 | 0 | pub fn iter(&self) -> Iter<'_, K, G> { |
832 | 0 | Iter { |
833 | 0 | raw: self.set.raw.iter(&self.guard), |
834 | 0 | } |
835 | 0 | } Unexecuted instantiation: <papaya::set::HashSetRef<bytes::bytes::Bytes, std::hash::random::RandomState, seize::guard::LocalGuard>>::iter Unexecuted instantiation: <papaya::set::HashSetRef<_, _, _>>::iter |
836 | | } |
837 | | |
838 | | impl<K, S, G> fmt::Debug for HashSetRef<'_, K, S, G> |
839 | | where |
840 | | K: Hash + Eq + fmt::Debug, |
841 | | S: BuildHasher, |
842 | | G: Guard, |
843 | | { |
844 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
845 | 0 | f.debug_set().entries(self.iter()).finish() |
846 | 0 | } |
847 | | } |
848 | | |
849 | | impl<'a, K, S, G> IntoIterator for &'a HashSetRef<'_, K, S, G> |
850 | | where |
851 | | K: Hash + Eq, |
852 | | S: BuildHasher, |
853 | | G: Guard, |
854 | | { |
855 | | type Item = &'a K; |
856 | | type IntoIter = Iter<'a, K, G>; |
857 | | |
858 | 0 | fn into_iter(self) -> Self::IntoIter { |
859 | 0 | self.iter() |
860 | 0 | } |
861 | | } |
862 | | |
863 | | /// An iterator over a set's entries. |
864 | | /// |
865 | | /// This struct is created by the [`iter`](HashSet::iter) method on [`HashSet`]. See its documentation for details. |
866 | | pub struct Iter<'g, K, G> { |
867 | | raw: raw::Iter<'g, K, (), MapGuard<G>>, |
868 | | } |
869 | | |
870 | | impl<'g, K: 'g, G> Iterator for Iter<'g, K, G> |
871 | | where |
872 | | G: Guard, |
873 | | { |
874 | | type Item = &'g K; |
875 | | |
876 | | #[inline] |
877 | 0 | fn next(&mut self) -> Option<Self::Item> { |
878 | 0 | self.raw.next().map(|(k, _)| k) |
879 | 0 | } Unexecuted instantiation: <papaya::set::Iter<bytes::bytes::Bytes, seize::guard::LocalGuard> as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <papaya::set::Iter<_, _> as core::iter::traits::iterator::Iterator>::next |
880 | | } |
881 | | |
882 | | impl<K, G> fmt::Debug for Iter<'_, K, G> |
883 | | where |
884 | | K: fmt::Debug, |
885 | | G: Guard, |
886 | | { |
887 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
888 | 0 | f.debug_list() |
889 | 0 | .entries(Iter { |
890 | 0 | raw: self.raw.clone(), |
891 | 0 | }) |
892 | 0 | .finish() |
893 | 0 | } |
894 | | } |