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}