flashmap/
write.rs

1use std::{
2    collections::hash_map::RandomState,
3    hash::{BuildHasher, Hash},
4    mem,
5    num::NonZeroUsize,
6    ops::Deref,
7    sync::atomic::{AtomicUsize, Ordering},
8};
9
10use hashbrown::hash_map::RawEntryMut;
11
12use crate::{
13    core::Core,
14    loom::cell::UnsafeCell,
15    loom::sync::Arc,
16    util::{Alias, BorrowHelper},
17    view::sealed::ReadAccess,
18    Map, View,
19};
20
21static NEXT_WRITER_UID: AtomicUsize = AtomicUsize::new(1);
22const LEAKED_VALUE_MISMATCH: &str = "Leaked value is not from this map";
23
24#[repr(transparent)]
25#[derive(PartialEq, Eq, Clone, Copy)]
26struct WriterUid(NonZeroUsize);
27
28impl WriterUid {
29    fn next() -> Self {
30        Self(
31            NonZeroUsize::new(NEXT_WRITER_UID.fetch_add(1, Ordering::Relaxed))
32                .expect("Maximum number of maps exceeded for this architecture"),
33        )
34    }
35}
36
37/// A write handle to the underlying map.
38///
39/// This type allows for the creation of [`WriteGuard`s](crate::WriteGuard) which allow for
40/// mutation of the underlying map.
41pub struct WriteHandle<K, V, S = RandomState>
42where
43    K: Hash + Eq,
44    S: BuildHasher,
45{
46    core: Arc<Core<K, V, S>>,
47    operations: UnsafeCell<Vec<Operation<K, V>>>,
48    uid: WriterUid,
49}
50
51unsafe impl<K, V, S> Send for WriteHandle<K, V, S>
52where
53    K: Send + Sync + Hash + Eq,
54    V: Send + Sync,
55    S: Send + Sync + BuildHasher,
56{
57}
58
59impl<K, V, S> WriteHandle<K, V, S>
60where
61    K: Hash + Eq,
62    S: BuildHasher,
63{
64    pub(crate) unsafe fn new(core: Arc<Core<K, V, S>>) -> Self {
65        Self {
66            core,
67            operations: UnsafeCell::new(Vec::new()),
68            uid: WriterUid::next(),
69        }
70    }
71
72    /// Blocks the calling thread until all readers see the same version of the map.
73    ///
74    /// If all readers already see the same version of the map (or if there are no active readers)
75    /// then this function is a no-op.
76    ///
77    /// This function is meant for advanced use only. See
78    /// `Leaked::`[`into_inner`](crate::Leaked::into_inner) for an example use-case.
79    #[inline]
80    pub fn synchronize(&self) {
81        self.core.synchronize();
82    }
83
84    /// Creates a new [`WriteGuard`](crate::WriteGuard) wrapped in a [`View`](crate::View),
85    /// allowing for safe read and write access to the map.
86    ///
87    /// # Examples
88    ///
89    /// ```
90    /// # use flashmap;
91    /// let (mut write, read) = flashmap::new::<String, String>();
92    ///
93    /// let mut guard = write.guard();
94    ///
95    /// // Insert a few values
96    /// guard.insert("apple".to_owned(), "red".to_owned());
97    /// guard.insert("banana".to_owned(), "yellow".to_owned());
98    ///
99    /// // Remove a value
100    /// assert_eq!(&*guard.remove("apple".to_owned()).unwrap(), "red");
101    ///
102    /// // Publishing makes all previous changes visible to new readers. Dropping the
103    /// // guard has the same effect.
104    /// guard.publish();
105    /// ```
106    ///
107    /// Unlike a read guard, when reading through a write guard, all changes will be immediately
108    /// visible.
109    /// ```
110    /// # use flashmap;
111    /// let (mut write, read) = flashmap::new::<String, String>();
112    ///
113    /// let mut guard = write.guard();
114    ///
115    /// // Our insert is immediately visible to us
116    /// guard.insert("apple".to_owned(), "red".to_owned());
117    /// assert_eq!(guard.get("apple").unwrap(), "red");
118    /// assert!(!guard.contains_key("banana"));
119    ///
120    /// guard.insert("banana".to_owned(), "yellow".to_owned());
121    /// assert_eq!(guard.get("banana").unwrap(), "yellow");
122    ///
123    /// // Likewise, removes (and all other operations) are immediately visible
124    /// assert_eq!(&*guard.remove("apple".to_owned()).unwrap(), "red");
125    /// assert!(!guard.contains_key("apple"));
126    /// ```
127    pub fn guard(&mut self) -> View<WriteGuard<'_, K, V, S>> {
128        self.synchronize();
129        let map = self.core.writer_map();
130        map.with_mut(|map_ptr| {
131            self.operations.with_mut(|ops_ptr| {
132                let operations = unsafe { &mut *ops_ptr };
133                unsafe { Self::flush_operations(operations, &mut *map_ptr) };
134                operations.shrink_to(64);
135            });
136        });
137
138        View::new(WriteGuard {
139            map,
140            handle: self,
141            handle_uid: self.uid,
142        })
143    }
144
145    /// Reclaims a leaked value, providing ownership of the underlying value.
146    ///
147    /// # Panics
148    ///
149    /// Panics if the leaked value provided came from a different map then the one this handle is
150    /// associated with.
151    ///
152    /// # Examples
153    ///
154    /// ```
155    /// use flashmap::{self, Evicted};
156    ///
157    /// let (mut write, read) = flashmap::new::<String, String>();
158    ///
159    /// write.guard().insert("ferris".to_owned(), "crab".to_owned());
160    ///
161    /// // ~~ stuff happens ~~
162    ///
163    /// let leaked = write.guard().remove("ferris".to_owned())
164    ///     .map(Evicted::leak)
165    ///     .unwrap();
166    ///
167    /// let value = write.reclaim_one(leaked);
168    /// assert_eq!(value, "crab");
169    /// ```
170    #[inline]
171    pub fn reclaim_one(&self, leaked: Leaked<V>) -> V {
172        (self.reclaimer())(leaked)
173    }
174
175    /// Returns a function which can safely reclaim leaked values. This is useful for reclaiming
176    /// multiple leaked values while only performign the necessary synchronization once.
177    ///
178    /// # Panics
179    ///
180    /// The **returned function** will panic if given a leaked value not from the map this handle
181    /// is associated with. This function itself will not panic.
182    ///
183    /// # Examples
184    ///
185    /// ```
186    /// use flashmap::{self, Evicted};
187    ///
188    /// let (mut write, read) = flashmap::new::<u32, String>();
189    ///
190    /// let mut guard = write.guard();
191    /// guard.insert(0xFF0000, "red".to_owned());
192    /// guard.insert(0x00FF00, "green".to_owned());
193    /// guard.insert(0x0000FF, "blue".to_owned());
194    /// guard.publish();
195    ///
196    /// // ~~ stuff happens ~~
197    ///
198    /// let mut guard = write.guard();
199    /// let colors = [0xFF0000, 0x00FF00, 0x0000FF].map(|hex| {
200    ///     guard.remove(hex).map(Evicted::leak).unwrap()
201    /// });
202    /// guard.publish();
203    ///
204    /// let [red, green, blue] = colors.map(write.reclaimer());
205    ///
206    /// assert_eq!(red, "red");
207    /// assert_eq!(green, "green");
208    /// assert_eq!(blue, "blue");
209    /// ```
210    #[inline]
211    pub fn reclaimer(&self) -> impl Fn(Leaked<V>) -> V + '_ {
212        self.synchronize();
213        let uid = self.uid;
214        move |leaked| {
215            assert!(uid == leaked.handle_uid, "{LEAKED_VALUE_MISMATCH}");
216            unsafe { Alias::into_owned(leaked.value) }
217        }
218    }
219
220    #[inline]
221    unsafe fn flush_operations(operations: &mut Vec<Operation<K, V>>, map: &mut Map<K, V, S>) {
222        // We do unchecked ops in here since this function benches pretty hot when doing a lot
223        // of writing
224
225        for Operation {
226            raw: mut operation,
227            leaky,
228        } in operations.drain(..)
229        {
230            match operation {
231                RawOperation::InsertUnique(key, value) => {
232                    map.insert_unique_unchecked(key, value);
233                }
234                RawOperation::Replace(ref key, value) => {
235                    let slot =
236                        unsafe { map.get_mut(BorrowHelper::new_ref(key)).unwrap_unchecked() };
237                    if !leaky {
238                        unsafe { Alias::drop(slot) };
239                    }
240                    *slot = value;
241                }
242                RawOperation::Remove(ref key) => {
243                    let (mut k, mut v) = unsafe {
244                        map.remove_entry(BorrowHelper::new_ref(key))
245                            .unwrap_unchecked()
246                    };
247                    unsafe { Alias::drop(&mut k) };
248                    if !leaky {
249                        unsafe { Alias::drop(&mut v) };
250                    }
251                }
252                RawOperation::Drop(ref mut value) => unsafe { Alias::drop(value) },
253            }
254        }
255    }
256}
257
258impl<K, V, S> Drop for WriteHandle<K, V, S>
259where
260    K: Hash + Eq,
261    S: BuildHasher,
262{
263    fn drop(&mut self) {
264        self.synchronize();
265        let map = self.core.writer_map();
266        map.with_mut(|map_ptr| {
267            self.operations.with_mut(|ops_ptr| unsafe {
268                Self::flush_operations(&mut *ops_ptr, &mut *map_ptr)
269            });
270        });
271    }
272}
273
274/// Provides mutable access to the underlying map, and publishes all changes to new readers when
275/// dropped.
276///
277/// See [`WriteHandle::guard`](crate::WriteHandle::guard) for examples. See [`View`](crate::View)
278/// for additional examples and the public API to interact with the underlying map.
279pub struct WriteGuard<'guard, K: Eq + Hash, V, S: BuildHasher = RandomState> {
280    map: &'guard UnsafeCell<Map<K, V, S>>,
281    handle: &'guard WriteHandle<K, V, S>,
282    handle_uid: WriterUid,
283}
284
285impl<'guard, K, V, S> ReadAccess for WriteGuard<'guard, K, V, S>
286where
287    K: Eq + Hash,
288    S: BuildHasher,
289{
290    type Map = Map<K, V, S>;
291
292    #[inline]
293    fn with_map<'read, F, R>(&'read self, op: F) -> R
294    where
295        F: FnOnce(&'read Self::Map) -> R,
296    {
297        self.map.with(|map_ptr| op(unsafe { &*map_ptr }))
298    }
299}
300
301impl<'guard, K, V, S> WriteGuard<'guard, K, V, S>
302where
303    K: Eq + Hash,
304    S: BuildHasher,
305{
306    #[inline]
307    fn with_map_mut<'write, F, R>(&'write mut self, op: F) -> R
308    where
309        F: FnOnce(&'write mut Map<K, V, S>, &'write mut Vec<Operation<K, V>>) -> R,
310    {
311        self.map.with_mut(|map_ptr| {
312            self.handle
313                .operations
314                .with_mut(|ops_ptr| unsafe { op(&mut *map_ptr, &mut *ops_ptr) })
315        })
316    }
317
318    #[inline]
319    pub(crate) fn insert<'ret>(&mut self, key: K, value: V) -> Option<Evicted<'ret, K, V>>
320    where
321        'guard: 'ret,
322    {
323        let value = Alias::new(value);
324
325        let evicted = self.with_map_mut(|map, operations| {
326            match map.raw_entry_mut().from_key(BorrowHelper::new_ref(&key)) {
327                RawEntryMut::Vacant(entry) => {
328                    let key = Alias::new(key);
329                    entry.insert(unsafe { Alias::copy(&key) }, unsafe { Alias::copy(&value) });
330                    operations.push(Operation::new(RawOperation::InsertUnique(key, value)));
331                    None
332                }
333                RawEntryMut::Occupied(mut entry) => {
334                    let old = mem::replace(entry.get_mut(), unsafe { Alias::copy(&value) });
335                    operations.push(Operation::new(RawOperation::Replace(key, value)));
336                    Some(old)
337                }
338            }
339        });
340
341        evicted.map(|alias| unsafe { Evicted::new(self, alias) })
342    }
343
344    #[inline]
345    pub(crate) fn replace<'ret, F>(&mut self, key: K, op: F) -> Option<Evicted<'ret, K, V>>
346    where
347        F: FnOnce(&V) -> V,
348        'guard: 'ret,
349    {
350        let evicted =
351            self.with_map_mut(
352                |map, operations| match map.get_mut(BorrowHelper::new_ref(&key)) {
353                    Some(value) => {
354                        let new_value = Alias::new(op(&**value));
355                        operations.push(Operation::new(RawOperation::Replace(key, unsafe {
356                            Alias::copy(&new_value)
357                        })));
358                        let old_value = mem::replace(value, new_value);
359                        Some(old_value)
360                    }
361                    None => None,
362                },
363            );
364
365        evicted.map(|value| unsafe { Evicted::new(self, value) })
366    }
367
368    #[inline]
369    pub(crate) fn remove<'ret>(&mut self, key: K) -> Option<Evicted<'ret, K, V>>
370    where
371        'guard: 'ret,
372    {
373        let evicted = self.with_map_mut(|map, operations| {
374            let removed = map.remove(BorrowHelper::new_ref(&key));
375
376            if removed.is_some() {
377                operations.push(Operation::new(RawOperation::Remove(key)));
378            }
379
380            removed
381        });
382
383        evicted.map(|value| unsafe { Evicted::new(self, value) })
384    }
385
386    #[inline]
387    pub(crate) fn drop_lazily(&self, leaked: Leaked<V>) {
388        assert!(
389            self.handle_uid == leaked.handle_uid,
390            "{LEAKED_VALUE_MISMATCH}"
391        );
392        self.handle.operations.with_mut(|ops_ptr| {
393            unsafe { &mut *ops_ptr }.push(Operation::new(RawOperation::Drop(Leaked::into_inner(
394                leaked,
395            ))));
396        });
397    }
398
399    #[inline]
400    pub(crate) fn publish(self) {
401        // publishing logic happens on drop
402        drop(self);
403    }
404}
405
406impl<'guard, K, V, S> Drop for WriteGuard<'guard, K, V, S>
407where
408    K: Eq + Hash,
409    S: BuildHasher,
410{
411    fn drop(&mut self) {
412        unsafe { self.handle.core.publish() };
413    }
414}
415
416struct Operation<K, V> {
417    raw: RawOperation<K, V>,
418    leaky: bool,
419}
420
421impl<K, V> Operation<K, V> {
422    #[inline]
423    fn new(raw: RawOperation<K, V>) -> Self {
424        Self { raw, leaky: false }
425    }
426
427    #[inline]
428    fn make_leaky(&mut self) {
429        self.leaky = true;
430    }
431}
432
433enum RawOperation<K, V> {
434    InsertUnique(Alias<K>, Alias<V>),
435    Replace(K, Alias<V>),
436    Remove(K),
437    Drop(Alias<V>),
438}
439
440/// A value which was evicted from a map.
441///
442/// Due to the nature of concurrent data structures, memory often cannot be reclaimed the instant a
443/// writer decides it no longer needs to be used. This goes for `flashmap` as well. When a value is
444/// removed from the map, an `Evicted<'a, V>` is returned. This type only guarantees that the value
445/// is valid for reads for the duration of `'a`, which will never outlive the guard which is
446/// protecting the value. To use the evicted value after the associated guard is dropped, it must
447/// be [`leak`](crate::Evicted::leak)ed, at which point the programmer is responsible for dropping
448/// or claiming ownership of the value. If an evicted value is not leaked, then it will be dropped
449/// at some unspecified point after (or while) the guard is dropped when it is safe to do so.
450///
451/// # Inspecting an evicted value
452///
453/// `Evicted` implements [`Deref`](std::ops::Deref), so you can get immutable access to the
454/// underlying value.
455///
456/// ```
457/// use flashmap::{self, Evicted};
458///
459/// let (mut write, read) = flashmap::new::<u32, u32>();
460/// let mut guard = write.guard();
461///
462/// // Insert a key-value pair
463/// guard.insert(0, 0);
464///
465/// // Evict the entry and its value
466/// let removed: Evicted<'_, u32, u32> = guard.remove(0).unwrap();
467///
468/// // Inspect the evicted value by dereferencing it
469/// assert_eq!(*removed, 0);
470/// ```
471///
472/// # Leaking
473///
474/// To use an evicted value beyond the lifetime of the guard which provides it, you must leak the
475/// value. This also means that you're responsible for manually dropping it. See
476/// [`leak`](crate::Evicted::leak) and [`Leaked`](crate::Leaked) for more information.
477pub struct Evicted<'a, K, V> {
478    leaked: Leaked<V>,
479    operations: &'a UnsafeCell<Vec<Operation<K, V>>>,
480    operation: usize,
481}
482
483impl<'a, K, V> Evicted<'a, K, V> {
484    #[inline]
485    unsafe fn new<S>(guard: &WriteGuard<'a, K, V, S>, value: Alias<V>) -> Self
486    where
487        K: Eq + Hash,
488        S: BuildHasher,
489    {
490        let operations = &guard.handle.operations;
491        let operation = operations.with(|ops_ptr| unsafe { &*ops_ptr }.len() - 1);
492
493        Self {
494            leaked: Leaked {
495                value,
496                handle_uid: guard.handle_uid,
497            },
498            operations,
499            operation,
500        }
501    }
502
503    /// Leaks the contained value, extending its lifetime until it is manually converted into an
504    /// owned value or dropped.
505    ///
506    /// The primary means for safely turning a leaked value into an owned value are through the
507    /// [`reclaim_one`](crate::WriteHandle::reclaim_one) and
508    /// [`reclaimer`](crate::WriteHandle::reclaimer) methods. For dropping a leaked value, you can
509    /// use the [`drop_lazily`](crate::View::drop_lazily) method. For more advanced use, see the
510    /// [`Leaked`](crate::Leaked) type and its associated [`into_inner`](crate::Leaked::into_inner)
511    /// method.
512    ///
513    /// # Examples
514    ///
515    /// ```
516    /// use flashmap::{self, Evicted, Leaked};
517    ///
518    /// let (mut write, read) = flashmap::new::<u32, String>();
519    /// let mut guard = write.guard();
520    ///
521    /// // Insert a couple values
522    /// guard.insert(1, "a".to_owned());
523    /// guard.insert(2, "b".to_owned());
524    ///
525    /// // Evict those values
526    /// let a = guard.remove(1).map(Evicted::leak).unwrap();
527    /// let b = guard.remove(2).map(Evicted::leak).unwrap();
528    ///
529    /// guard.publish();
530    ///
531    /// // Reclaim one
532    /// let a = write.reclaim_one(a);
533    /// assert_eq!(a, "a");
534    ///
535    /// // Lazily drop another
536    /// write.guard().drop_lazily(b);
537    /// ```
538    pub fn leak(evicted: Self) -> Leaked<V> {
539        evicted
540            .operations
541            .with_mut(|ptr| unsafe { (*ptr).get_unchecked_mut(evicted.operation) }.make_leaky());
542
543        evicted.leaked
544    }
545}
546
547impl<K, V> Deref for Evicted<'_, K, V> {
548    type Target = V;
549
550    fn deref(&self) -> &Self::Target {
551        &self.leaked
552    }
553}
554
555/// A leaked value from the map.
556///
557/// Similar to [`Evicted`](crate::Evicted), this type implements [`Deref`](std::ops::Deref),
558/// allowing for immutable access to the underlying value.
559///
560/// This type behaves similarly to [`ManuallyDrop`](std::mem::ManuallyDrop) in that the underlying
561/// value is not dropped if the wrapper is dropped. See [`leak`](crate::Evicted::leak) for how to
562/// safely drop or take ownership of a leaked value. See [`into_inner`](crate::Leaked::into_inner)
563/// for details on how to unsafely take ownership of a leaked value.
564#[must_use = "Not using a leaked value may cause a memory leak"]
565pub struct Leaked<V> {
566    value: Alias<V>,
567    handle_uid: WriterUid,
568}
569
570unsafe impl<V> Send for Leaked<V> where V: Send {}
571unsafe impl<V> Sync for Leaked<V> where V: Sync {}
572
573impl<V> Leaked<V> {
574    /// Consumes this leaked value, providing the inner aliased value. Note that the aliased value
575    /// must be manually dropped via `Alias::`[`drop`](crate::Alias::drop), or converted into an
576    /// owned value via `Alias::`[`into_owned`](crate::Alias::into_owned).
577    ///
578    /// # Examples
579    ///
580    /// ```
581    /// use flashmap::{self, Alias, Evicted, Leaked};
582    ///
583    /// let (mut write, read) = flashmap::new::<u32, Box<u32>>();
584    ///
585    /// write.guard().insert(10, Box::new(20));
586    ///
587    /// // Remove and leak the previously inserted value
588    /// let leaked: Leaked<Box<u32>> = write.guard()
589    ///     .remove(10)
590    ///     .map(Evicted::leak)
591    ///     .unwrap();
592    ///
593    /// // Extract the inner aliased value
594    /// let inner: Alias<Box<u32>> = Leaked::into_inner(leaked);
595    ///
596    /// // Wait until no more readers can access the aliased value
597    /// write.synchronize();
598    ///
599    /// // Safety: we called `synchronize` on the write handle of the map the aliased
600    /// // value came from, so we are guaranteed that we are the only ones accessing the
601    /// // aliased value from this point forward.
602    /// let value = unsafe { Alias::into_owned(inner) };
603    ///
604    /// assert_eq!(*value, 20);
605    /// ```
606    #[must_use = "Not using an aliased value may cause a memory leak"]
607    pub fn into_inner(leaked: Self) -> Alias<V> {
608        leaked.value
609    }
610}
611
612impl<V> Deref for Leaked<V> {
613    type Target = V;
614
615    fn deref(&self) -> &Self::Target {
616        &self.value
617    }
618}