1extern crate alloc;
2
3use core::{
4 cell::Cell,
5 cmp, fmt,
6 hash::{Hash, Hasher},
7 hint,
8 iter::{self, FusedIterator},
9 marker::PhantomData,
10 mem::{self, MaybeUninit},
11 num::NonZeroU32,
12 slice,
13 sync::atomic::{
14 self, AtomicI32, AtomicU32, AtomicUsize,
15 Ordering::{Acquire, Relaxed, Release},
16 },
17};
18pub use slot::Slot;
19use slot::{header_ptr_from_slots, Vec};
20use std::{hash::DefaultHasher, thread};
21
22pub mod hyaline;
23mod slot;
24
25const NIL: u32 = u32::MAX;
27
28const TAG_BITS: u32 = 8;
30
31const TAG_MASK: u32 = (1 << TAG_BITS) - 1;
33
34const STATE_BITS: u32 = 2;
36
37const STATE_MASK: u32 = 0b11 << TAG_BITS;
39
40const VACANT_TAG: u32 = 0b00 << TAG_BITS;
42
43const OCCUPIED_TAG: u32 = 0b01 << TAG_BITS;
45
46const INVALIDATED_TAG: u32 = 0b10 << TAG_BITS;
48
49const RECLAIMED_TAG: u32 = 0b11 << TAG_BITS;
51
52const GENERATION_MASK: u32 = u32::MAX << (TAG_BITS + STATE_BITS);
54
55const ONE_GENERATION: u32 = 1 << (TAG_BITS + STATE_BITS);
57
58static SHARD_COUNT: AtomicUsize = AtomicUsize::new(0);
60
61thread_local! {
62 static SHARD_INDEX: Cell<usize> = const { Cell::new(0) };
64}
65
66pub struct SlotMap<K, V> {
67 inner: SlotMapInner<V>,
68 marker: PhantomData<fn(K) -> K>,
69}
70
71struct SlotMapInner<V> {
72 slots: Vec<V>,
82 collector: hyaline::CollectorHandle,
83}
84
85#[repr(transparent)]
86struct Header {
87 shards: [HeaderShard],
88}
89
90#[repr(align(128))]
91struct HeaderShard {
92 free_list: AtomicU32,
95 len: AtomicI32,
97}
98
99unsafe impl<K, V: Send> Send for SlotMap<K, V> {}
102
103unsafe impl<K, V: Send + Sync> Sync for SlotMap<K, V> {}
108
109impl<V> SlotMap<SlotId, V> {
110 #[must_use]
111 #[track_caller]
112 pub fn new(max_capacity: u32) -> Self {
113 Self::with_key(max_capacity)
114 }
115
116 #[must_use]
122 #[track_caller]
123 pub unsafe fn with_collector(max_capacity: u32, collector: hyaline::CollectorHandle) -> Self {
124 unsafe { Self::with_collector_and_key(max_capacity, collector) }
126 }
127}
128
129impl<K, V> SlotMap<K, V> {
130 #[must_use]
131 #[track_caller]
132 pub fn with_key(max_capacity: u32) -> Self {
133 unsafe { Self::with_collector_and_key(max_capacity, hyaline::CollectorHandle::new()) }
137 }
138
139 #[must_use]
164 #[track_caller]
165 pub unsafe fn with_collector_and_key(
166 max_capacity: u32,
167 collector: hyaline::CollectorHandle,
168 ) -> Self {
169 SlotMap {
170 inner: SlotMapInner {
171 slots: Vec::new(max_capacity),
172 collector,
173 },
174 marker: PhantomData,
175 }
176 }
177
178 #[inline]
179 #[must_use]
180 pub fn capacity(&self) -> u32 {
181 self.inner.slots.capacity()
182 }
183
184 #[inline]
185 #[must_use]
186 pub fn len(&self) -> u32 {
187 self.inner.header().len()
188 }
189
190 #[inline]
191 #[must_use]
192 pub fn is_empty(&self) -> bool {
193 self.len() == 0
194 }
195
196 #[inline]
197 #[must_use]
198 pub fn collector(&self) -> &hyaline::CollectorHandle {
199 &self.inner.collector
200 }
201
202 #[inline]
203 #[must_use]
204 pub fn pin(&self) -> hyaline::Guard<'_> {
205 self.inner.pin()
206 }
207
208 #[inline]
212 #[track_caller]
213 pub fn slots<'a>(&'a self, guard: &'a hyaline::Guard<'a>) -> Slots<'a, V> {
214 self.inner.check_guard(guard);
215
216 Slots {
217 slots: self.inner.slots.iter(),
218 }
219 }
220}
221
222impl<K: Key, V> SlotMap<K, V> {
223 #[inline]
227 #[track_caller]
228 pub fn insert<'a>(&'a self, value: V, guard: &'a hyaline::Guard<'a>) -> K {
229 self.insert_with_tag(value, 0, guard)
230 }
231
232 #[inline]
237 #[track_caller]
238 pub fn insert_with_tag<'a>(&'a self, value: V, tag: u32, guard: &'a hyaline::Guard<'a>) -> K {
239 K::from_id(self.inner.insert_with_tag_with(tag, guard, |_| value))
240 }
241
242 #[inline]
246 #[track_caller]
247 pub fn insert_with<'a>(&'a self, guard: &'a hyaline::Guard<'a>, f: impl FnOnce(K) -> V) -> K {
248 self.insert_with_tag_with(0, guard, f)
249 }
250
251 #[inline]
256 #[track_caller]
257 pub fn insert_with_tag_with<'a>(
258 &'a self,
259 tag: u32,
260 guard: &'a hyaline::Guard<'a>,
261 f: impl FnOnce(K) -> V,
262 ) -> K {
263 let f = |id| f(K::from_id(id));
264
265 K::from_id(self.inner.insert_with_tag_with(tag, guard, f))
266 }
267
268 #[inline]
269 pub fn insert_mut(&mut self, value: V) -> K {
270 self.insert_with_tag_mut(value, 0)
271 }
272
273 #[inline]
277 #[track_caller]
278 pub fn insert_with_tag_mut(&mut self, value: V, tag: u32) -> K {
279 K::from_id(self.inner.insert_with_tag_with_mut(tag, |_| value))
280 }
281
282 #[inline]
283 pub fn insert_with_mut(&mut self, f: impl FnOnce(K) -> V) -> K {
284 self.insert_with_tag_with_mut(0, f)
285 }
286
287 #[inline]
291 #[track_caller]
292 pub fn insert_with_tag_with_mut(&mut self, tag: u32, f: impl FnOnce(K) -> V) -> K {
293 let f = |id| f(K::from_id(id));
294
295 K::from_id(self.inner.insert_with_tag_with_mut(tag, f))
296 }
297
298 #[inline]
302 #[track_caller]
303 pub fn remove<'a>(&'a self, key: K, guard: &'a hyaline::Guard<'a>) -> Option<&'a V> {
304 self.inner.remove(key.as_id(), guard)
305 }
306
307 #[inline]
308 pub fn remove_mut(&mut self, key: K) -> Option<V> {
309 self.inner.remove_mut(key.as_id())
310 }
311
312 #[inline]
317 #[track_caller]
318 pub unsafe fn remove_unchecked<'a>(&'a self, key: K, guard: &'a hyaline::Guard<'a>) -> &'a V {
319 unsafe { self.inner.remove_unchecked(key.as_id(), guard) }
321 }
322
323 #[cfg(test)]
324 fn remove_index<'a>(&'a self, index: u32, guard: &'a hyaline::Guard<'a>) -> Option<&'a V> {
325 self.inner.remove_index(index, guard)
326 }
327
328 #[inline]
329 #[track_caller]
330 pub fn invalidate<'a>(&'a self, key: K, guard: &'a hyaline::Guard<'a>) -> Option<&'a V> {
331 self.inner.invalidate(key.as_id(), guard)
332 }
333
334 #[inline]
335 pub fn remove_invalidated(&self, key: K) -> Option<()> {
336 self.inner.remove_invalidated(key.as_id())
337 }
338
339 #[inline]
344 pub unsafe fn remove_invalidated_unchecked(&self, key: K) {
345 unsafe { self.inner.remove_invalidated_unchecked(key.as_id()) };
347 }
348
349 #[inline(always)]
353 #[must_use]
354 #[track_caller]
355 pub fn get<'a>(&'a self, key: K, guard: &'a hyaline::Guard<'a>) -> Option<&'a V> {
356 self.inner.get(key.as_id(), guard)
357 }
358
359 #[inline(always)]
360 #[must_use]
361 pub fn get_mut(&mut self, key: K) -> Option<&mut V> {
362 self.inner.get_mut(key.as_id())
363 }
364
365 #[inline]
366 #[must_use]
367 pub fn get_disjoint_mut<const N: usize>(&mut self, keys: [K; N]) -> Option<[&mut V; N]> {
368 self.inner.get_disjoint_mut(keys.map(Key::as_id))
369 }
370
371 #[cfg(test)]
372 fn index<'a>(&'a self, index: u32, guard: &'a hyaline::Guard<'a>) -> Option<&'a V> {
373 self.inner.index(index, guard)
374 }
375
376 #[inline(always)]
384 #[must_use]
385 #[track_caller]
386 pub unsafe fn get_unchecked<'a>(&'a self, key: K, guard: &'a hyaline::Guard<'a>) -> &'a V {
387 unsafe { self.inner.get_unchecked(key.as_id(), guard) }
389 }
390
391 #[inline(always)]
395 #[must_use]
396 pub unsafe fn get_unchecked_mut(&mut self, key: K) -> &mut V {
397 unsafe { self.inner.get_unchecked_mut(key.as_id()) }
399 }
400
401 #[inline]
405 #[must_use]
406 #[track_caller]
407 pub fn iter<'a>(&'a self, guard: &'a hyaline::Guard<'a>) -> Iter<'a, K, V> {
408 self.inner.check_guard(guard);
409
410 Iter {
411 slots: self.inner.slots.iter().enumerate(),
412 marker: PhantomData,
413 }
414 }
415
416 #[inline]
417 #[must_use]
418 pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
419 IterMut {
420 slots: self.inner.slots.iter_mut().enumerate(),
421 marker: PhantomData,
422 }
423 }
424}
425
426impl<K: Key, V> SlotMap<K, MaybeUninit<V>> {
427 #[inline]
431 #[track_caller]
432 pub fn revive_or_insert_with<'a>(
433 &'a self,
434 guard: &'a hyaline::Guard<'a>,
435 f: impl FnOnce(K) -> MaybeUninit<V>,
436 ) -> (K, &'a MaybeUninit<V>) {
437 let f = |id| f(K::from_id(id));
438
439 let (id, value) = self.inner.revive_or_insert_with(guard, f);
440
441 (K::from_id(id), value)
442 }
443}
444
445impl<V> SlotMapInner<V> {
446 fn pin(&self) -> hyaline::Guard<'_> {
447 unsafe { self.collector.pin() }
449 }
450
451 #[track_caller]
452 fn insert_with_tag_with<'a>(
453 &'a self,
454 tag: u32,
455 guard: &'a hyaline::Guard<'a>,
456 f: impl FnOnce(SlotId) -> V,
457 ) -> SlotId {
458 assert_eq!(tag & !TAG_MASK, 0);
459
460 let id = if let Some((id, slot)) = self.allocate_slot(tag, guard) {
461 unsafe { slot.value.get().cast::<V>().write(f(id)) };
465
466 slot.generation.store(id.generation(), Release);
467
468 id
469 } else {
470 self.slots.push_with_tag_with(tag, f).0
471 };
472
473 self.header().shard().len.fetch_add(1, Relaxed);
474
475 id
476 }
477
478 #[track_caller]
479 fn allocate_slot<'a>(
480 &'a self,
481 tag: u32,
482 guard: &'a hyaline::Guard<'a>,
483 ) -> Option<(SlotId, &'a Slot<V>)> {
484 self.check_guard(guard);
485
486 'outer: for shard in self.header().shards() {
487 let mut free_list_head = shard.free_list.load(Acquire);
488 let mut backoff = Backoff::new();
489
490 loop {
491 if free_list_head == NIL {
492 continue 'outer;
493 }
494
495 let slot = unsafe { self.slots.get_unchecked(free_list_head) };
498
499 let next_free = slot.next_free.load(Relaxed);
500
501 match shard.free_list.compare_exchange_weak(
502 free_list_head,
503 next_free,
504 Release,
505 Acquire,
506 ) {
507 Ok(_) => {
508 let generation = slot.generation.load(Relaxed);
509
510 debug_assert!(generation & STATE_MASK == VACANT_TAG);
511
512 let new_generation = generation | OCCUPIED_TAG | tag;
513
514 let id = unsafe { SlotId::new_unchecked(free_list_head, new_generation) };
517
518 return Some((id, slot));
519 }
520 Err(new_head) => {
521 free_list_head = new_head;
522 backoff.spin();
523 }
524 }
525 }
526 }
527
528 None
529 }
530
531 #[track_caller]
532 fn insert_with_tag_with_mut(&mut self, tag: u32, f: impl FnOnce(SlotId) -> V) -> SlotId {
533 assert_eq!(tag & !TAG_MASK, 0);
534
535 let header = unsafe { mem::transmute::<&mut Header, &mut Header>(self.slots.header_mut()) };
539
540 for shard in header.shards_mut() {
541 let free_list_head = *shard.free_list.get_mut();
542
543 if free_list_head != NIL {
544 let slot = unsafe { self.slots.get_unchecked_mut(free_list_head) };
547
548 *shard.free_list.get_mut() = *slot.next_free.get_mut();
549
550 let generation = *slot.generation.get_mut();
551
552 debug_assert!(generation & STATE_MASK == VACANT_TAG);
553
554 let new_generation = generation | OCCUPIED_TAG | tag;
555
556 let id = unsafe { SlotId::new_unchecked(free_list_head, new_generation) };
559
560 *slot.value.get_mut() = MaybeUninit::new(f(id));
561
562 *slot.generation.get_mut() = new_generation;
563
564 let len = header.shard_mut().len.get_mut();
565 *len = len.wrapping_add(1);
566
567 return id;
568 }
569 }
570
571 let id = self.slots.push_with_tag_with_mut(tag, f);
572
573 let len = header.shard_mut().len.get_mut();
574 *len = len.wrapping_add(1);
575
576 id
577 }
578
579 #[track_caller]
580 fn remove<'a>(&'a self, id: SlotId, guard: &'a hyaline::Guard<'a>) -> Option<&'a V> {
581 self.check_guard(guard);
582
583 let slot = self.slots.get(id.index)?;
584 let new_generation = (id.generation() & GENERATION_MASK).wrapping_add(ONE_GENERATION);
585
586 if slot
587 .generation
588 .compare_exchange(id.generation(), new_generation, Acquire, Relaxed)
589 .is_err()
590 {
591 return None;
592 }
593
594 self.header().shard().len.fetch_sub(1, Relaxed);
595
596 unsafe { guard.defer_reclaim(id.index, &self.slots) };
599
600 Some(unsafe { slot.value_unchecked() })
608 }
609
610 fn remove_mut(&mut self, id: SlotId) -> Option<V> {
611 let header = unsafe { mem::transmute::<&mut Header, &mut Header>(self.slots.header_mut()) };
615
616 let slot = self.slots.get_mut(id.index)?;
617 let generation = *slot.generation.get_mut();
618
619 if generation == id.generation() {
620 let new_generation = (generation & GENERATION_MASK).wrapping_add(ONE_GENERATION);
621 *slot.generation.get_mut() = new_generation;
622
623 *slot.next_free.get_mut() = *header.shard_mut().free_list.get_mut();
624 *header.shard_mut().free_list.get_mut() = id.index;
625
626 let len = header.shard_mut().len.get_mut();
627 *len = len.wrapping_sub(1);
628
629 Some(unsafe { slot.value.get().cast::<V>().read() })
637 } else {
638 None
639 }
640 }
641
642 #[track_caller]
643 unsafe fn remove_unchecked<'a>(&'a self, id: SlotId, guard: &'a hyaline::Guard<'a>) -> &'a V {
644 self.check_guard(guard);
645
646 let slot = unsafe { self.slots.get_unchecked(id.index) };
648
649 let new_generation = (id.generation() & GENERATION_MASK).wrapping_add(ONE_GENERATION);
650
651 let generation = slot.generation.swap(new_generation, Acquire);
652
653 assert_unsafe_precondition!(
654 is_occupied(generation),
655 "`id` must refer to a currently occupied slot",
656 );
657
658 self.header().shard().len.fetch_sub(1, Relaxed);
659
660 unsafe { guard.defer_reclaim(id.index, &self.slots) };
663
664 unsafe { slot.value_unchecked() }
671 }
672
673 #[cfg(test)]
674 fn remove_index<'a>(&'a self, index: u32, guard: &'a hyaline::Guard<'a>) -> Option<&'a V> {
675 self.check_guard(guard);
676
677 let slot = self.slots.get(index)?;
678 let mut generation = slot.generation.load(Relaxed);
679
680 loop {
681 if !is_occupied(generation) {
682 return None;
683 }
684
685 let new_generation = (generation & GENERATION_MASK).wrapping_add(ONE_GENERATION);
686
687 match slot.generation.compare_exchange_weak(
688 generation,
689 new_generation,
690 Acquire,
691 Relaxed,
692 ) {
693 Ok(_) => break,
694 Err(new_generation) => generation = new_generation,
695 }
696 }
697
698 self.header().shard().len.fetch_sub(1, Relaxed);
699
700 unsafe { guard.defer_reclaim(index, &self.slots) };
703
704 Some(unsafe { slot.value_unchecked() })
712 }
713
714 #[track_caller]
715 fn invalidate<'a>(&'a self, id: SlotId, guard: &'a hyaline::Guard<'a>) -> Option<&'a V> {
716 self.check_guard(guard);
717
718 let slot = self.slots.get(id.index)?;
719 let new_generation = (id.generation() & !STATE_MASK) | INVALIDATED_TAG;
720
721 if slot
722 .generation
723 .compare_exchange(id.generation(), new_generation, Acquire, Relaxed)
724 .is_err()
725 {
726 return None;
727 }
728
729 self.header().shard().len.fetch_sub(1, Relaxed);
730
731 unsafe { guard.defer_reclaim_invalidated(id.index, &self.slots) };
734
735 Some(unsafe { slot.value_unchecked() })
743 }
744
745 fn remove_invalidated(&self, id: SlotId) -> Option<()> {
746 let slot = self.slots.get(id.index)?;
747 let mut generation = slot.generation.load(Relaxed);
748 let new_generation = (id.generation() & GENERATION_MASK).wrapping_add(ONE_GENERATION);
749
750 loop {
751 if generation & !STATE_MASK != id.generation() & !STATE_MASK {
752 break None;
753 }
754
755 if generation & STATE_MASK == RECLAIMED_TAG {
756 match slot.generation.compare_exchange_weak(
757 generation,
758 new_generation,
759 Acquire,
760 Relaxed,
761 ) {
762 Ok(_) => {
763 unsafe { reclaim(id.index, self.slots.as_ptr()) };
775
776 break Some(());
777 }
778 Err(new_generation) => generation = new_generation,
779 }
780 } else if generation & STATE_MASK == INVALIDATED_TAG {
781 match slot.generation.compare_exchange_weak(
782 generation,
783 new_generation,
784 Relaxed,
785 Relaxed,
786 ) {
787 Ok(_) => break Some(()),
788 Err(new_generation) => generation = new_generation,
789 }
790 } else {
791 break None;
792 }
793 }
794 }
795
796 unsafe fn remove_invalidated_unchecked(&self, id: SlotId) {
797 let slot = unsafe { self.slots.get_unchecked(id.index) };
799
800 let new_generation = (id.generation() & GENERATION_MASK).wrapping_add(ONE_GENERATION);
801
802 let generation = slot.generation.swap(new_generation, Relaxed);
803
804 assert_unsafe_precondition!(
805 generation & STATE_MASK == RECLAIMED_TAG || generation & STATE_MASK == INVALIDATED_TAG,
806 "`id` must refer to a currently invalidated slot",
807 );
808
809 if generation & STATE_MASK == RECLAIMED_TAG {
810 atomic::fence(Acquire);
811
812 unsafe { reclaim(id.index, self.slots.as_ptr()) };
824 }
825 }
826
827 #[inline(always)]
828 #[track_caller]
829 fn get<'a>(&'a self, id: SlotId, guard: &'a hyaline::Guard<'a>) -> Option<&'a V> {
830 self.check_guard(guard);
831
832 let slot = self.slots.get(id.index)?;
833 let generation = slot.generation.load(Acquire);
834
835 if generation == id.generation() {
836 Some(unsafe { slot.value_unchecked() })
844 } else {
845 None
846 }
847 }
848
849 #[inline(always)]
850 fn get_mut(&mut self, id: SlotId) -> Option<&mut V> {
851 let slot = self.slots.get_mut(id.index)?;
852 let generation = *slot.generation.get_mut();
853
854 if generation == id.generation() {
855 Some(unsafe { slot.value_unchecked_mut() })
861 } else {
862 None
863 }
864 }
865
866 #[inline]
867 fn get_disjoint_mut<const N: usize>(&mut self, ids: [SlotId; N]) -> Option<[&mut V; N]> {
868 fn get_disjoint_check_valid<const N: usize>(ids: &[SlotId; N], len: u32) -> bool {
869 let mut valid = true;
870
871 for (i, id) in ids.iter().enumerate() {
872 valid &= id.index < len;
873
874 for id2 in &ids[..i] {
875 valid &= id.index != id2.index;
876 }
877 }
878
879 valid
880 }
881
882 let len = self.slots.capacity_mut();
883
884 if get_disjoint_check_valid(&ids, len) {
885 unsafe { self.get_disjoint_unchecked_mut(ids) }
887 } else {
888 None
889 }
890 }
891
892 #[inline]
893 unsafe fn get_disjoint_unchecked_mut<const N: usize>(
894 &mut self,
895 ids: [SlotId; N],
896 ) -> Option<[&mut V; N]> {
897 let mut refs = MaybeUninit::<[&mut V; N]>::uninit();
898 let refs_ptr = refs.as_mut_ptr().cast::<&mut V>();
899
900 for i in 0..N {
901 let id = unsafe { ids.get_unchecked(i) };
903
904 let slot = unsafe { self.slots.get_unchecked_mut(id.index) };
909
910 let slot = unsafe { mem::transmute::<&mut Slot<V>, &mut Slot<V>>(slot) };
914
915 let generation = *slot.generation.get_mut();
916
917 if generation != id.generation() {
918 return None;
919 }
920
921 let value = unsafe { slot.value_unchecked_mut() };
927
928 unsafe { *refs_ptr.add(i) = value };
930 }
931
932 Some(unsafe { refs.assume_init() })
934 }
935
936 #[cfg(test)]
937 fn index<'a>(&'a self, index: u32, guard: &'a hyaline::Guard<'a>) -> Option<&'a V> {
938 self.check_guard(guard);
939
940 let slot = self.slots.get(index)?;
941 let generation = slot.generation.load(Acquire);
942
943 if is_occupied(generation) {
944 Some(unsafe { slot.value_unchecked() })
951 } else {
952 None
953 }
954 }
955
956 #[inline(always)]
957 #[track_caller]
958 unsafe fn get_unchecked<'a>(&'a self, id: SlotId, guard: &'a hyaline::Guard<'a>) -> &'a V {
959 self.check_guard(guard);
960
961 let slot = unsafe { self.slots.get_unchecked(id.index) };
963
964 let _generation = slot.generation.load(Acquire);
965
966 unsafe { slot.value_unchecked() }
972 }
973
974 #[inline(always)]
975 unsafe fn get_unchecked_mut(&mut self, id: SlotId) -> &mut V {
976 let slot = unsafe { self.slots.get_unchecked_mut(id.index) };
978
979 unsafe { slot.value_unchecked_mut() }
983 }
984
985 #[inline]
986 fn collector(&self) -> &hyaline::CollectorHandle {
987 &self.collector
988 }
989
990 #[inline]
991 fn header(&self) -> &Header {
992 self.slots.header()
993 }
994
995 #[inline(always)]
996 #[track_caller]
997 fn check_guard(&self, guard: &hyaline::Guard<'_>) {
998 #[inline(never)]
999 #[track_caller]
1000 fn collector_mismatch() -> ! {
1001 panic!("the given guard does not belong to this collection");
1002 }
1003
1004 if guard.collector() != self.collector() {
1005 collector_mismatch();
1006 }
1007 }
1008}
1009
1010impl<V> SlotMapInner<MaybeUninit<V>> {
1011 #[track_caller]
1012 fn revive_or_insert_with<'a>(
1013 &'a self,
1014 guard: &'a hyaline::Guard<'a>,
1015 f: impl FnOnce(SlotId) -> MaybeUninit<V>,
1016 ) -> (SlotId, &'a MaybeUninit<V>) {
1017 let (id, slot) = if let Some((id, slot)) = self.allocate_slot(0, guard) {
1018 slot.generation.store(id.generation(), Release);
1019
1020 (id, slot)
1021 } else {
1022 self.slots.push_with_tag_with(0, f)
1023 };
1024
1025 self.header().shard().len.fetch_add(1, Relaxed);
1026
1027 (id, unsafe { slot.value_unchecked() })
1029 }
1030}
1031
1032unsafe fn reclaim<V>(index: u32, slots: *const Slot<V>) {
1033 let slot = unsafe { &*slots.add(index as usize) };
1036
1037 unsafe { slot.value.get().cast::<V>().drop_in_place() };
1039
1040 let header = unsafe { &*header_ptr_from_slots(slots.cast()) };
1043
1044 let shard = header.shard();
1045
1046 let mut free_list_head = shard.free_list.load(Acquire);
1047 let mut backoff = Backoff::new();
1048
1049 loop {
1050 slot.next_free.store(free_list_head, Relaxed);
1051
1052 match shard
1053 .free_list
1054 .compare_exchange_weak(free_list_head, index, Release, Acquire)
1055 {
1056 Ok(_) => break,
1057 Err(new_head) => {
1058 free_list_head = new_head;
1059 backoff.spin();
1060 }
1061 }
1062 }
1063}
1064
1065unsafe fn reclaim_invalidated<V>(index: u32, slots: *const Slot<V>) {
1066 let slot = unsafe { &*slots.add(index as usize) };
1069
1070 let mut generation = slot.generation.load(Relaxed);
1071
1072 while generation & STATE_MASK == INVALIDATED_TAG {
1073 let new_generation = (generation & !STATE_MASK) | RECLAIMED_TAG;
1074
1075 match slot
1076 .generation
1077 .compare_exchange_weak(generation, new_generation, Relaxed, Relaxed)
1078 {
1079 Ok(_) => return,
1080 Err(new_generation) => generation = new_generation,
1081 }
1082 }
1083
1084 debug_assert!(generation & STATE_MASK == VACANT_TAG);
1085
1086 atomic::fence(Acquire);
1087
1088 unsafe { reclaim(index, slots) };
1096}
1097
1098impl<K: fmt::Debug + Key, V: fmt::Debug> fmt::Debug for SlotMap<K, V> {
1099 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1100 f.debug_struct("SlotMap").finish_non_exhaustive()
1101 }
1102}
1103
1104impl<V> Drop for SlotMapInner<V> {
1105 fn drop(&mut self) {
1106 if !core::mem::needs_drop::<V>() {
1107 return;
1108 }
1109
1110 for slot in self.slots.iter_mut() {
1111 if *slot.generation.get_mut() & STATE_MASK != VACANT_TAG {
1112 let ptr = slot.value.get_mut().as_mut_ptr();
1113
1114 unsafe { ptr.drop_in_place() };
1119 }
1120 }
1121 }
1122}
1123
1124impl<'a, K: Key, V> IntoIterator for &'a mut SlotMap<K, V> {
1125 type Item = (K, &'a mut V);
1126
1127 type IntoIter = IterMut<'a, K, V>;
1128
1129 #[inline]
1130 fn into_iter(self) -> Self::IntoIter {
1131 self.iter_mut()
1132 }
1133}
1134
1135impl Header {
1136 #[inline]
1137 fn shard(&self) -> &HeaderShard {
1138 let shard_index = SHARD_INDEX.with(Cell::get);
1139
1140 unsafe { self.shards.get_unchecked(shard_index) }
1142 }
1143
1144 #[inline]
1145 fn shard_mut(&mut self) -> &mut HeaderShard {
1146 unsafe { self.shards.get_unchecked_mut(0) }
1148 }
1149
1150 #[inline]
1151 fn shards(&self) -> HeaderShards<'_> {
1152 let shard_index = SHARD_INDEX.with(Cell::get);
1153
1154 HeaderShards {
1155 shards: &self.shards,
1156 shard_index,
1157 yielded: 0,
1158 }
1159 }
1160
1161 #[inline]
1162 fn shards_mut(&mut self) -> slice::IterMut<'_, HeaderShard> {
1163 self.shards.iter_mut()
1164 }
1165
1166 #[inline]
1167 fn len(&self) -> u32 {
1168 self.shards()
1169 .map(|shard| shard.len.load(Relaxed))
1170 .sum::<i32>()
1171 .try_into()
1172 .unwrap_or(0)
1173 }
1174}
1175
1176struct HeaderShards<'a> {
1177 shards: &'a [HeaderShard],
1178 shard_index: usize,
1179 yielded: usize,
1180}
1181
1182impl<'a> Iterator for HeaderShards<'a> {
1183 type Item = &'a HeaderShard;
1184
1185 #[inline]
1186 fn next(&mut self) -> Option<Self::Item> {
1187 if self.yielded < self.shards.len() {
1188 let current_index = (self.shard_index + self.yielded) & (self.shards.len() - 1);
1189 self.yielded += 1;
1190
1191 Some(unsafe { self.shards.get_unchecked(current_index) })
1194 } else {
1195 None
1196 }
1197 }
1198}
1199
1200#[inline(never)]
1201fn set_shard_index() {
1202 let mut state = DefaultHasher::new();
1203 thread::current().id().hash(&mut state);
1204 let thread_id_hash = state.finish();
1205
1206 let shard_count = SHARD_COUNT.load(Relaxed);
1207 let shard_index = (thread_id_hash & (shard_count as u64 - 1)) as usize;
1208 SHARD_INDEX.with(|cell| cell.set(shard_index));
1209}
1210
1211pub trait Key: Sized {
1212 fn from_id(id: SlotId) -> Self;
1213
1214 #[allow(clippy::wrong_self_convention)]
1215 fn as_id(self) -> SlotId;
1216}
1217
1218impl Key for SlotId {
1219 #[inline(always)]
1220 fn from_id(id: SlotId) -> Self {
1221 id
1222 }
1223
1224 #[inline(always)]
1225 fn as_id(self) -> SlotId {
1226 self
1227 }
1228}
1229
1230#[derive(Clone, Copy)]
1231#[repr(C, align(8))]
1232pub struct SlotId {
1233 #[cfg(target_endian = "little")]
1234 index: u32,
1235 generation: NonZeroU32,
1236 #[cfg(target_endian = "big")]
1237 index: u32,
1238}
1239
1240impl Default for SlotId {
1241 #[inline]
1242 fn default() -> Self {
1243 Self::INVALID
1244 }
1245}
1246
1247impl SlotId {
1248 pub const INVALID: Self = SlotId {
1249 index: u32::MAX,
1250 generation: NonZeroU32::MAX,
1251 };
1252
1253 pub const TAG_BITS: u32 = TAG_BITS;
1254
1255 pub const TAG_MASK: u32 = TAG_MASK;
1256
1257 pub const STATE_BITS: u32 = STATE_BITS;
1258
1259 pub const STATE_MASK: u32 = STATE_MASK;
1260
1261 pub const OCCUPIED_TAG: u32 = OCCUPIED_TAG;
1262
1263 #[inline(always)]
1264 #[must_use]
1265 #[track_caller]
1266 pub const fn new(index: u32, generation: u32) -> Self {
1267 assert!(is_occupied(generation));
1268
1269 unsafe { SlotId::new_unchecked(index, generation) }
1271 }
1272
1273 #[inline(always)]
1280 #[must_use]
1281 pub const unsafe fn new_unchecked(index: u32, generation: u32) -> Self {
1282 debug_assert!(is_occupied(generation));
1284
1285 let generation = unsafe { NonZeroU32::new_unchecked(generation) };
1287
1288 SlotId { index, generation }
1289 }
1290
1291 #[inline(always)]
1292 #[must_use]
1293 pub const fn index(self) -> u32 {
1294 self.index
1295 }
1296
1297 #[inline(always)]
1298 #[must_use]
1299 pub const fn generation(self) -> u32 {
1300 self.generation.get()
1301 }
1302
1303 #[inline(always)]
1304 #[must_use]
1305 pub const fn tag(self) -> u32 {
1306 self.generation.get() & TAG_MASK
1307 }
1308
1309 #[inline]
1310 fn as_u64(self) -> u64 {
1311 u64::from(self.index) | (u64::from(self.generation.get()) << 32)
1312 }
1313}
1314
1315impl fmt::Debug for SlotId {
1316 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1317 if *self == Self::INVALID {
1318 return f.write_str("INVALID");
1319 }
1320
1321 let generation = self.generation() >> (TAG_BITS + STATE_BITS);
1322 write!(f, "{}v{}", self.index, generation)?;
1323
1324 if self.generation() & TAG_MASK != 0 {
1325 write!(f, "t{}", self.generation() & TAG_MASK)?;
1326 }
1327
1328 Ok(())
1329 }
1330}
1331
1332impl PartialEq for SlotId {
1333 #[inline]
1334 fn eq(&self, other: &Self) -> bool {
1335 self.as_u64() == other.as_u64()
1336 }
1337}
1338
1339impl Eq for SlotId {}
1340
1341impl Hash for SlotId {
1342 #[inline]
1343 fn hash<H: Hasher>(&self, state: &mut H) {
1344 self.as_u64().hash(state);
1345 }
1346}
1347
1348impl PartialOrd for SlotId {
1349 #[inline]
1350 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
1351 Some(self.cmp(other))
1352 }
1353}
1354
1355impl Ord for SlotId {
1356 #[inline]
1357 fn cmp(&self, other: &Self) -> cmp::Ordering {
1358 self.as_u64().cmp(&other.as_u64())
1359 }
1360}
1361
1362#[macro_export]
1363macro_rules! declare_key {
1364 (
1365 $(#[$meta:meta])*
1366 $vis:vis struct $name:ident $(;)?
1367 ) => {
1368 $(#[$meta])*
1369 #[repr(transparent)]
1370 $vis struct $name($crate::SlotId);
1371
1372 impl $crate::Key for $name {
1373 #[inline(always)]
1374 fn from_id(id: $crate::SlotId) -> Self {
1375 $name(id)
1376 }
1377
1378 #[inline(always)]
1379 fn as_id(self) -> $crate::SlotId {
1380 self.0
1381 }
1382 }
1383 };
1384}
1385
1386pub struct Iter<'a, K, V> {
1387 slots: iter::Enumerate<slice::Iter<'a, Slot<V>>>,
1388 marker: PhantomData<fn(K) -> K>,
1389}
1390
1391impl<K, V: fmt::Debug> fmt::Debug for Iter<'_, K, V> {
1392 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1393 f.debug_struct("Iter").finish_non_exhaustive()
1394 }
1395}
1396
1397impl<'a, K: Key, V> Iterator for Iter<'a, K, V> {
1398 type Item = (K, &'a V);
1399
1400 #[inline]
1401 fn next(&mut self) -> Option<Self::Item> {
1402 loop {
1403 let (index, slot) = self.slots.next()?;
1404 let generation = slot.generation.load(Acquire);
1405
1406 if is_occupied(generation) {
1407 #[allow(clippy::cast_possible_truncation)]
1409 let index = index as u32;
1410
1411 let id = unsafe { SlotId::new_unchecked(index, generation) };
1413
1414 let r = unsafe { slot.value_unchecked() };
1421
1422 break Some((K::from_id(id), r));
1423 }
1424 }
1425 }
1426
1427 #[inline]
1428 fn size_hint(&self) -> (usize, Option<usize>) {
1429 (0, Some(self.slots.len()))
1430 }
1431}
1432
1433impl<K: Key, V> DoubleEndedIterator for Iter<'_, K, V> {
1434 #[inline]
1435 fn next_back(&mut self) -> Option<Self::Item> {
1436 loop {
1437 let (index, slot) = self.slots.next_back()?;
1438 let generation = slot.generation.load(Acquire);
1439
1440 if is_occupied(generation) {
1441 #[allow(clippy::cast_possible_truncation)]
1443 let index = index as u32;
1444
1445 let id = unsafe { SlotId::new_unchecked(index, generation) };
1447
1448 let r = unsafe { slot.value_unchecked() };
1455
1456 break Some((K::from_id(id), r));
1457 }
1458 }
1459 }
1460}
1461
1462impl<K: Key, V> FusedIterator for Iter<'_, K, V> {}
1463
1464pub struct IterMut<'a, K, V> {
1465 slots: iter::Enumerate<slice::IterMut<'a, Slot<V>>>,
1466 marker: PhantomData<fn(K) -> K>,
1467}
1468
1469impl<K, V: fmt::Debug> fmt::Debug for IterMut<'_, K, V> {
1470 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1471 f.debug_struct("IterMut").finish_non_exhaustive()
1472 }
1473}
1474
1475impl<'a, K: Key, V> Iterator for IterMut<'a, K, V> {
1476 type Item = (K, &'a mut V);
1477
1478 #[inline]
1479 fn next(&mut self) -> Option<Self::Item> {
1480 loop {
1481 let (index, slot) = self.slots.next()?;
1482 let generation = *slot.generation.get_mut();
1483
1484 if is_occupied(generation) {
1485 #[allow(clippy::cast_possible_truncation)]
1487 let index = index as u32;
1488
1489 let id = unsafe { SlotId::new_unchecked(index, generation) };
1491
1492 let r = unsafe { slot.value_unchecked_mut() };
1495
1496 break Some((K::from_id(id), r));
1497 }
1498 }
1499 }
1500
1501 #[inline]
1502 fn size_hint(&self) -> (usize, Option<usize>) {
1503 (0, Some(self.slots.len()))
1504 }
1505}
1506
1507impl<K: Key, V> DoubleEndedIterator for IterMut<'_, K, V> {
1508 #[inline]
1509 fn next_back(&mut self) -> Option<Self::Item> {
1510 loop {
1511 let (index, slot) = self.slots.next_back()?;
1512 let generation = *slot.generation.get_mut();
1513
1514 if is_occupied(generation) {
1515 #[allow(clippy::cast_possible_truncation)]
1517 let index = index as u32;
1518
1519 let id = unsafe { SlotId::new_unchecked(index, generation) };
1521
1522 let r = unsafe { slot.value_unchecked_mut() };
1525
1526 break Some((K::from_id(id), r));
1527 }
1528 }
1529 }
1530}
1531
1532impl<K: Key, V> FusedIterator for IterMut<'_, K, V> {}
1533
1534pub struct Slots<'a, V> {
1535 slots: slice::Iter<'a, Slot<V>>,
1536}
1537
1538impl<V: fmt::Debug> fmt::Debug for Slots<'_, V> {
1539 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1540 f.debug_struct("Slots").finish_non_exhaustive()
1541 }
1542}
1543
1544impl<'a, V> Iterator for Slots<'a, V> {
1545 type Item = &'a Slot<V>;
1546
1547 #[inline]
1548 fn next(&mut self) -> Option<Self::Item> {
1549 self.slots.next()
1550 }
1551
1552 #[inline]
1553 fn size_hint(&self) -> (usize, Option<usize>) {
1554 self.slots.size_hint()
1555 }
1556}
1557
1558impl<V> DoubleEndedIterator for Slots<'_, V> {
1559 #[inline]
1560 fn next_back(&mut self) -> Option<Self::Item> {
1561 self.slots.next_back()
1562 }
1563}
1564
1565impl<V> FusedIterator for Slots<'_, V> {}
1566
1567const fn is_occupied(generation: u32) -> bool {
1568 generation & STATE_MASK == OCCUPIED_TAG
1569}
1570
1571const SPIN_LIMIT: u32 = 6;
1572
1573struct Backoff {
1574 step: u32,
1575}
1576
1577impl Backoff {
1578 fn new() -> Self {
1579 Backoff { step: 0 }
1580 }
1581
1582 fn spin(&mut self) {
1583 for _ in 0..1 << self.step {
1584 hint::spin_loop();
1585 }
1586
1587 if self.step <= SPIN_LIMIT {
1588 self.step += 1;
1589 }
1590 }
1591}
1592
1593macro_rules! assert_unsafe_precondition {
1594 ($condition:expr, $message:expr $(,)?) => {
1595 if cfg!(debug_assertions) {
1598 if !$condition {
1599 crate::panic_nounwind(concat!("unsafe precondition(s) validated: ", $message));
1600 }
1601 }
1602 };
1603}
1604use assert_unsafe_precondition;
1605
1606#[cold]
1608#[inline(never)]
1609fn panic_nounwind(message: &'static str) -> ! {
1610 struct UnwindGuard;
1611
1612 impl Drop for UnwindGuard {
1613 fn drop(&mut self) {
1614 panic!();
1615 }
1616 }
1617
1618 let _guard = UnwindGuard;
1619 std::panic::panic_any(message);
1620}
1621
1622#[cfg(test)]
1623mod tests {
1624 use super::*;
1625 use std::thread;
1626
1627 #[test]
1628 fn basic_usage1() {
1629 let map = SlotMap::new(10);
1630 let guard = &map.pin();
1631
1632 let x = map.insert(69, guard);
1633 let y = map.insert(42, guard);
1634
1635 assert_eq!(map.get(x, guard), Some(&69));
1636 assert_eq!(map.get(y, guard), Some(&42));
1637
1638 map.remove(x, guard);
1639
1640 let x2 = map.insert(12, guard);
1641
1642 assert_eq!(map.get(x2, guard), Some(&12));
1643 assert_eq!(map.get(x, guard), None);
1644
1645 map.remove(y, guard);
1646 map.remove(x2, guard);
1647
1648 assert_eq!(map.get(y, guard), None);
1649 assert_eq!(map.get(x2, guard), None);
1650 }
1651
1652 #[test]
1653 fn basic_usage2() {
1654 let map = SlotMap::new(10);
1655 let guard = &map.pin();
1656
1657 let x = map.insert(1, guard);
1658 let y = map.insert(2, guard);
1659 let z = map.insert(3, guard);
1660
1661 assert_eq!(map.get(x, guard), Some(&1));
1662 assert_eq!(map.get(y, guard), Some(&2));
1663 assert_eq!(map.get(z, guard), Some(&3));
1664
1665 map.remove(y, guard);
1666
1667 let y2 = map.insert(20, guard);
1668
1669 assert_eq!(map.get(y2, guard), Some(&20));
1670 assert_eq!(map.get(y, guard), None);
1671
1672 map.remove(x, guard);
1673 map.remove(z, guard);
1674
1675 let x2 = map.insert(10, guard);
1676
1677 assert_eq!(map.get(x2, guard), Some(&10));
1678 assert_eq!(map.get(x, guard), None);
1679
1680 let z2 = map.insert(30, guard);
1681
1682 assert_eq!(map.get(z2, guard), Some(&30));
1683 assert_eq!(map.get(x, guard), None);
1684
1685 map.remove(x2, guard);
1686
1687 assert_eq!(map.get(x2, guard), None);
1688
1689 map.remove(y2, guard);
1690 map.remove(z2, guard);
1691
1692 assert_eq!(map.get(y2, guard), None);
1693 assert_eq!(map.get(z2, guard), None);
1694 }
1695
1696 #[test]
1697 fn basic_usage3() {
1698 let map = SlotMap::new(10);
1699 let guard = &map.pin();
1700
1701 let x = map.insert(1, guard);
1702 let y = map.insert(2, guard);
1703
1704 assert_eq!(map.get(x, guard), Some(&1));
1705 assert_eq!(map.get(y, guard), Some(&2));
1706
1707 let z = map.insert(3, guard);
1708
1709 assert_eq!(map.get(z, guard), Some(&3));
1710
1711 map.remove(x, guard);
1712 map.remove(z, guard);
1713
1714 let z2 = map.insert(30, guard);
1715 let x2 = map.insert(10, guard);
1716
1717 assert_eq!(map.get(x2, guard), Some(&10));
1718 assert_eq!(map.get(z2, guard), Some(&30));
1719 assert_eq!(map.get(x, guard), None);
1720 assert_eq!(map.get(z, guard), None);
1721
1722 map.remove(x2, guard);
1723 map.remove(y, guard);
1724 map.remove(z2, guard);
1725
1726 assert_eq!(map.get(x2, guard), None);
1727 assert_eq!(map.get(y, guard), None);
1728 assert_eq!(map.get(z2, guard), None);
1729 }
1730
1731 #[test]
1732 fn basic_usage_invalidated1() {
1733 let map = SlotMap::new(10);
1734 let guard = &map.pin();
1735
1736 let x = map.insert(69, guard);
1737 let y = map.insert(42, guard);
1738
1739 assert_eq!(map.get(x, guard), Some(&69));
1740 assert_eq!(map.get(y, guard), Some(&42));
1741
1742 map.invalidate(x, guard);
1743 map.remove_invalidated(x);
1744
1745 let x2 = map.insert(12, guard);
1746
1747 assert_eq!(map.get(x2, guard), Some(&12));
1748 assert_eq!(map.get(x, guard), None);
1749
1750 map.invalidate(y, guard);
1751 map.invalidate(x2, guard);
1752
1753 assert_eq!(map.get(y, guard), None);
1754 assert_eq!(map.get(x2, guard), None);
1755
1756 map.remove_invalidated(y);
1757 map.remove_invalidated(x2);
1758
1759 assert_eq!(map.get(y, guard), None);
1760 assert_eq!(map.get(x2, guard), None);
1761 }
1762
1763 #[test]
1764 fn basic_usage_invalidated2() {
1765 let map = SlotMap::new(10);
1766 let guard = &map.pin();
1767
1768 let x = map.insert(1, guard);
1769 let y = map.insert(2, guard);
1770 let z = map.insert(3, guard);
1771
1772 assert_eq!(map.get(x, guard), Some(&1));
1773 assert_eq!(map.get(y, guard), Some(&2));
1774 assert_eq!(map.get(z, guard), Some(&3));
1775
1776 map.invalidate(y, guard);
1777 map.remove_invalidated(y);
1778
1779 let y2 = map.insert(20, guard);
1780
1781 assert_eq!(map.get(y2, guard), Some(&20));
1782 assert_eq!(map.get(y, guard), None);
1783
1784 map.invalidate(x, guard);
1785 map.invalidate(z, guard);
1786 map.remove_invalidated(x);
1787 map.remove_invalidated(z);
1788
1789 let x2 = map.insert(10, guard);
1790
1791 assert_eq!(map.get(x2, guard), Some(&10));
1792 assert_eq!(map.get(x, guard), None);
1793
1794 let z2 = map.insert(30, guard);
1795
1796 assert_eq!(map.get(z2, guard), Some(&30));
1797 assert_eq!(map.get(x, guard), None);
1798
1799 map.invalidate(x2, guard);
1800
1801 assert_eq!(map.get(x2, guard), None);
1802
1803 map.remove_invalidated(x2);
1804
1805 assert_eq!(map.get(x2, guard), None);
1806
1807 map.invalidate(y2, guard);
1808 map.invalidate(z2, guard);
1809
1810 assert_eq!(map.get(y2, guard), None);
1811 assert_eq!(map.get(z2, guard), None);
1812
1813 map.remove_invalidated(y2);
1814 map.remove_invalidated(z2);
1815
1816 assert_eq!(map.get(y2, guard), None);
1817 assert_eq!(map.get(z2, guard), None);
1818 }
1819
1820 #[test]
1821 fn basic_usage_invalidated3() {
1822 let map = SlotMap::new(10);
1823 let guard = &map.pin();
1824
1825 let x = map.insert(1, guard);
1826 let y = map.insert(2, guard);
1827
1828 assert_eq!(map.get(x, guard), Some(&1));
1829 assert_eq!(map.get(y, guard), Some(&2));
1830
1831 let z = map.insert(3, guard);
1832
1833 assert_eq!(map.get(z, guard), Some(&3));
1834
1835 map.invalidate(x, guard);
1836 map.invalidate(z, guard);
1837 map.remove_invalidated(x);
1838 map.remove_invalidated(z);
1839
1840 let z2 = map.insert(30, guard);
1841 let x2 = map.insert(10, guard);
1842
1843 assert_eq!(map.get(x2, guard), Some(&10));
1844 assert_eq!(map.get(z2, guard), Some(&30));
1845 assert_eq!(map.get(x, guard), None);
1846 assert_eq!(map.get(z, guard), None);
1847
1848 map.invalidate(x2, guard);
1849 map.invalidate(y, guard);
1850 map.invalidate(z2, guard);
1851
1852 assert_eq!(map.get(x2, guard), None);
1853 assert_eq!(map.get(y, guard), None);
1854 assert_eq!(map.get(z2, guard), None);
1855
1856 map.remove_invalidated(x2);
1857 map.remove_invalidated(y);
1858 map.remove_invalidated(z2);
1859
1860 assert_eq!(map.get(x2, guard), None);
1861 assert_eq!(map.get(y, guard), None);
1862 assert_eq!(map.get(z2, guard), None);
1863 }
1864
1865 #[test]
1866 fn basic_usage_mut1() {
1867 let mut map = SlotMap::new(10);
1868
1869 let x = map.insert_mut(69);
1870 let y = map.insert_mut(42);
1871
1872 assert_eq!(map.get_mut(x), Some(&mut 69));
1873 assert_eq!(map.get_mut(y), Some(&mut 42));
1874
1875 map.remove_mut(x);
1876
1877 let x2 = map.insert_mut(12);
1878
1879 assert_eq!(map.get_mut(x2), Some(&mut 12));
1880 assert_eq!(map.get_mut(x), None);
1881
1882 map.remove_mut(y);
1883 map.remove_mut(x2);
1884
1885 assert_eq!(map.get_mut(y), None);
1886 assert_eq!(map.get_mut(x2), None);
1887 }
1888
1889 #[test]
1890 fn basic_usage_mut2() {
1891 let mut map = SlotMap::new(10);
1892
1893 let x = map.insert_mut(1);
1894 let y = map.insert_mut(2);
1895 let z = map.insert_mut(3);
1896
1897 assert_eq!(map.get_mut(x), Some(&mut 1));
1898 assert_eq!(map.get_mut(y), Some(&mut 2));
1899 assert_eq!(map.get_mut(z), Some(&mut 3));
1900
1901 map.remove_mut(y);
1902
1903 let y2 = map.insert_mut(20);
1904
1905 assert_eq!(map.get_mut(y2), Some(&mut 20));
1906 assert_eq!(map.get_mut(y), None);
1907
1908 map.remove_mut(x);
1909 map.remove_mut(z);
1910
1911 let x2 = map.insert_mut(10);
1912
1913 assert_eq!(map.get_mut(x2), Some(&mut 10));
1914 assert_eq!(map.get_mut(x), None);
1915
1916 let z2 = map.insert_mut(30);
1917
1918 assert_eq!(map.get_mut(z2), Some(&mut 30));
1919 assert_eq!(map.get_mut(x), None);
1920
1921 map.remove_mut(x2);
1922
1923 assert_eq!(map.get_mut(x2), None);
1924
1925 map.remove_mut(y2);
1926 map.remove_mut(z2);
1927
1928 assert_eq!(map.get_mut(y2), None);
1929 assert_eq!(map.get_mut(z2), None);
1930 }
1931
1932 #[test]
1933 fn basic_usage_mut3() {
1934 let mut map = SlotMap::new(10);
1935
1936 let x = map.insert_mut(1);
1937 let y = map.insert_mut(2);
1938
1939 assert_eq!(map.get_mut(x), Some(&mut 1));
1940 assert_eq!(map.get_mut(y), Some(&mut 2));
1941
1942 let z = map.insert_mut(3);
1943
1944 assert_eq!(map.get_mut(z), Some(&mut 3));
1945
1946 map.remove_mut(x);
1947 map.remove_mut(z);
1948
1949 let z2 = map.insert_mut(30);
1950 let x2 = map.insert_mut(10);
1951
1952 assert_eq!(map.get_mut(x2), Some(&mut 10));
1953 assert_eq!(map.get_mut(z2), Some(&mut 30));
1954 assert_eq!(map.get_mut(x), None);
1955 assert_eq!(map.get_mut(z), None);
1956
1957 map.remove_mut(x2);
1958 map.remove_mut(y);
1959 map.remove_mut(z2);
1960
1961 assert_eq!(map.get_mut(x2), None);
1962 assert_eq!(map.get_mut(y), None);
1963 assert_eq!(map.get_mut(z2), None);
1964 }
1965
1966 #[test]
1967 fn iter1() {
1968 let map = SlotMap::new(10);
1969 let guard = &map.pin();
1970
1971 let x = map.insert(1, guard);
1972 let _ = map.insert(2, guard);
1973 let y = map.insert(3, guard);
1974
1975 let mut iter = map.iter(guard);
1976
1977 assert_eq!(*iter.next().unwrap().1, 1);
1978 assert_eq!(*iter.next().unwrap().1, 2);
1979 assert_eq!(*iter.next().unwrap().1, 3);
1980 assert!(iter.next().is_none());
1981
1982 map.remove(x, guard);
1983 map.remove(y, guard);
1984
1985 let mut iter = map.iter(guard);
1986
1987 assert_eq!(*iter.next().unwrap().1, 2);
1988 assert!(iter.next().is_none());
1989
1990 map.insert(3, guard);
1991 map.insert(1, guard);
1992
1993 let mut iter = map.iter(guard);
1994
1995 assert_eq!(*iter.next().unwrap().1, 2);
1996 assert_eq!(*iter.next().unwrap().1, 3);
1997 assert_eq!(*iter.next().unwrap().1, 1);
1998 assert!(iter.next().is_none());
1999 }
2000
2001 #[test]
2002 fn iter2() {
2003 let map = SlotMap::new(10);
2004 let guard = &map.pin();
2005
2006 let x = map.insert(1, guard);
2007 let y = map.insert(2, guard);
2008 let z = map.insert(3, guard);
2009
2010 map.remove(x, guard);
2011
2012 let mut iter = map.iter(guard);
2013
2014 assert_eq!(*iter.next().unwrap().1, 2);
2015 assert_eq!(*iter.next().unwrap().1, 3);
2016 assert!(iter.next().is_none());
2017
2018 map.remove(y, guard);
2019
2020 let mut iter = map.iter(guard);
2021
2022 assert_eq!(*iter.next().unwrap().1, 3);
2023 assert!(iter.next().is_none());
2024
2025 map.remove(z, guard);
2026
2027 let mut iter = map.iter(guard);
2028
2029 assert!(iter.next().is_none());
2030 }
2031
2032 #[test]
2033 fn iter3() {
2034 let map = SlotMap::new(10);
2035 let guard = &map.pin();
2036
2037 let _ = map.insert(1, guard);
2038 let x = map.insert(2, guard);
2039
2040 let mut iter = map.iter(guard);
2041
2042 assert_eq!(*iter.next().unwrap().1, 1);
2043 assert_eq!(*iter.next().unwrap().1, 2);
2044 assert!(iter.next().is_none());
2045
2046 map.remove(x, guard);
2047
2048 let x = map.insert(2, guard);
2049 let _ = map.insert(3, guard);
2050 let y = map.insert(4, guard);
2051
2052 map.remove(y, guard);
2053
2054 let mut iter = map.iter(guard);
2055
2056 assert_eq!(*iter.next().unwrap().1, 1);
2057 assert_eq!(*iter.next().unwrap().1, 2);
2058 assert_eq!(*iter.next().unwrap().1, 3);
2059 assert!(iter.next().is_none());
2060
2061 map.remove(x, guard);
2062
2063 let mut iter = map.iter(guard);
2064
2065 assert_eq!(*iter.next().unwrap().1, 1);
2066 assert_eq!(*iter.next().unwrap().1, 3);
2067 assert!(iter.next().is_none());
2068 }
2069
2070 #[test]
2071 fn iter_mut1() {
2072 let mut map = SlotMap::new(10);
2073
2074 let x = map.insert_mut(1);
2075 let _ = map.insert_mut(2);
2076 let y = map.insert_mut(3);
2077
2078 let mut iter = map.iter_mut();
2079
2080 assert_eq!(*iter.next().unwrap().1, 1);
2081 assert_eq!(*iter.next().unwrap().1, 2);
2082 assert_eq!(*iter.next().unwrap().1, 3);
2083 assert!(iter.next().is_none());
2084
2085 map.remove_mut(x);
2086 map.remove_mut(y);
2087
2088 let mut iter = map.iter_mut();
2089
2090 assert_eq!(*iter.next().unwrap().1, 2);
2091 assert!(iter.next().is_none());
2092
2093 map.insert_mut(3);
2094 map.insert_mut(1);
2095
2096 let mut iter = map.iter_mut();
2097
2098 assert_eq!(*iter.next().unwrap().1, 1);
2099 assert_eq!(*iter.next().unwrap().1, 2);
2100 assert_eq!(*iter.next().unwrap().1, 3);
2101 assert!(iter.next().is_none());
2102 }
2103
2104 #[test]
2105 fn iter_mut2() {
2106 let mut map = SlotMap::new(10);
2107
2108 let x = map.insert_mut(1);
2109 let y = map.insert_mut(2);
2110 let z = map.insert_mut(3);
2111
2112 map.remove_mut(x);
2113
2114 let mut iter = map.iter_mut();
2115
2116 assert_eq!(*iter.next().unwrap().1, 2);
2117 assert_eq!(*iter.next().unwrap().1, 3);
2118 assert!(iter.next().is_none());
2119
2120 map.remove_mut(y);
2121
2122 let mut iter = map.iter_mut();
2123
2124 assert_eq!(*iter.next().unwrap().1, 3);
2125 assert!(iter.next().is_none());
2126
2127 map.remove_mut(z);
2128
2129 let mut iter = map.iter_mut();
2130
2131 assert!(iter.next().is_none());
2132 }
2133
2134 #[test]
2135 fn iter_mut3() {
2136 let mut map = SlotMap::new(10);
2137
2138 let _ = map.insert_mut(1);
2139 let x = map.insert_mut(2);
2140
2141 let mut iter = map.iter_mut();
2142
2143 assert_eq!(*iter.next().unwrap().1, 1);
2144 assert_eq!(*iter.next().unwrap().1, 2);
2145 assert!(iter.next().is_none());
2146
2147 map.remove_mut(x);
2148
2149 let x = map.insert_mut(2);
2150 let _ = map.insert_mut(3);
2151 let y = map.insert_mut(4);
2152
2153 map.remove_mut(y);
2154
2155 let mut iter = map.iter_mut();
2156
2157 assert_eq!(*iter.next().unwrap().1, 1);
2158 assert_eq!(*iter.next().unwrap().1, 2);
2159 assert_eq!(*iter.next().unwrap().1, 3);
2160 assert!(iter.next().is_none());
2161
2162 map.remove_mut(x);
2163
2164 let mut iter = map.iter_mut();
2165
2166 assert_eq!(*iter.next().unwrap().1, 1);
2167 assert_eq!(*iter.next().unwrap().1, 3);
2168 assert!(iter.next().is_none());
2169 }
2170
2171 #[test]
2172 fn reusing_slots1() {
2173 let map = SlotMap::new(10);
2174
2175 let x = map.insert(0, &map.pin());
2176 let y = map.insert(0, &map.pin());
2177
2178 map.remove(y, &map.pin());
2179 map.pin().flush();
2180
2181 let y2 = map.insert(0, &map.pin());
2182 assert_eq!(y2.index, y.index);
2183 assert_ne!(y2.generation, y.generation);
2184
2185 map.remove(x, &map.pin());
2186 map.pin().flush();
2187
2188 let x2 = map.insert(0, &map.pin());
2189 assert_eq!(x2.index, x.index);
2190 assert_ne!(x2.generation, x.generation);
2191
2192 map.remove(y2, &map.pin());
2193 map.remove(x2, &map.pin());
2194 }
2195
2196 #[test]
2197 fn reusing_slots2() {
2198 let map = SlotMap::new(10);
2199
2200 let x = map.insert(0, &map.pin());
2201
2202 map.remove(x, &map.pin());
2203 map.pin().flush();
2204
2205 let x2 = map.insert(0, &map.pin());
2206 assert_eq!(x.index, x2.index);
2207 assert_ne!(x.generation, x2.generation);
2208
2209 let y = map.insert(0, &map.pin());
2210 let z = map.insert(0, &map.pin());
2211
2212 map.remove(y, &map.pin());
2213 map.remove(x2, &map.pin());
2214 map.pin().flush();
2215
2216 let x3 = map.insert(0, &map.pin());
2217 let y2 = map.insert(0, &map.pin());
2218 assert_eq!(x3.index, x2.index);
2219 assert_ne!(x3.generation, x2.generation);
2220 assert_eq!(y2.index, y.index);
2221 assert_ne!(y2.generation, y.generation);
2222
2223 map.remove(x3, &map.pin());
2224 map.remove(y2, &map.pin());
2225 map.remove(z, &map.pin());
2226 }
2227
2228 #[test]
2229 fn reusing_slots3() {
2230 let map = SlotMap::new(10);
2231
2232 let x = map.insert(0, &map.pin());
2233 let y = map.insert(0, &map.pin());
2234
2235 map.remove(x, &map.pin());
2236 map.remove(y, &map.pin());
2237 map.pin().flush();
2238
2239 let y2 = map.insert(0, &map.pin());
2240 let x2 = map.insert(0, &map.pin());
2241 let z = map.insert(0, &map.pin());
2242 assert_eq!(x2.index, x.index);
2243 assert_ne!(x2.generation, x.generation);
2244 assert_eq!(y2.index, y.index);
2245 assert_ne!(y2.generation, y.generation);
2246
2247 map.remove(x2, &map.pin());
2248 map.remove(z, &map.pin());
2249 map.remove(y2, &map.pin());
2250 map.pin().flush();
2251
2252 let y3 = map.insert(0, &map.pin());
2253 let z2 = map.insert(0, &map.pin());
2254 let x3 = map.insert(0, &map.pin());
2255 assert_eq!(y3.index, y2.index);
2256 assert_ne!(y3.generation, y2.generation);
2257 assert_eq!(z2.index, z.index);
2258 assert_ne!(z2.generation, z.generation);
2259 assert_eq!(x3.index, x2.index);
2260 assert_ne!(x3.generation, x2.generation);
2261
2262 map.remove(x3, &map.pin());
2263 map.remove(y3, &map.pin());
2264 map.remove(z2, &map.pin());
2265 }
2266
2267 #[test]
2268 fn reusing_slots_invalidated1() {
2269 let map = SlotMap::new(10);
2270
2271 let x = map.insert(0, &map.pin());
2272 let y = map.insert(0, &map.pin());
2273
2274 map.invalidate(y, &map.pin());
2275 map.remove_invalidated(y);
2276 map.pin().flush();
2277
2278 let y2 = map.insert(0, &map.pin());
2279 assert_eq!(y2.index, y.index);
2280 assert_ne!(y2.generation, y.generation);
2281
2282 map.invalidate(x, &map.pin());
2283 map.remove_invalidated(x);
2284 map.pin().flush();
2285
2286 let x2 = map.insert(0, &map.pin());
2287 assert_eq!(x2.index, x.index);
2288 assert_ne!(x2.generation, x.generation);
2289
2290 map.invalidate(y2, &map.pin());
2291 map.invalidate(x2, &map.pin());
2292 map.remove_invalidated(y2);
2293 map.remove_invalidated(x2);
2294 }
2295
2296 #[test]
2297 fn reusing_slots_invalidated2() {
2298 let map = SlotMap::new(10);
2299
2300 let x = map.insert(0, &map.pin());
2301
2302 map.invalidate(x, &map.pin());
2303 map.remove_invalidated(x);
2304 map.pin().flush();
2305
2306 let x2 = map.insert(0, &map.pin());
2307 assert_eq!(x.index, x2.index);
2308 assert_ne!(x.generation, x2.generation);
2309
2310 let y = map.insert(0, &map.pin());
2311 let z = map.insert(0, &map.pin());
2312
2313 map.invalidate(y, &map.pin());
2314 map.invalidate(x2, &map.pin());
2315 map.remove_invalidated(y);
2316 map.remove_invalidated(x2);
2317 map.pin().flush();
2318
2319 let x3 = map.insert(0, &map.pin());
2320 let y2 = map.insert(0, &map.pin());
2321 assert_eq!(x3.index, x2.index);
2322 assert_ne!(x3.generation, x2.generation);
2323 assert_eq!(y2.index, y.index);
2324 assert_ne!(y2.generation, y.generation);
2325
2326 map.invalidate(x3, &map.pin());
2327 map.invalidate(y2, &map.pin());
2328 map.invalidate(z, &map.pin());
2329 map.remove_invalidated(x3);
2330 map.remove_invalidated(y2);
2331 map.remove_invalidated(z);
2332 }
2333
2334 #[test]
2335 fn reusing_slots_invalidated3() {
2336 let map = SlotMap::new(10);
2337
2338 let x = map.insert(0, &map.pin());
2339 let y = map.insert(0, &map.pin());
2340
2341 map.remove(x, &map.pin());
2342 map.remove(y, &map.pin());
2343 map.pin().flush();
2344
2345 let y2 = map.insert(0, &map.pin());
2346 let x2 = map.insert(0, &map.pin());
2347 let z = map.insert(0, &map.pin());
2348 assert_eq!(x2.index, x.index);
2349 assert_ne!(x2.generation, x.generation);
2350 assert_eq!(y2.index, y.index);
2351 assert_ne!(y2.generation, y.generation);
2352
2353 map.remove(x2, &map.pin());
2354 map.remove(z, &map.pin());
2355 map.remove(y2, &map.pin());
2356 map.pin().flush();
2357
2358 let y3 = map.insert(0, &map.pin());
2359 let z2 = map.insert(0, &map.pin());
2360 let x3 = map.insert(0, &map.pin());
2361 assert_eq!(y3.index, y2.index);
2362 assert_ne!(y3.generation, y2.generation);
2363 assert_eq!(z2.index, z.index);
2364 assert_ne!(z2.generation, z.generation);
2365 assert_eq!(x3.index, x2.index);
2366 assert_ne!(x3.generation, x2.generation);
2367
2368 map.remove(x3, &map.pin());
2369 map.remove(y3, &map.pin());
2370 map.remove(z2, &map.pin());
2371 }
2372
2373 #[test]
2374 fn reusing_slots_mut1() {
2375 let mut map = SlotMap::new(10);
2376
2377 let x = map.insert_mut(0);
2378 let y = map.insert_mut(0);
2379
2380 map.remove_mut(y);
2381
2382 let y2 = map.insert_mut(0);
2383 assert_eq!(y2.index, y.index);
2384 assert_ne!(y2.generation, y.generation);
2385
2386 map.remove_mut(x);
2387
2388 let x2 = map.insert_mut(0);
2389 assert_eq!(x2.index, x.index);
2390 assert_ne!(x2.generation, x.generation);
2391
2392 map.remove_mut(y2);
2393 map.remove_mut(x2);
2394 }
2395
2396 #[test]
2397 fn reusing_slots_mut2() {
2398 let mut map = SlotMap::new(10);
2399
2400 let x = map.insert_mut(0);
2401
2402 map.remove_mut(x);
2403
2404 let x2 = map.insert_mut(0);
2405 assert_eq!(x.index, x2.index);
2406 assert_ne!(x.generation, x2.generation);
2407
2408 let y = map.insert_mut(0);
2409 let z = map.insert_mut(0);
2410
2411 map.remove_mut(y);
2412 map.remove_mut(x2);
2413
2414 let x3 = map.insert_mut(0);
2415 let y2 = map.insert_mut(0);
2416 assert_eq!(x3.index, x2.index);
2417 assert_ne!(x3.generation, x2.generation);
2418 assert_eq!(y2.index, y.index);
2419 assert_ne!(y2.generation, y.generation);
2420
2421 map.remove_mut(x3);
2422 map.remove_mut(y2);
2423 map.remove_mut(z);
2424 }
2425
2426 #[test]
2427 fn reusing_slots_mut3() {
2428 let mut map = SlotMap::new(10);
2429
2430 let x = map.insert_mut(0);
2431 let y = map.insert_mut(0);
2432
2433 map.remove_mut(x);
2434 map.remove_mut(y);
2435
2436 let y2 = map.insert_mut(0);
2437 let x2 = map.insert_mut(0);
2438 let z = map.insert_mut(0);
2439 assert_eq!(x2.index, x.index);
2440 assert_ne!(x2.generation, x.generation);
2441 assert_eq!(y2.index, y.index);
2442 assert_ne!(y2.generation, y.generation);
2443
2444 map.remove_mut(x2);
2445 map.remove_mut(z);
2446 map.remove_mut(y2);
2447
2448 let y3 = map.insert_mut(0);
2449 let z2 = map.insert_mut(0);
2450 let x3 = map.insert_mut(0);
2451 assert_eq!(y3.index, y2.index);
2452 assert_ne!(y3.generation, y2.generation);
2453 assert_eq!(z2.index, z.index);
2454 assert_ne!(z2.generation, z.generation);
2455 assert_eq!(x3.index, x2.index);
2456 assert_ne!(x3.generation, x2.generation);
2457
2458 map.remove_mut(x3);
2459 map.remove_mut(y3);
2460 map.remove_mut(z2);
2461 }
2462
2463 #[test]
2464 fn get_disjoint_mut() {
2465 let mut map = SlotMap::new(3);
2466
2467 let x = map.insert_mut(1);
2468 let y = map.insert_mut(2);
2469 let z = map.insert_mut(3);
2470
2471 assert_eq!(map.get_disjoint_mut([x, y]), Some([&mut 1, &mut 2]));
2472 assert_eq!(map.get_disjoint_mut([y, z]), Some([&mut 2, &mut 3]));
2473 assert_eq!(map.get_disjoint_mut([z, x]), Some([&mut 3, &mut 1]));
2474
2475 assert_eq!(
2476 map.get_disjoint_mut([x, y, z]),
2477 Some([&mut 1, &mut 2, &mut 3]),
2478 );
2479 assert_eq!(
2480 map.get_disjoint_mut([z, y, x]),
2481 Some([&mut 3, &mut 2, &mut 1]),
2482 );
2483
2484 assert_eq!(map.get_disjoint_mut([x, x]), None);
2485 assert_eq!(
2486 map.get_disjoint_mut([x, SlotId::new(3, OCCUPIED_TAG)]),
2487 None,
2488 );
2489
2490 map.remove_mut(y);
2491
2492 assert_eq!(map.get_disjoint_mut([x, z]), Some([&mut 1, &mut 3]));
2493
2494 assert_eq!(map.get_disjoint_mut([y]), None);
2495 assert_eq!(map.get_disjoint_mut([x, y]), None);
2496 assert_eq!(map.get_disjoint_mut([y, z]), None);
2497
2498 let y = map.insert_mut(2);
2499
2500 assert_eq!(
2501 map.get_disjoint_mut([x, y, z]),
2502 Some([&mut 1, &mut 2, &mut 3]),
2503 );
2504
2505 map.remove_mut(x);
2506 map.remove_mut(z);
2507
2508 assert_eq!(map.get_disjoint_mut([y]), Some([&mut 2]));
2509
2510 assert_eq!(map.get_disjoint_mut([x]), None);
2511 assert_eq!(map.get_disjoint_mut([z]), None);
2512
2513 map.remove_mut(y);
2514
2515 assert_eq!(map.get_disjoint_mut([]), Some([]));
2516 }
2517
2518 #[test]
2519 fn tagged() {
2520 let map = SlotMap::new(1);
2521 let guard = &map.pin();
2522
2523 let x = map.insert_with_tag(42, 1, guard);
2524 assert_eq!(x.generation() & TAG_MASK, 1);
2525 assert_eq!(map.get(x, guard), Some(&42));
2526 }
2527
2528 #[test]
2529 fn tagged_mut() {
2530 let mut map = SlotMap::new(1);
2531
2532 let x = map.insert_with_tag_mut(42, 1);
2533 assert_eq!(x.generation() & TAG_MASK, 1);
2534 assert_eq!(map.get_mut(x), Some(&mut 42));
2535 }
2536
2537 #[test]
2538 fn remove_unchecked() {
2539 let map = SlotMap::new(1);
2540
2541 let x = map.insert(69, &map.pin());
2542
2543 assert_eq!(unsafe { map.remove_unchecked(x, &map.pin()) }, &69);
2545
2546 assert_eq!(map.get(x, &map.pin()), None);
2547 }
2548
2549 #[test]
2550 fn invalidate() {
2551 let map = SlotMap::new(1);
2552
2553 let x = map.insert(69, &map.pin());
2554
2555 assert_eq!(map.invalidate(x, &map.pin()), Some(&69));
2556 assert_eq!(map.invalidate(x, &map.pin()), None);
2557 assert_eq!(map.get(x, &map.pin()), None);
2558 assert_eq!(map.remove(x, &map.pin()), None);
2559 assert_eq!(map.remove_invalidated(x), Some(()));
2560 assert_eq!(map.remove_invalidated(x), None);
2561 assert_eq!(map.get(x, &map.pin()), None);
2562 assert_eq!(map.remove(x, &map.pin()), None);
2563
2564 map.pin().flush();
2565
2566 let guard = &map.pin();
2567 let y = map.insert(42, guard);
2568
2569 assert_eq!(map.invalidate(y, guard), Some(&42));
2570 assert_eq!(map.invalidate(y, guard), None);
2571 assert_eq!(map.get(y, guard), None);
2572 assert_eq!(map.remove(y, guard), None);
2573 assert_eq!(map.remove_invalidated(y), Some(()));
2574 assert_eq!(map.remove_invalidated(y), None);
2575 assert_eq!(map.get(y, guard), None);
2576 assert_eq!(map.remove(y, guard), None);
2577 }
2578
2579 #[test]
2580 fn remove_invalidated_unchecked() {
2581 let map = SlotMap::new(1);
2582
2583 let x = map.insert(69, &map.pin());
2584
2585 assert_eq!(map.invalidate(x, &map.pin()), Some(&69));
2586
2587 unsafe { map.remove_invalidated_unchecked(x) };
2589
2590 assert_eq!(map.get(x, &map.pin()), None);
2591 }
2592
2593 #[test]
2594 fn revive_or_insert() {
2595 let mut map = SlotMap::new(1);
2596
2597 let x = map.insert(MaybeUninit::new(Box::new(69)), &map.pin());
2598 map.remove(x, &map.pin());
2599 map.pin().flush();
2600
2601 let guard = map.pin();
2602 let (y, value) = map.revive_or_insert_with(&guard, |_| MaybeUninit::new(Box::new(42)));
2603
2604 assert_eq!(y, SlotId::new(x.index, x.generation() + ONE_GENERATION));
2605
2606 assert_eq!(
2607 unsafe { value.assume_init_ref() },
2609 &Box::new(69),
2610 );
2611
2612 drop(guard);
2613
2614 unsafe { MaybeUninit::assume_init(map.remove_mut(y).unwrap()) };
2616 }
2617
2618 #[test]
2619 fn header_shards() {
2620 let map = SlotMap::<_, i32>::new(0);
2621
2622 thread::scope(|s| {
2623 let map = ↦
2624 let shard_count = SHARD_COUNT.load(Relaxed);
2625
2626 for _ in 0..shard_count {
2627 s.spawn(move || {
2628 assert_eq!(map.inner.header().shards().count(), shard_count);
2629 });
2630 }
2631 });
2632 }
2633
2634 const ITERATIONS: u32 = if cfg!(miri) { 1_000 } else { 1_000_000 };
2639
2640 #[test]
2641 fn multi_threaded1() {
2642 const THREADS: u32 = 2;
2643
2644 let map = SlotMap::new(ITERATIONS);
2645
2646 thread::scope(|s| {
2647 let inserter = || {
2648 for _ in 0..ITERATIONS / THREADS {
2649 map.insert(0, &map.pin());
2650 }
2651 };
2652
2653 for _ in 0..THREADS {
2654 s.spawn(inserter);
2655 }
2656 });
2657
2658 thread::scope(|s| {
2659 let remover = || {
2660 for index in 0..ITERATIONS {
2661 let _ = map.remove(SlotId::new(index, OCCUPIED_TAG), &map.pin());
2662 }
2663 };
2664
2665 for _ in 0..THREADS {
2666 s.spawn(remover);
2667 }
2668 });
2669
2670 assert_eq!(map.len(), 0);
2671 }
2672
2673 #[test]
2674 fn multi_threaded2() {
2675 const CAPACITY: u32 = 8_000;
2676
2677 let map = SlotMap::new(CAPACITY);
2678
2679 thread::scope(|s| {
2680 let insert_remover = || {
2681 for _ in 0..ITERATIONS / 6 {
2682 let x = map.insert(0, &map.pin());
2683 let y = map.insert(0, &map.pin());
2684 map.remove(y, &map.pin());
2685 let z = map.insert(0, &map.pin());
2686 map.remove(x, &map.pin());
2687 map.remove(z, &map.pin());
2688 }
2689 };
2690 let iterator = || {
2691 for _ in 0..ITERATIONS / CAPACITY * 2 {
2692 for index in 0..CAPACITY {
2693 if let Some(value) = map.index(index, &map.pin()) {
2694 let _ = *value;
2695 }
2696 }
2697 }
2698 };
2699
2700 s.spawn(iterator);
2701 s.spawn(iterator);
2702 s.spawn(iterator);
2703 s.spawn(insert_remover);
2704 });
2705 }
2706
2707 #[test]
2708 fn multi_threaded3() {
2709 let map = SlotMap::new(ITERATIONS / 10);
2710
2711 thread::scope(|s| {
2712 let inserter = || {
2713 for i in 0..ITERATIONS {
2714 if i % 10 == 0 {
2715 map.insert(0, &map.pin());
2716 } else {
2717 thread::yield_now();
2718 }
2719 }
2720 };
2721 let remover = || {
2722 for _ in 0..ITERATIONS {
2723 map.remove_index(0, &map.pin());
2724 }
2725 };
2726 let getter = || {
2727 for _ in 0..ITERATIONS {
2728 if let Some(value) = map.index(0, &map.pin()) {
2729 let _ = *value;
2730 }
2731 }
2732 };
2733
2734 s.spawn(getter);
2735 s.spawn(getter);
2736 s.spawn(getter);
2737 s.spawn(getter);
2738 s.spawn(remover);
2739 s.spawn(remover);
2740 s.spawn(remover);
2741 s.spawn(inserter);
2742 });
2743 }
2744}