flashmap/
lib.rs

1#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
2#![deny(rust_2018_idioms, unsafe_op_in_unsafe_fn)]
3#![warn(missing_docs)]
4#![doc = include_str!("../README.md")]
5
6pub mod algorithm;
7mod core;
8mod read;
9mod util;
10mod view;
11mod write;
12
13pub use read::*;
14pub(crate) use util::loom;
15pub use util::{deterministic::*, Alias};
16pub use view::View;
17pub use write::*;
18
19use self::core::Core;
20use std::{
21    collections::hash_map::RandomState,
22    fmt::{self, Debug, Formatter},
23    hash::{BuildHasher, Hash},
24};
25
26pub(crate) type Map<K, V, S = RandomState> = hashbrown::HashMap<Alias<K>, Alias<V>, S>;
27
28/// Creates a new map with a [`RandomState`](std::collections::hash_map::RandomState) hasher.
29///
30/// If you wish to specify additional parameters, see [`with_capacity`](crate::with_capacity),
31/// [`with_hasher`](crate::with_hasher), and [`Builder`](crate::Builder).
32pub fn new<K, V>() -> (WriteHandle<K, V>, ReadHandle<K, V>)
33where
34    K: TrustedHashEq,
35{
36    Builder::new().build()
37}
38
39/// Creates a new map with the specified initial capacity and a
40/// [`RandomState`](std::collections::hash_map::RandomState) hasher.
41///
42/// If you wish to specify additional parameters, see [`Builder`](crate::Builder).
43pub fn with_capacity<K, V>(capacity: usize) -> (WriteHandle<K, V>, ReadHandle<K, V>)
44where
45    K: TrustedHashEq,
46{
47    Builder::new().with_capacity(capacity).build()
48}
49
50/// Creates a new map with the specified hasher.
51///
52/// If you wish to specify additional parameters, see [`Builder`](crate::Builder).
53///
54/// # Safety
55///
56/// The given hasher builder must produce a deterministic hasher. In other words, the built hasher
57/// must always produce the same hash given the same input and initial state.
58pub unsafe fn with_hasher<K, V, S>(hasher: S) -> (WriteHandle<K, V, S>, ReadHandle<K, V, S>)
59where
60    K: TrustedHashEq,
61    S: Clone + BuildHasher,
62{
63    unsafe { Builder::new().with_hasher(hasher).build() }
64}
65
66/// A builder for a map.
67///
68/// This builder allows you to specify an initial capacity and a hasher, and provides more
69/// flexibility in how that hasher can be constructed.
70#[derive(Clone, Copy)]
71pub struct Builder<S = RandomState> {
72    capacity: usize,
73    hasher: HasherGen<S>,
74}
75
76impl<S> Debug for Builder<S> {
77    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
78        f.debug_struct("Builder")
79            .field("capacity", &self.capacity)
80            .field("hasher", &std::any::type_name::<S>())
81            .finish()
82    }
83}
84
85impl Builder<RandomState> {
86    /// Creates a new builder with a [`RandomState`](std::collections::hash_map::RandomState)
87    /// hasher, and an initial capacity of zero.
88    pub fn new() -> Self {
89        Self {
90            capacity: 0,
91            hasher: HasherGen::MakeBoth(|| {
92                let hasher = RandomState::default();
93                (hasher.clone(), hasher)
94            }),
95        }
96    }
97}
98
99impl Default for Builder<RandomState> {
100    fn default() -> Self {
101        Self::new()
102    }
103}
104
105impl<S> Builder<S> {
106    /// Sets the initial capacity of the map. If not specified, the default is 0.
107    pub fn with_capacity(self, capacity: usize) -> Self {
108        Self {
109            capacity,
110            hasher: self.hasher,
111        }
112    }
113
114    /// Sets the hasher for the underlying map. The provided hasher must implement `Clone` due to
115    /// the implementation details of this crate.
116    ///
117    /// # Safety
118    ///
119    /// See [`crate::with_hasher`](crate::with_hasher).
120    pub unsafe fn with_hasher<H>(self, hasher: H) -> Builder<H>
121    where
122        H: Clone + BuildHasher,
123    {
124        Builder {
125            capacity: self.capacity,
126            hasher: HasherGen::Clone(hasher, H::clone),
127        }
128    }
129
130    /// Sets the hasher for the underlying map. Similar to
131    /// [`with_hasher`](crate::Builder::with_hasher), but instead of using a concrete hasher
132    /// builder, the provided function will be called as many times as necessary to initialize
133    /// the underlying map.
134    ///
135    /// # Safety
136    ///
137    /// See [`crate::with_hasher`](crate::with_hasher).
138    pub unsafe fn with_hasher_generator<H>(self, gen: fn() -> H) -> Builder<H>
139    where
140        H: BuildHasher,
141    {
142        Builder {
143            capacity: self.capacity,
144            hasher: HasherGen::Generate(gen),
145        }
146    }
147
148    /// Consumes the builder and returns a write handle and read handle to the map.
149    ///
150    /// # Examples
151    ///
152    /// ```
153    /// # use flashmap::Builder;
154    /// // Use type inference to determine the key and value types
155    /// let (mut write, read) = Builder::new().build();
156    ///
157    /// write.guard().insert(10u32, 20u32);
158    ///
159    /// // Or specify them explicitly
160    /// let (write, read) = Builder::new().build::<String, String>();
161    /// ```
162    pub fn build<K, V>(self) -> (WriteHandle<K, V, S>, ReadHandle<K, V, S>)
163    where
164        K: TrustedHashEq,
165        S: BuildHasher,
166    {
167        unsafe { self.build_assert_trusted() }
168    }
169
170    /// Consumes the builder and returns a write handle and read handle to the map.
171    ///
172    /// # Safety
173    ///
174    /// The implementations of `Hash` and `Eq` for the key type **must** be deterministic. See
175    /// [`TrustedHashEq`](crate::TrustedHashEq) for details.
176    pub unsafe fn build_assert_trusted<K, V>(self) -> (WriteHandle<K, V, S>, ReadHandle<K, V, S>)
177    where
178        K: Hash + Eq,
179        S: BuildHasher,
180    {
181        unsafe { Core::build_map(self.into_args()) }
182    }
183
184    pub(crate) fn into_args(self) -> BuilderArgs<S> {
185        let (h1, h2) = self.hasher.generate();
186        BuilderArgs {
187            capacity: self.capacity,
188            h1,
189            h2,
190        }
191    }
192}
193
194#[derive(Clone, Copy)]
195enum HasherGen<S> {
196    Generate(fn() -> S),
197    MakeBoth(fn() -> (S, S)),
198    Clone(S, fn(&S) -> S),
199}
200
201impl<S> HasherGen<S> {
202    fn generate(self) -> (S, S) {
203        match self {
204            Self::Generate(gen) => (gen(), gen()),
205            Self::MakeBoth(make_both) => make_both(),
206            Self::Clone(hasher, clone) => (clone(&hasher), hasher),
207        }
208    }
209}
210
211pub(crate) struct BuilderArgs<S> {
212    pub capacity: usize,
213    pub h1: S,
214    pub h2: S,
215}
216
217/// ```compile_fail
218/// fn assert_send<T: Send>() {}
219/// use flashmap::*;
220/// assert_send::<Evicted<'_, (), ()>>();
221/// ```
222///
223/// ```compile_fail
224/// fn assert_send<T: Send>() {}
225/// use flashmap::*;
226/// assert_send::<Alias<std::cell::Cell<()>>>();
227/// ```
228#[allow(dead_code)]
229struct NotSendTypes;
230
231/// ```compile_fail
232/// fn assert_sync<T: Sync>() {}
233/// use flashmap::*;
234/// assert_sync::<Evicted<'_, (), ()>>();
235/// ```
236///
237/// ```compile_fail
238/// fn assert_sync<T: Sync>() {}
239/// use flashmap::*;
240/// assert_sync::<Alias<std::sync::MutexGuard<'_, ()>>>();
241/// ```
242#[allow(dead_code)]
243struct NotSyncTypes;
244
245#[cfg(test)]
246mod tests {
247    use super::*;
248    use std::{collections::hash_map::DefaultHasher, marker::PhantomData};
249
250    fn assert_send<T: Send>() {}
251    fn assert_sync<T: Sync>() {}
252
253    #[derive(PartialEq, Eq, Hash)]
254    struct SendOnly(PhantomData<*const u8>);
255
256    unsafe impl Send for SendOnly {}
257
258    #[derive(PartialEq, Eq, Hash)]
259    struct SyncOnly(PhantomData<*const u8>);
260
261    unsafe impl Sync for SyncOnly {}
262
263    #[derive(PartialEq, Eq, Hash)]
264    struct SendSync;
265
266    impl BuildHasher for SendSync {
267        type Hasher = DefaultHasher;
268
269        fn build_hasher(&self) -> Self::Hasher {
270            unimplemented!()
271        }
272    }
273
274    #[test]
275    fn send_types() {
276        assert_send::<ReadHandle<SendSync, SendSync, SendSync>>();
277        assert_send::<WriteHandle<SendSync, SendSync, SendSync>>();
278        assert_send::<View<ReadGuard<'_, SendSync, SendSync, SendSync>>>();
279        assert_send::<Leaked<SendOnly>>();
280    }
281
282    #[test]
283    fn sync_types() {
284        assert_sync::<ReadHandle<SendSync, SendSync, SendSync>>();
285        assert_sync::<View<ReadGuard<'_, SendSync, SendSync, SendSync>>>();
286        assert_sync::<Leaked<SyncOnly>>();
287    }
288}