waitcache/
iter.rs

1//
2// Copyright (C) 2020 Nathan Sharp.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public License,
5// v. 2.0. If a copy of the MPL was not distributed with this file, You can
6// obtain one at https://mozilla.org/MPL/2.0/
7//
8// This Source Code Form is "Incompatible With Secondary Licenses", as defined
9// by the Mozilla Public License, v. 2.0.
10//
11
12//! Iterator types for [`WaitCache`].
13//!
14//! [`WaitCache`]: crate::WaitCache
15
16use std::collections::hash_map::RandomState;
17use std::hash::{BuildHasher, Hash};
18
19use dashmap::iter::Iter as DashIter;
20use dashmap::iter::OwningIter as DashOwningIter;
21use dashmap::mapref::multiple::RefMulti as DashMulti;
22use waitcell::WaitCell;
23
24/// The iterator produced by [`WaitCache::iter`].
25///
26/// [`WaitCache::iter`]: crate::WaitCache::iter
27pub struct Iter<'a, K, V, S = RandomState> {
28    pub(crate) iter: DashIter<'a, K, Box<WaitCell<V>>, S>,
29    pub(crate) current: Option<DashMulti<'a, K, Box<WaitCell<V>>, S>>,
30}
31
32impl<'a, K: Eq + Hash, V, S: BuildHasher + Clone> Iterator for Iter<'a, K, V, S> {
33    type Item = (&'a K, &'a WaitCell<V>);
34
35    fn next(&mut self) -> Option<Self::Item> {
36        // Drop the previous reference before advancing to avoid a deadlock.
37        self.current.take();
38        self.current = self.iter.next();
39
40        // Safety: Holding the iterator ensures that the reference will live at least as
41        //         long as `self` was borrowed.
42        self.current.as_ref().map(|multi| unsafe {
43            (&*(multi.key() as *const K), &*(multi.value().as_ref() as *const WaitCell<V>))
44        })
45    }
46}
47
48/// The iterator produced by [`WaitCache::keys`].
49///
50/// [`WaitCache::keys`]: crate::WaitCache::keys
51pub struct Keys<'a, K, V, S = RandomState> {
52    pub(crate) iter: Iter<'a, K, V, S>,
53}
54
55impl<'a, K: Eq + Hash, V, S: BuildHasher + Clone> Iterator for Keys<'a, K, V, S> {
56    type Item = &'a K;
57
58    fn next(&mut self) -> Option<Self::Item> {
59        self.iter.next().map(|(key, _)| key)
60    }
61}
62
63/// The iterator produced by [`WaitCache::values`].
64///
65/// [`WaitCache::values`]: crate::WaitCache::values
66pub struct Values<'a, K, V, S = RandomState> {
67    pub(crate) iter: DashIter<'a, K, Box<WaitCell<V>>, S>,
68}
69
70impl<'a, K: Eq + Hash, V, S: BuildHasher + Clone> Iterator for Values<'a, K, V, S> {
71    type Item = &'a WaitCell<V>;
72
73    fn next(&mut self) -> Option<Self::Item> {
74        // Safety: 'a is an immutable borrow of the cache, so the same guarantees as in
75        // `get` applies.
76        let ptr = self.iter.next()?.value().as_ref() as *const WaitCell<V>;
77        Some(unsafe { &*ptr })
78    }
79}
80
81/// The iterator produced by [`WaitCache::into_iter`].
82///
83/// [`WaitCache::into_iter`]: crate::WaitCache::into_iter
84pub struct Owned<K, V, S = RandomState> {
85    pub(crate) iter: DashOwningIter<K, Box<WaitCell<V>>, S>,
86}
87
88impl<K: Eq + Hash, V, S: BuildHasher + Clone> Iterator for Owned<K, V, S> {
89    type Item = (K, Option<V>);
90
91    fn next(&mut self) -> Option<Self::Item> {
92        self.iter.next().map(|(key, value)| (key, value.into_inner()))
93    }
94}