once_map/
sync.rs

1use crate::{map, map::HashMap, Equivalent, InfallibleResult, ToOwnedEquivalent};
2use alloc::boxed::Box;
3use core::{
4    borrow::Borrow,
5    fmt,
6    hash::{BuildHasher, Hash, Hasher},
7    ptr::NonNull,
8};
9use parking_lot::{Condvar, Mutex, MutexGuard, RwLock};
10#[cfg(feature = "rayon")]
11use rayon::prelude::*;
12#[cfg(feature = "serde")]
13use serde_core as serde;
14use stable_deref_trait::StableDeref;
15
16#[cfg(feature = "std")]
17#[inline]
18fn default_shards_amount() -> usize {
19    use std::{
20        sync::atomic::{AtomicUsize, Ordering},
21        thread::available_parallelism,
22    };
23
24    // We want to cache the result to compute it only once
25    static N_SHARDS: AtomicUsize = AtomicUsize::new(0);
26
27    #[cold]
28    fn load_slow() -> usize {
29        // This is racy but that's fine
30        let n = available_parallelism()
31            .ok()
32            .and_then(|n| n.get().checked_next_power_of_two())
33            .and_then(|n| n.checked_mul(4))
34            .unwrap_or(16);
35        N_SHARDS.store(n, Ordering::Relaxed);
36        n
37    }
38
39    let n = N_SHARDS.load(Ordering::Relaxed);
40    if n != 0 {
41        return n;
42    }
43
44    load_slow()
45}
46
47#[cfg(not(feature = "std"))]
48#[inline]
49fn default_shards_amount() -> usize {
50    32
51}
52
53unsafe fn extend_lifetime<'a, T: StableDeref>(ptr: &T) -> &'a T::Target {
54    &*(&**ptr as *const T::Target)
55}
56
57struct ValidPtr<T>(NonNull<T>);
58
59unsafe impl<T: Send> Send for ValidPtr<T> {}
60unsafe impl<T: Sync> Sync for ValidPtr<T> {}
61
62impl<T> core::ops::Deref for ValidPtr<T> {
63    type Target = T;
64
65    fn deref(&self) -> &T {
66        unsafe { self.0.as_ref() }
67    }
68}
69
70impl<T> Clone for ValidPtr<T> {
71    fn clone(&self) -> Self {
72        *self
73    }
74}
75
76impl<T> Copy for ValidPtr<T> {}
77
78impl<T> Borrow<T> for ValidPtr<T> {
79    fn borrow(&self) -> &T {
80        self
81    }
82}
83
84impl<T: Hash> Hash for ValidPtr<T> {
85    fn hash<H: Hasher>(&self, state: &mut H) {
86        (**self).hash(state);
87    }
88}
89
90impl<T: PartialEq> PartialEq for ValidPtr<T> {
91    fn eq(&self, other: &Self) -> bool {
92        **self == **other
93    }
94}
95
96impl<T: Eq> Eq for ValidPtr<T> {}
97
98/// Looks like a Condvar, but wait for all notified threads to wake up when
99/// calling `notify_all`.
100struct WaitingBarrier {
101    condvar: Condvar,
102    n_waiters: Mutex<usize>,
103}
104
105struct Waiter<'a> {
106    guard: MutexGuard<'a, usize>,
107    condvar: &'a Condvar,
108}
109
110impl WaitingBarrier {
111    fn new() -> Self {
112        Self {
113            condvar: Condvar::new(),
114            n_waiters: Mutex::new(0),
115        }
116    }
117
118    /// Registers ourselves as willing to wait
119    fn prepare_waiting(&self) -> Waiter<'_> {
120        let mut guard = self.n_waiters.lock();
121        *guard += 1;
122        Waiter {
123            guard,
124            condvar: &self.condvar,
125        }
126    }
127
128    /// Notifies all waiters and wait for them to wake up
129    fn notify_all(&self) {
130        let mut n = self.n_waiters.lock();
131        self.condvar.notify_all();
132        while *n != 0 {
133            self.condvar.wait(&mut n);
134        }
135    }
136}
137
138impl Waiter<'_> {
139    fn wait(mut self) {
140        self.condvar.wait(&mut self.guard);
141    }
142}
143
144impl Drop for Waiter<'_> {
145    fn drop(&mut self) {
146        *self.guard -= 1;
147        if *self.guard == 0 {
148            self.condvar.notify_one();
149        }
150    }
151}
152
153struct BarrierGuard<'a>(&'a WaitingBarrier);
154
155impl Drop for BarrierGuard<'_> {
156    fn drop(&mut self) {
157        self.0.notify_all();
158    }
159}
160
161type Waiters<K> = Mutex<HashMap<ValidPtr<K>, ValidPtr<WaitingBarrier>>>;
162
163struct WaitersGuard<'a, K: Eq + Hash> {
164    waiters: &'a Waiters<K>,
165    key: &'a K,
166    hash: u64,
167}
168
169impl<K: Eq + Hash> Drop for WaitersGuard<'_, K> {
170    fn drop(&mut self) {
171        let mut writing = self.waiters.lock();
172        writing.remove(self.hash, self.key);
173    }
174}
175
176#[repr(align(64))]
177struct Shard<K, V> {
178    map: RwLock<HashMap<K, V>>,
179
180    // This lock should always be taken after `map`
181    waiters: Waiters<K>,
182}
183
184impl<K, V> Shard<K, V> {
185    fn new() -> Self {
186        Self {
187            map: RwLock::new(HashMap::new()),
188            waiters: Mutex::new(HashMap::new()),
189        }
190    }
191}
192
193impl<K, V> Shard<K, V>
194where
195    K: Hash + Eq,
196{
197    fn get<Q, T>(&self, hash: u64, key: &Q, with_result: impl FnOnce(&K, &V) -> T) -> Option<T>
198    where
199        Q: Hash + Equivalent<K> + ?Sized,
200    {
201        let this = self.map.read();
202        let (k, v) = this.get_key_value(hash, key)?;
203        Some(with_result(k, v))
204    }
205
206    fn try_get<Q, G, T, U>(&self, hash: u64, key: &Q, data: T, with_result: G) -> Result<U, (T, G)>
207    where
208        Q: Hash + Equivalent<K> + ?Sized,
209        G: FnOnce(T, &K, &V) -> U,
210    {
211        let this = self.map.read();
212        match this.get_key_value(hash, key) {
213            Some((k, v)) => Ok(with_result(data, k, v)),
214            None => Err((data, with_result)),
215        }
216    }
217
218    #[cold]
219    fn get_or_try_insert<E, T, U>(
220        &self,
221        hash: u64,
222        key: K,
223        data: T,
224        hasher: &impl BuildHasher,
225        on_vacant: impl FnOnce(T, &K) -> Result<(V, U), E>,
226        on_occupied: impl FnOnce(T, &K, &V) -> U,
227    ) -> Result<U, E> {
228        let barrier = WaitingBarrier::new();
229
230        loop {
231            // If a value already exists, we're done
232            let map = self.map.read();
233            if let Some((key, value)) = map.get_key_value(hash, &key) {
234                return Ok(on_occupied(data, key, value));
235            }
236
237            // Else try to register ourselves as willing to write
238            let mut writing = self.waiters.lock();
239
240            drop(map);
241
242            match writing.entry(hash, &key, hasher) {
243                map::Entry::Occupied(entry) => {
244                    // Somebody is already writing this value ! Wait until it
245                    // is done, then start again.
246
247                    // Safety: We call `prepare_wait` before dropping the mutex
248                    // guard, so the barrier is guaranteed to be valid for the
249                    // wait even if it was removed from the map.
250                    let barrier = unsafe { entry.get().0.as_ref() };
251                    let waiter = barrier.prepare_waiting();
252
253                    // Ensure that other threads will be able to use the mutex
254                    // while we wait for the value's writing to complete
255                    drop(writing);
256                    waiter.wait();
257                    continue;
258                }
259                map::Entry::Vacant(entry) => {
260                    // We're the first ! Register our barrier so other can wait
261                    // on it.
262                    let key_ref = ValidPtr(NonNull::from(&key));
263                    let barrier_ref = ValidPtr(NonNull::from(&barrier));
264                    entry.insert(key_ref, barrier_ref);
265                    break;
266                }
267            }
268        }
269
270        // We know that are we know that we are the only one reaching this point
271        // for this key
272
273        // Now that our barrier is shared, some other thread might wait on it
274        // even if it is removed from `self.waiters.tokens`, so we make sure
275        // that we don't leave this function while someone still thinks the
276        // barrier is alive.
277        let _barrier_guard = BarrierGuard(&barrier);
278        let guard = WaitersGuard {
279            waiters: &self.waiters,
280            key: &key,
281            hash,
282        };
283
284        // It is important not to hold any lock here
285        let (value, ret) = on_vacant(data, &key)?;
286
287        // Take this lock first to avoid deadlocks
288        let mut map = self.map.write();
289
290        // We'll have to move the key to insert it in the map, which will
291        // invalidate the pointer we put in `waiters`, so we remove it now.
292        //
293        // Note that the mutex guard will stay alive until the end of the
294        // function, which is intentional.
295        let mut writing = self.waiters.lock();
296
297        match writing.remove(hash, &key) {
298            Some(b) => debug_assert!(core::ptr::eq(b.0.as_ptr(), &barrier)),
299            None => debug_assert!(false),
300        }
301
302        // We have just done the cleanup manually
303        core::mem::forget(guard);
304
305        // We can finally insert the value in the map.
306        match map.entry(hash, &key, hasher) {
307            map::Entry::Vacant(entry) => {
308                entry.insert(key, value);
309            }
310            map::Entry::Occupied(_) => panic!("re-entrant init"),
311        }
312        Ok(ret)
313
314        // Leaving the function will wake up waiting threads.
315    }
316
317    pub fn contains_key<Q>(&self, hash: u64, key: &Q) -> bool
318    where
319        Q: Hash + Equivalent<K> + ?Sized,
320    {
321        self.map.read().contains_key(hash, key)
322    }
323
324    pub fn remove_entry<Q>(&mut self, hash: u64, key: &Q) -> Option<(K, V)>
325    where
326        Q: Hash + Equivalent<K> + ?Sized,
327    {
328        self.map.get_mut().remove_entry(hash, key)
329    }
330}
331
332pub struct OnceMap<K, V, S = crate::RandomState> {
333    shards: Box<[Shard<K, V>]>,
334    hash_builder: S,
335}
336
337impl<K, V> OnceMap<K, V> {
338    /// Creates an empty `OnceMap`.
339    pub fn new() -> Self {
340        Self::with_hasher(crate::RandomState::new())
341    }
342
343    #[cfg(test)]
344    pub(crate) fn with_single_shard() -> Self {
345        let hash_builder = crate::RandomState::new();
346        let shards = Box::new([Shard::new()]);
347        Self {
348            shards,
349            hash_builder,
350        }
351    }
352}
353
354impl<K, V, S> OnceMap<K, V, S> {
355    /// Creates an empty `OnceMap` which will use the given hash builder to hash keys.
356    pub fn with_hasher(hash_builder: S) -> Self {
357        let shards = (0..default_shards_amount()).map(|_| Shard::new()).collect();
358        Self {
359            shards,
360            hash_builder,
361        }
362    }
363}
364
365impl<K, V, S> OnceMap<K, V, S> {
366    /// Removes all key-value pairs from the map, but keeps the allocated memory.
367    pub fn clear(&mut self) {
368        self.shards.iter_mut().for_each(|s| s.map.get_mut().clear());
369    }
370
371    pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
372        self.shards
373            .iter_mut()
374            .flat_map(|s| s.map.get_mut().values_mut())
375    }
376
377    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
378        self.shards
379            .iter_mut()
380            .flat_map(|s| s.map.get_mut().iter_mut())
381    }
382
383    #[allow(clippy::should_implement_trait)]
384    pub fn into_iter(self) -> impl Iterator<Item = (K, V)> {
385        self.shards
386            .into_vec()
387            .into_iter()
388            .flat_map(|s| s.map.into_inner().into_iter())
389    }
390
391    /// Returns a reference to the map's [`BuildHasher`].
392    pub fn hasher(&self) -> &S {
393        &self.hash_builder
394    }
395
396    /// Locks the whole map for reading.
397    ///
398    /// This enables more methods, such as iterating on the maps, but will cause
399    /// a deadlock if trying to insert values in the map from the same thread.
400    pub fn read_only_view(&self) -> ReadOnlyView<'_, K, V, S> {
401        ReadOnlyView::new(self)
402    }
403}
404
405#[cfg(feature = "rayon")]
406#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
407impl<K, V, S> OnceMap<K, V, S>
408where
409    K: Send,
410    V: Send,
411{
412    pub fn into_par_iter(self) -> impl rayon::iter::ParallelIterator<Item = (K, V)> {
413        self.shards
414            .into_vec()
415            .into_par_iter()
416            .flat_map(|s| s.map.into_inner().into_par_iter())
417    }
418}
419
420impl<K, V, S> OnceMap<K, V, S>
421where
422    K: Eq + Hash,
423    S: BuildHasher,
424{
425    fn hash_one<Q>(&self, key: &Q) -> u64
426    where
427        Q: Hash + Equivalent<K> + ?Sized,
428    {
429        crate::hash_one(&self.hash_builder, key)
430    }
431
432    fn get_shard(&self, hash: u64) -> &Shard<K, V> {
433        let len = self.shards.len();
434        &self.shards[(len - 1) & (hash as usize)]
435    }
436
437    fn get_shard_mut(&mut self, hash: u64) -> &mut Shard<K, V> {
438        let len = self.shards.len();
439        &mut self.shards[(len - 1) & (hash as usize)]
440    }
441
442    /// Returns `true` if the map contains a value for the specified key.
443    pub fn contains_key<Q>(&self, key: &Q) -> bool
444    where
445        Q: Hash + Equivalent<K> + ?Sized,
446    {
447        let hash = self.hash_one(key);
448        self.get_shard(hash).contains_key(hash, key)
449    }
450
451    pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
452    where
453        Q: Hash + Equivalent<K> + ?Sized,
454    {
455        let hash = self.hash_one(key);
456        let (_, v) = self.get_shard_mut(hash).remove_entry(hash, key)?;
457        Some(v)
458    }
459
460    pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
461    where
462        Q: Hash + Equivalent<K> + ?Sized,
463    {
464        let hash = self.hash_one(key);
465        self.get_shard_mut(hash).remove_entry(hash, key)
466    }
467}
468
469impl<K, V, S> OnceMap<K, V, S>
470where
471    K: Eq + Hash,
472    S: BuildHasher,
473    V: StableDeref,
474{
475    /// Returns a reference to the value corresponding to the key.
476    pub fn get<Q>(&self, key: &Q) -> Option<&V::Target>
477    where
478        Q: Hash + Equivalent<K> + ?Sized,
479    {
480        self.map_get(key, |_, v| unsafe { extend_lifetime(v) })
481    }
482
483    /// Returns a reference to the value corresponding to the key or insert one
484    /// with the given closure.
485    pub fn insert(&self, key: K, make_val: impl FnOnce(&K) -> V) -> &V::Target {
486        self.map_insert(key, make_val, |_, v| unsafe { extend_lifetime(v) })
487    }
488
489    /// Same as `insert` but the closure is allowed to fail.
490    ///
491    /// If the closure is called and an error is returned, no value is stored in
492    /// the map.
493    pub fn try_insert<E>(
494        &self,
495        key: K,
496        make_val: impl FnOnce(&K) -> Result<V, E>,
497    ) -> Result<&V::Target, E> {
498        self.map_try_insert(key, make_val, |_, v| unsafe { extend_lifetime(v) })
499    }
500}
501
502impl<K, V, S> OnceMap<K, V, S>
503where
504    K: Eq + Hash,
505    S: BuildHasher,
506    V: Clone,
507{
508    pub fn get_cloned<Q>(&self, key: &Q) -> Option<V>
509    where
510        Q: Hash + Equivalent<K> + ?Sized,
511    {
512        self.map_get(key, |_, v| v.clone())
513    }
514
515    pub fn insert_cloned(&self, key: K, make_val: impl FnOnce(&K) -> V) -> V {
516        self.map_insert(key, make_val, |_, v| v.clone())
517    }
518
519    pub fn try_insert_cloned<E>(
520        &self,
521        key: K,
522        make_val: impl FnOnce(&K) -> Result<V, E>,
523    ) -> Result<V, E> {
524        self.map_try_insert(key, make_val, |_, v| v.clone())
525    }
526}
527
528impl<K, V, S> OnceMap<K, V, S>
529where
530    K: Eq + Hash,
531    S: BuildHasher,
532{
533    pub fn map_get<Q, T>(&self, key: &Q, with_result: impl FnOnce(&K, &V) -> T) -> Option<T>
534    where
535        Q: Hash + Equivalent<K> + ?Sized,
536    {
537        let hash = self.hash_one(key);
538        self.get_shard(hash).get(hash, key, with_result)
539    }
540
541    pub fn map_insert<T>(
542        &self,
543        key: K,
544        make_val: impl FnOnce(&K) -> V,
545        with_result: impl FnOnce(&K, &V) -> T,
546    ) -> T {
547        self.map_try_insert(key, |k| Ok(make_val(k)), with_result)
548            .unwrap_infallible()
549    }
550
551    pub fn map_insert_ref<Q, T>(
552        &self,
553        key: &Q,
554        make_key: impl FnOnce(&Q) -> K,
555        make_val: impl FnOnce(&K) -> V,
556        with_result: impl FnOnce(&K, &V) -> T,
557    ) -> T
558    where
559        Q: Hash + Equivalent<K> + ?Sized,
560    {
561        self.map_try_insert_ref(key, make_key, |k| Ok(make_val(k)), with_result)
562            .unwrap_infallible()
563    }
564
565    pub fn map_try_insert<T, E>(
566        &self,
567        key: K,
568        make_val: impl FnOnce(&K) -> Result<V, E>,
569        with_result: impl FnOnce(&K, &V) -> T,
570    ) -> Result<T, E> {
571        self.get_or_try_insert(
572            key,
573            with_result,
574            |with_result, k| {
575                let v = make_val(k)?;
576                let ret = with_result(k, &v);
577                Ok((v, ret))
578            },
579            |with_result, k, v| with_result(k, v),
580        )
581    }
582
583    pub fn map_try_insert_ref<Q, T, E>(
584        &self,
585        key: &Q,
586        make_key: impl FnOnce(&Q) -> K,
587        make_val: impl FnOnce(&K) -> Result<V, E>,
588        with_result: impl FnOnce(&K, &V) -> T,
589    ) -> Result<T, E>
590    where
591        Q: Hash + Equivalent<K> + ?Sized,
592    {
593        self.get_or_try_insert_ref(
594            key,
595            with_result,
596            make_key,
597            |with_result, k| {
598                let v = make_val(k)?;
599                let ret = with_result(k, &v);
600                Ok((v, ret))
601            },
602            |with_result, k, v| with_result(k, v),
603        )
604    }
605
606    pub fn get_or_try_insert<T, U, E>(
607        &self,
608        key: K,
609        data: T,
610        on_vacant: impl FnOnce(T, &K) -> Result<(V, U), E>,
611        on_occupied: impl FnOnce(T, &K, &V) -> U,
612    ) -> Result<U, E> {
613        let hash = self.hash_one(&key);
614        let shard = self.get_shard(hash);
615
616        match shard.try_get(hash, &key, data, on_occupied) {
617            Ok(result) => Ok(result),
618            Err((data, on_occupied)) => {
619                shard.get_or_try_insert(hash, key, data, &self.hash_builder, on_vacant, on_occupied)
620            }
621        }
622    }
623
624    pub fn get_or_try_insert_ref<Q, T, U, E>(
625        &self,
626        key: &Q,
627        data: T,
628        make_key: impl FnOnce(&Q) -> K,
629        on_vacant: impl FnOnce(T, &K) -> Result<(V, U), E>,
630        on_occupied: impl FnOnce(T, &K, &V) -> U,
631    ) -> Result<U, E>
632    where
633        Q: Hash + Equivalent<K> + ?Sized,
634    {
635        let hash = self.hash_one(key);
636        let shard = self.get_shard(hash);
637
638        // Try to get the value from the map as a fast-path, to avoid having to
639        // compute an owned version of the key.
640        shard.try_get(hash, key, data, on_occupied).or_else(
641            #[cold]
642            |(data, on_occupied)| {
643                let owned_key = make_key(key);
644                debug_assert_eq!(self.hash_one::<K>(&owned_key), hash);
645                debug_assert!(key.equivalent(&owned_key));
646                shard.get_or_try_insert(
647                    hash,
648                    owned_key,
649                    data,
650                    &self.hash_builder,
651                    on_vacant,
652                    on_occupied,
653                )
654            },
655        )
656    }
657}
658
659impl<K, V, S: Default> Default for OnceMap<K, V, S> {
660    fn default() -> Self {
661        Self::with_hasher(S::default())
662    }
663}
664
665impl<K, V, S> Extend<(K, V)> for OnceMap<K, V, S>
666where
667    K: Eq + Hash,
668    S: BuildHasher,
669{
670    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
671        iter.into_iter()
672            .for_each(|(k, v)| self.map_insert(k, |_| v, |_, _| ()))
673    }
674}
675
676impl<K, V, S> Extend<(K, V)> for &'_ OnceMap<K, V, S>
677where
678    K: Eq + Hash,
679    S: BuildHasher,
680{
681    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
682        iter.into_iter()
683            .for_each(|(k, v)| self.map_insert(k, |_| v, |_, _| ()))
684    }
685}
686
687impl<K, V, S> FromIterator<(K, V)> for OnceMap<K, V, S>
688where
689    K: Eq + Hash,
690    S: BuildHasher + Default,
691{
692    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
693        let mut map = OnceMap::default();
694        map.extend(iter);
695        map
696    }
697}
698
699impl<K, V, S, const N: usize> From<[(K, V); N]> for OnceMap<K, V, S>
700where
701    K: Eq + Hash,
702    S: BuildHasher + Default,
703{
704    fn from(array: [(K, V); N]) -> Self {
705        Self::from_iter(array)
706    }
707}
708
709#[cfg(feature = "rayon")]
710#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
711impl<K, V, S> ParallelExtend<(K, V)> for OnceMap<K, V, S>
712where
713    K: Eq + Hash + Send + Sync,
714    V: Send + Sync,
715    S: BuildHasher + Sync,
716{
717    fn par_extend<I>(&mut self, par_iter: I)
718    where
719        I: IntoParallelIterator<Item = (K, V)>,
720    {
721        par_iter
722            .into_par_iter()
723            .for_each(|(k, v)| self.map_insert(k, |_| v, |_, _| ()));
724    }
725}
726
727#[cfg(feature = "rayon")]
728#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
729impl<K, V, S> ParallelExtend<(K, V)> for &'_ OnceMap<K, V, S>
730where
731    K: Eq + Hash + Send + Sync,
732    V: Send + Sync,
733    S: BuildHasher + Sync,
734{
735    fn par_extend<I>(&mut self, par_iter: I)
736    where
737        I: IntoParallelIterator<Item = (K, V)>,
738    {
739        par_iter
740            .into_par_iter()
741            .for_each(|(k, v)| self.map_insert(k, |_| v, |_, _| ()));
742    }
743}
744
745#[cfg(feature = "rayon")]
746#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
747impl<K, V, S> FromParallelIterator<(K, V)> for OnceMap<K, V, S>
748where
749    K: Eq + Hash + Send + Sync,
750    V: Send + Sync,
751    S: BuildHasher + Default + Sync,
752{
753    fn from_par_iter<I>(par_iter: I) -> Self
754    where
755        I: IntoParallelIterator<Item = (K, V)>,
756    {
757        let mut map = Self::default();
758        map.par_extend(par_iter);
759        map
760    }
761}
762
763#[cfg(feature = "serde")]
764#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
765impl<K, V, S> serde::Serialize for OnceMap<K, V, S>
766where
767    K: serde::Serialize,
768    V: serde::Serialize,
769{
770    fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
771    where
772        Ser: serde::Serializer,
773    {
774        serializer.collect_map(self.read_only_view().iter())
775    }
776}
777
778#[cfg(feature = "serde")]
779#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
780impl<'de, K, V, S> serde::Deserialize<'de> for OnceMap<K, V, S>
781where
782    K: Eq + Hash + serde::Deserialize<'de>,
783    V: serde::Deserialize<'de>,
784    S: BuildHasher + Default,
785{
786    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
787    where
788        D: serde::Deserializer<'de>,
789    {
790        struct OnceMapVisitor<K, V, S>(OnceMap<K, V, S>);
791
792        impl<'de, K, V, S> serde::de::Visitor<'de> for OnceMapVisitor<K, V, S>
793        where
794            K: Eq + Hash + serde::Deserialize<'de>,
795            V: serde::Deserialize<'de>,
796            S: BuildHasher,
797        {
798            type Value = OnceMap<K, V, S>;
799
800            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
801                formatter.write_str("a map")
802            }
803
804            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
805            where
806                A: serde::de::MapAccess<'de>,
807            {
808                while let Some((key, value)) = map.next_entry()? {
809                    self.0.map_insert(key, |_| value, |_, _| ())
810                }
811
812                Ok(self.0)
813            }
814        }
815
816        deserializer.deserialize_map(OnceMapVisitor(OnceMap::default()))
817    }
818}
819
820impl<K, V, S> fmt::Debug for OnceMap<K, V, S>
821where
822    K: fmt::Debug,
823    V: fmt::Debug,
824{
825    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
826        f.debug_map().entries(self.read_only_view().iter()).finish()
827    }
828}
829
830#[repr(transparent)]
831struct LockedShard<K, V>(Shard<K, V>);
832
833unsafe impl<K: Sync, V: Sync> Sync for LockedShard<K, V> {}
834
835impl<K, V> LockedShard<K, V> {
836    fn get(&self) -> &HashMap<K, V> {
837        unsafe { &*self.0.map.data_ptr() }
838    }
839}
840
841pub struct ReadOnlyView<'a, K, V, S = crate::RandomState> {
842    shards: &'a [LockedShard<K, V>],
843    hasher: &'a S,
844    _marker: crate::PhantomUnsend,
845}
846
847impl<'a, K, V, S> ReadOnlyView<'a, K, V, S> {
848    fn new(map: &'a OnceMap<K, V, S>) -> Self {
849        use parking_lot::lock_api::RawRwLockRecursive;
850
851        for shard in map.shards.iter() {
852            unsafe {
853                shard.map.raw().lock_shared_recursive();
854            }
855        }
856
857        let shards = unsafe { &*(&*map.shards as *const [_] as *const [_]) };
858
859        Self {
860            shards,
861            hasher: &map.hash_builder,
862            _marker: crate::PhantomUnsend(std::marker::PhantomData),
863        }
864    }
865
866    #[inline]
867    fn iter_shards(&self) -> impl ExactSizeIterator<Item = &HashMap<K, V>> {
868        self.shards.iter().map(|shard| shard.get())
869    }
870
871    pub fn len(&self) -> usize {
872        self.iter_shards().map(|s| s.len()).sum()
873    }
874
875    pub fn is_empty(&self) -> bool {
876        self.iter_shards().all(|s| s.is_empty())
877    }
878
879    pub fn hasher(&self) -> &S {
880        self.hasher
881    }
882
883    pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
884        self.iter_shards().flat_map(|shard| shard.iter())
885    }
886
887    pub fn keys(&self) -> impl Iterator<Item = &K> {
888        self.iter_shards().flat_map(|shard| shard.keys())
889    }
890
891    pub fn values(&self) -> impl Iterator<Item = &V> {
892        self.iter_shards().flat_map(|shard| shard.values())
893    }
894}
895
896impl<K, V, S> ReadOnlyView<'_, K, V, S>
897where
898    K: Eq + Hash,
899    S: BuildHasher,
900{
901    #[inline]
902    fn hash_one<Q>(&self, key: &Q) -> u64
903    where
904        Q: Hash + Equivalent<K> + ?Sized,
905    {
906        crate::hash_one(self.hasher, key)
907    }
908
909    fn get_shard(&self, hash: u64) -> &HashMap<K, V> {
910        let len = self.shards.len();
911        let shard = &self.shards[(len - 1) & (hash as usize)];
912        shard.get()
913    }
914
915    pub fn get<Q>(&self, key: &Q) -> Option<&V>
916    where
917        Q: Hash + Equivalent<K> + ?Sized,
918    {
919        let hash = self.hash_one(key);
920        self.get_shard(hash).get(hash, key)
921    }
922
923    pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)>
924    where
925        Q: Hash + Equivalent<K> + ?Sized,
926    {
927        let hash = self.hash_one(key);
928        self.get_shard(hash).get_key_value(hash, key)
929    }
930
931    pub fn contains_key<Q>(&self, key: &Q) -> bool
932    where
933        Q: Hash + Equivalent<K> + ?Sized,
934    {
935        let hash = self.hash_one(key);
936        self.get_shard(hash).contains_key(hash, key)
937    }
938}
939
940impl<K, V, S> Drop for ReadOnlyView<'_, K, V, S> {
941    fn drop(&mut self) {
942        for shard in self.shards.iter() {
943            unsafe { shard.0.map.force_unlock_read() }
944        }
945    }
946}
947
948#[cfg(feature = "rayon")]
949#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
950impl<K, V, S> ReadOnlyView<'_, K, V, S>
951where
952    K: Sync,
953    V: Sync,
954{
955    #[inline]
956    fn par_iter_shards(&self) -> impl rayon::iter::IndexedParallelIterator<Item = &HashMap<K, V>> {
957        self.shards.par_iter().map(|shard| shard.get())
958    }
959
960    pub fn par_iter(&self) -> impl rayon::iter::ParallelIterator<Item = (&K, &V)> {
961        self.par_iter_shards().flat_map(|shard| shard.par_iter())
962    }
963
964    pub fn par_keys(&self) -> impl rayon::iter::ParallelIterator<Item = &K> {
965        self.par_iter_shards().flat_map(|shard| shard.par_keys())
966    }
967
968    pub fn par_values(&self) -> impl rayon::iter::ParallelIterator<Item = &V> {
969        self.par_iter_shards().flat_map(|shard| shard.par_values())
970    }
971}
972
973#[cfg(feature = "serde")]
974#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
975impl<K, V, S> serde::Serialize for ReadOnlyView<'_, K, V, S>
976where
977    K: serde::Serialize,
978    V: serde::Serialize,
979{
980    fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
981    where
982        Ser: serde::Serializer,
983    {
984        serializer.collect_map(self.iter())
985    }
986}
987
988impl<K, V, S> fmt::Debug for ReadOnlyView<'_, K, V, S>
989where
990    K: fmt::Debug,
991    V: fmt::Debug,
992{
993    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
994        f.debug_map().entries(self.iter()).finish()
995    }
996}
997
998/// A map where values are automatically filled at access.
999///
1000/// This type can be shared across threads.
1001///
1002/// ```
1003/// let map = once_map::LazyMap::new(|x: &i32| x.to_string());
1004///
1005/// assert_eq!(&map[&3], "3");
1006/// assert_eq!(map.get(&-67), "-67");
1007/// ```
1008pub struct LazyMap<K, V, S = crate::RandomState, F = fn(&K) -> V> {
1009    map: OnceMap<K, V, S>,
1010    init: F,
1011}
1012
1013impl<K, V, F> LazyMap<K, V, crate::RandomState, F> {
1014    pub fn new(f: F) -> Self {
1015        Self::with_hasher(crate::RandomState::new(), f)
1016    }
1017}
1018
1019impl<K, V, S, F> LazyMap<K, V, S, F> {
1020    pub fn with_hasher(hash_builder: S, f: F) -> Self {
1021        Self {
1022            map: OnceMap::with_hasher(hash_builder),
1023            init: f,
1024        }
1025    }
1026
1027    /// Removes all entries from the map.
1028    pub fn clear(&mut self) {
1029        self.map.clear();
1030    }
1031}
1032
1033impl<K, V, S, F> LazyMap<K, V, S, F>
1034where
1035    K: Eq + Hash,
1036    S: BuildHasher,
1037    F: Fn(&K) -> V,
1038    V: StableDeref,
1039{
1040    pub fn get<Q>(&self, key: &Q) -> &V::Target
1041    where
1042        Q: Hash + ToOwnedEquivalent<K> + ?Sized,
1043    {
1044        self.map_get(key, |_, v| unsafe { extend_lifetime(v) })
1045    }
1046}
1047
1048impl<K, V, S, F> LazyMap<K, V, S, F>
1049where
1050    K: Eq + Hash,
1051    S: BuildHasher,
1052    F: Fn(&K) -> V,
1053    V: Clone,
1054{
1055    pub fn get_cloned<Q>(&self, key: &Q) -> V
1056    where
1057        Q: Hash + ToOwnedEquivalent<K> + ?Sized,
1058    {
1059        self.map_get(key, |_, v| v.clone())
1060    }
1061}
1062
1063impl<K, V, S, F> LazyMap<K, V, S, F>
1064where
1065    K: Eq + Hash,
1066    S: BuildHasher,
1067    F: Fn(&K) -> V,
1068{
1069    pub fn map_get<Q, T>(&self, key: &Q, with_result: impl FnOnce(&K, &V) -> T) -> T
1070    where
1071        Q: Hash + ToOwnedEquivalent<K> + ?Sized,
1072    {
1073        self.map
1074            .map_insert_ref(key, Q::to_owned_equivalent, &self.init, with_result)
1075    }
1076}
1077
1078impl<K, V, S, F> LazyMap<K, V, S, F>
1079where
1080    K: Eq + Hash,
1081    S: BuildHasher,
1082{
1083    pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
1084    where
1085        Q: Hash + Equivalent<K> + ?Sized,
1086    {
1087        self.map.remove(key)
1088    }
1089}
1090
1091impl<K, V, S, F, Q> core::ops::Index<&Q> for LazyMap<K, V, S, F>
1092where
1093    K: Eq + Hash,
1094    S: BuildHasher,
1095    F: Fn(&K) -> V,
1096    V: StableDeref,
1097    Q: Hash + ToOwnedEquivalent<K> + ?Sized,
1098{
1099    type Output = V::Target;
1100
1101    fn index(&self, key: &Q) -> &V::Target {
1102        self.get(key)
1103    }
1104}
1105
1106/// Creates a `LazyMap` that fills all values with `V::default()`.
1107impl<K, V: Default, S: Default> Default for LazyMap<K, V, S> {
1108    fn default() -> Self {
1109        Self::with_hasher(S::default(), |_| V::default())
1110    }
1111}
1112
1113impl<K, V, S> fmt::Debug for LazyMap<K, V, S>
1114where
1115    K: fmt::Debug,
1116    V: fmt::Debug,
1117{
1118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1119        f.debug_struct("LazyMap")
1120            .field("values", &self.map)
1121            .finish_non_exhaustive()
1122    }
1123}