1use std::marker::PhantomData;
19
20#[derive(Debug)]
27pub struct Handle<T> {
28 index: u32,
29 generation: u32,
30 _marker: PhantomData<T>,
31}
32
33impl<T> Clone for Handle<T> {
34 fn clone(&self) -> Self {
35 *self
36 }
37}
38
39impl<T> Copy for Handle<T> {}
40
41impl<T> PartialEq for Handle<T> {
42 fn eq(&self, other: &Self) -> bool {
43 self.index == other.index && self.generation == other.generation
44 }
45}
46
47impl<T> Eq for Handle<T> {}
48
49impl<T> std::hash::Hash for Handle<T> {
50 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
51 self.index.hash(state);
52 self.generation.hash(state);
53 }
54}
55
56impl<T> Handle<T> {
57 #[inline]
59 #[must_use]
60 pub const fn new(index: u32, generation: u32) -> Self {
61 Self {
62 index,
63 generation,
64 _marker: PhantomData,
65 }
66 }
67
68 #[inline]
70 #[must_use]
71 pub const fn index(self) -> u32 {
72 self.index
73 }
74
75 #[inline]
77 #[must_use]
78 pub const fn generation(self) -> u32 {
79 self.generation
80 }
81
82 #[inline]
84 #[must_use]
85 pub const fn dangling() -> Self {
86 Self {
87 index: u32::MAX,
88 generation: 0,
89 _marker: PhantomData,
90 }
91 }
92
93 #[inline]
95 #[must_use]
96 pub const fn is_dangling(self) -> bool {
97 self.index == u32::MAX
98 }
99}
100
101impl<T> Default for Handle<T> {
102 fn default() -> Self {
103 Self::dangling()
104 }
105}
106
107#[derive(Debug, Clone)]
109struct AllocatorEntry<T> {
110 value: Option<T>,
112 generation: u32,
114}
115
116impl<T> Default for AllocatorEntry<T> {
117 fn default() -> Self {
118 Self {
119 value: None,
120 generation: 0,
121 }
122 }
123}
124
125#[derive(Debug)]
130pub struct HandleAllocator<T> {
131 entries: Vec<AllocatorEntry<T>>,
132 free_list: Vec<u32>,
133}
134
135impl<T> Default for HandleAllocator<T> {
136 fn default() -> Self {
137 Self::new()
138 }
139}
140
141impl<T> HandleAllocator<T> {
142 #[must_use]
144 pub fn new() -> Self {
145 Self {
146 entries: Vec::new(),
147 free_list: Vec::new(),
148 }
149 }
150
151 #[must_use]
153 pub fn with_capacity(capacity: usize) -> Self {
154 Self {
155 entries: Vec::with_capacity(capacity),
156 free_list: Vec::new(),
157 }
158 }
159
160 #[must_use]
162 pub fn allocate(&mut self, value: T) -> Handle<T> {
163 if let Some(index) = self.free_list.pop() {
164 let entry = &mut self.entries[index as usize];
165 entry.value = Some(value);
166 Handle::new(index, entry.generation)
167 } else {
168 let index = self.entries.len() as u32;
169 self.entries.push(AllocatorEntry {
170 value: Some(value),
171 generation: 0,
172 });
173 Handle::new(index, 0)
174 }
175 }
176
177 pub fn deallocate(&mut self, handle: Handle<T>) -> Option<T> {
179 let index = handle.index as usize;
180 if index >= self.entries.len() {
181 return None;
182 }
183
184 let entry = &mut self.entries[index];
185 if entry.generation != handle.generation {
186 return None;
187 }
188
189 let value = entry.value.take();
190 if value.is_some() {
191 entry.generation = entry.generation.wrapping_add(1);
192 self.free_list.push(handle.index);
193 }
194 value
195 }
196
197 #[must_use]
199 pub fn get(&self, handle: Handle<T>) -> Option<&T> {
200 let index = handle.index as usize;
201 if index >= self.entries.len() {
202 return None;
203 }
204
205 let entry = &self.entries[index];
206 if entry.generation != handle.generation {
207 return None;
208 }
209
210 entry.value.as_ref()
211 }
212
213 #[must_use]
215 pub fn get_mut(&mut self, handle: Handle<T>) -> Option<&mut T> {
216 let index = handle.index as usize;
217 if index >= self.entries.len() {
218 return None;
219 }
220
221 let entry = &mut self.entries[index];
222 if entry.generation != handle.generation {
223 return None;
224 }
225
226 entry.value.as_mut()
227 }
228
229 #[must_use]
231 pub fn is_valid(&self, handle: Handle<T>) -> bool {
232 self.get(handle).is_some()
233 }
234
235 #[must_use]
237 pub fn len(&self) -> usize {
238 self.entries.len() - self.free_list.len()
239 }
240
241 #[must_use]
243 pub fn is_empty(&self) -> bool {
244 self.len() == 0
245 }
246
247 #[must_use]
249 pub fn capacity(&self) -> usize {
250 self.entries.capacity()
251 }
252
253 pub fn clear(&mut self) {
255 self.entries.clear();
256 self.free_list.clear();
257 }
258
259 pub fn iter(&self) -> impl Iterator<Item = (Handle<T>, &T)> {
261 self.entries
262 .iter()
263 .enumerate()
264 .filter_map(|(index, entry)| {
265 entry
266 .value
267 .as_ref()
268 .map(|value| (Handle::new(index as u32, entry.generation), value))
269 })
270 }
271
272 pub fn iter_mut(&mut self) -> impl Iterator<Item = (Handle<T>, &mut T)> {
274 self.entries
275 .iter_mut()
276 .enumerate()
277 .filter_map(|(index, entry)| {
278 let generation = entry.generation;
279 entry
280 .value
281 .as_mut()
282 .map(|value| (Handle::new(index as u32, generation), value))
283 })
284 }
285
286 pub fn values(&self) -> impl Iterator<Item = &T> {
288 self.entries.iter().filter_map(|entry| entry.value.as_ref())
289 }
290
291 pub fn values_mut(&mut self) -> impl Iterator<Item = &mut T> {
293 self.entries
294 .iter_mut()
295 .filter_map(|entry| entry.value.as_mut())
296 }
297}
298
299#[cfg(feature = "parallel")]
304impl<T: Send + Sync> HandleAllocator<T> {
305 #[must_use]
319 pub fn par_values(&self) -> impl rayon::iter::ParallelIterator<Item = &T> {
320 use rayon::prelude::*;
321 self.entries
322 .par_iter()
323 .filter_map(|entry| entry.value.as_ref())
324 }
325
326 pub fn par_values_mut(&mut self) -> impl rayon::iter::ParallelIterator<Item = &mut T> {
328 use rayon::prelude::*;
329 self.entries
330 .par_iter_mut()
331 .filter_map(|entry| entry.value.as_mut())
332 }
333}
334
335#[cfg(feature = "parallel")]
340mod concurrent {
341 use super::{AllocatorEntry, Handle};
342 use parking_lot::{Mutex, RwLock};
343
344 #[derive(Debug)]
369 pub struct ConcurrentHandleAllocator<T> {
370 entries: RwLock<Vec<AllocatorEntry<T>>>,
371 free_list: Mutex<Vec<u32>>,
372 }
373
374 impl<T> Default for ConcurrentHandleAllocator<T> {
375 fn default() -> Self {
376 Self::new()
377 }
378 }
379
380 impl<T> ConcurrentHandleAllocator<T> {
381 #[must_use]
383 pub fn new() -> Self {
384 Self {
385 entries: RwLock::new(Vec::new()),
386 free_list: Mutex::new(Vec::new()),
387 }
388 }
389
390 #[must_use]
392 pub fn with_capacity(capacity: usize) -> Self {
393 Self {
394 entries: RwLock::new(Vec::with_capacity(capacity)),
395 free_list: Mutex::new(Vec::new()),
396 }
397 }
398
399 pub fn allocate(&self, value: T) -> Handle<T> {
403 let mut free_list = self.free_list.lock();
404
405 if let Some(index) = free_list.pop() {
406 let mut entries = self.entries.write();
407 let entry = &mut entries[index as usize];
408 entry.value = Some(value);
409 Handle::new(index, entry.generation)
410 } else {
411 let mut entries = self.entries.write();
412 let index = entries.len() as u32;
413 entries.push(AllocatorEntry {
414 value: Some(value),
415 generation: 0,
416 });
417 Handle::new(index, 0)
418 }
419 }
420
421 pub fn deallocate(&self, handle: Handle<T>) -> Option<T> {
423 let index = handle.index as usize;
424
425 let mut entries = self.entries.write();
426 if index >= entries.len() {
427 return None;
428 }
429
430 let entry = &mut entries[index];
431 if entry.generation != handle.generation {
432 return None;
433 }
434
435 let value = entry.value.take();
436 if value.is_some() {
437 entry.generation = entry.generation.wrapping_add(1);
438 drop(entries); self.free_list.lock().push(handle.index);
440 }
441 value
442 }
443
444 #[must_use]
448 pub fn get(&self, handle: Handle<T>) -> Option<ValueRef<'_, T>> {
449 let index = handle.index as usize;
450 let entries = self.entries.read();
451
452 if index >= entries.len() {
453 return None;
454 }
455
456 if entries[index].generation != handle.generation {
457 return None;
458 }
459
460 entries[index].value.as_ref()?;
461
462 Some(ValueRef {
463 guard: entries,
464 index,
465 })
466 }
467
468 #[must_use]
470 pub fn is_valid(&self, handle: Handle<T>) -> bool {
471 let index = handle.index as usize;
472 let entries = self.entries.read();
473
474 if index >= entries.len() {
475 return false;
476 }
477
478 let entry = &entries[index];
479 entry.generation == handle.generation && entry.value.is_some()
480 }
481
482 #[must_use]
484 pub fn len(&self) -> usize {
485 let entries = self.entries.read();
486 let free_list = self.free_list.lock();
487 entries.len() - free_list.len()
488 }
489
490 #[must_use]
492 pub fn is_empty(&self) -> bool {
493 self.len() == 0
494 }
495
496 pub fn clear(&self) {
498 let mut entries = self.entries.write();
499 let mut free_list = self.free_list.lock();
500 entries.clear();
501 free_list.clear();
502 }
503 }
504
505 pub struct ValueRef<'a, T> {
507 guard: parking_lot::RwLockReadGuard<'a, Vec<AllocatorEntry<T>>>,
508 index: usize,
509 }
510
511 impl<T> std::ops::Deref for ValueRef<'_, T> {
512 type Target = T;
513
514 fn deref(&self) -> &Self::Target {
515 self.guard[self.index].value.as_ref().unwrap()
517 }
518 }
519}
520
521#[cfg(feature = "parallel")]
522pub use concurrent::ConcurrentHandleAllocator;
523
524#[cfg(test)]
525mod tests {
526 use super::*;
527
528 #[test]
529 fn test_handle_creation() {
530 let handle: Handle<i32> = Handle::new(0, 0);
531 assert_eq!(handle.index(), 0);
532 assert_eq!(handle.generation(), 0);
533 }
534
535 #[test]
536 fn test_handle_dangling() {
537 let handle: Handle<i32> = Handle::dangling();
538 assert!(handle.is_dangling());
539 }
540
541 #[test]
542 fn test_handle_default() {
543 let handle: Handle<i32> = Handle::default();
544 assert!(handle.is_dangling());
545 }
546
547 #[test]
548 fn test_handle_equality() {
549 let h1: Handle<i32> = Handle::new(1, 2);
550 let h2: Handle<i32> = Handle::new(1, 2);
551 let h3: Handle<i32> = Handle::new(1, 3);
552
553 assert_eq!(h1, h2);
554 assert_ne!(h1, h3);
555 }
556
557 #[test]
558 fn test_handle_copy() {
559 let h1: Handle<i32> = Handle::new(1, 2);
560 let h2 = h1;
561 assert_eq!(h1, h2);
562 }
563
564 #[test]
565 fn test_allocator_allocate() {
566 let mut alloc = HandleAllocator::new();
567 let handle = alloc.allocate(42);
568
569 assert_eq!(handle.index(), 0);
570 assert_eq!(handle.generation(), 0);
571 assert_eq!(alloc.len(), 1);
572 }
573
574 #[test]
575 fn test_allocator_get() {
576 let mut alloc = HandleAllocator::new();
577 let handle = alloc.allocate(42);
578
579 assert_eq!(alloc.get(handle), Some(&42));
580 }
581
582 #[test]
583 fn test_allocator_get_mut() {
584 let mut alloc = HandleAllocator::new();
585 let handle = alloc.allocate(42);
586
587 if let Some(value) = alloc.get_mut(handle) {
588 *value = 100;
589 }
590
591 assert_eq!(alloc.get(handle), Some(&100));
592 }
593
594 #[test]
595 fn test_allocator_deallocate() {
596 let mut alloc = HandleAllocator::new();
597 let handle = alloc.allocate(42);
598
599 let value = alloc.deallocate(handle);
600 assert_eq!(value, Some(42));
601 assert_eq!(alloc.len(), 0);
602 }
603
604 #[test]
605 fn test_allocator_stale_handle() {
606 let mut alloc = HandleAllocator::new();
607 let handle1 = alloc.allocate(42);
608 alloc.deallocate(handle1);
609
610 assert!(!alloc.is_valid(handle1));
612 assert_eq!(alloc.get(handle1), None);
613 }
614
615 #[test]
616 fn test_allocator_reuse_slot() {
617 let mut alloc = HandleAllocator::new();
618 let handle1 = alloc.allocate(42);
619 alloc.deallocate(handle1);
620 let handle2 = alloc.allocate(100);
621
622 assert_eq!(handle2.index(), handle1.index());
624 assert_eq!(handle2.generation(), handle1.generation() + 1);
625
626 assert!(!alloc.is_valid(handle1));
628 assert!(alloc.is_valid(handle2));
629 assert_eq!(alloc.get(handle2), Some(&100));
630 }
631
632 #[test]
633 fn test_allocator_multiple_allocations() {
634 let mut alloc = HandleAllocator::new();
635 let h1 = alloc.allocate(1);
636 let h2 = alloc.allocate(2);
637 let h3 = alloc.allocate(3);
638
639 assert_eq!(alloc.len(), 3);
640 assert_eq!(alloc.get(h1), Some(&1));
641 assert_eq!(alloc.get(h2), Some(&2));
642 assert_eq!(alloc.get(h3), Some(&3));
643 }
644
645 #[test]
646 fn test_allocator_deallocate_middle() {
647 let mut alloc = HandleAllocator::new();
648 let h1 = alloc.allocate(1);
649 let h2 = alloc.allocate(2);
650 let h3 = alloc.allocate(3);
651
652 alloc.deallocate(h2);
653
654 assert!(alloc.is_valid(h1));
655 assert!(!alloc.is_valid(h2));
656 assert!(alloc.is_valid(h3));
657 assert_eq!(alloc.len(), 2);
658 }
659
660 #[test]
661 fn test_allocator_double_deallocate() {
662 let mut alloc = HandleAllocator::new();
663 let handle = alloc.allocate(42);
664
665 assert_eq!(alloc.deallocate(handle), Some(42));
666 assert_eq!(alloc.deallocate(handle), None);
667 }
668
669 #[test]
670 fn test_allocator_invalid_handle() {
671 let alloc: HandleAllocator<i32> = HandleAllocator::new();
672 let invalid = Handle::new(999, 0);
673
674 assert!(!alloc.is_valid(invalid));
675 assert_eq!(alloc.get(invalid), None);
676 }
677
678 #[test]
679 fn test_allocator_clear() {
680 let mut alloc = HandleAllocator::new();
681 let _ = alloc.allocate(1);
682 let _ = alloc.allocate(2);
683 let _ = alloc.allocate(3);
684
685 alloc.clear();
686
687 assert!(alloc.is_empty());
688 assert_eq!(alloc.len(), 0);
689 }
690
691 #[test]
692 fn test_allocator_iter() {
693 let mut alloc = HandleAllocator::new();
694 let h1 = alloc.allocate(1);
695 let _h2 = alloc.allocate(2);
696 let h3 = alloc.allocate(3);
697
698 alloc.deallocate(h1);
699
700 let values: Vec<_> = alloc.iter().map(|(_, v)| *v).collect();
701 assert_eq!(values.len(), 2);
702 assert!(values.contains(&2));
703 assert!(values.contains(&3));
704 assert!(!values.contains(&1));
705
706 for (handle, _) in alloc.iter() {
708 assert!(alloc.is_valid(handle));
709 if handle == h3 {
711 assert_eq!(alloc.get(handle), Some(&3));
712 }
713 }
714 }
715
716 #[test]
717 fn test_allocator_iter_mut() {
718 let mut alloc = HandleAllocator::new();
719 let _ = alloc.allocate(1);
720 let _ = alloc.allocate(2);
721 let _ = alloc.allocate(3);
722
723 for (_, value) in alloc.iter_mut() {
724 *value *= 10;
725 }
726
727 let values: Vec<_> = alloc.iter().map(|(_, v)| *v).collect();
728 assert!(values.contains(&10));
729 assert!(values.contains(&20));
730 assert!(values.contains(&30));
731 }
732
733 #[test]
734 fn test_allocator_with_capacity() {
735 let alloc: HandleAllocator<i32> = HandleAllocator::with_capacity(100);
736 assert!(alloc.capacity() >= 100);
737 assert!(alloc.is_empty());
738 }
739
740 #[test]
741 fn test_handle_hash() {
742 use std::collections::HashSet;
743
744 let mut set = HashSet::new();
745 let h1: Handle<i32> = Handle::new(1, 0);
746 let h2: Handle<i32> = Handle::new(2, 0);
747 let h3: Handle<i32> = Handle::new(1, 0);
748
749 set.insert(h1);
750 set.insert(h2);
751 set.insert(h3); assert_eq!(set.len(), 2);
754 }
755
756 #[test]
757 fn test_values_iterator() {
758 let mut alloc = HandleAllocator::new();
759 let _ = alloc.allocate(1);
760 let h2 = alloc.allocate(2);
761 let _ = alloc.allocate(3);
762
763 alloc.deallocate(h2);
764
765 let values: Vec<_> = alloc.values().copied().collect();
766 assert_eq!(values.len(), 2);
767 assert!(values.contains(&1));
768 assert!(values.contains(&3));
769 assert!(!values.contains(&2));
770 }
771}
772
773#[cfg(all(test, feature = "parallel"))]
774mod parallel_tests {
775 use super::*;
776 use rayon::prelude::*;
777
778 #[test]
779 fn test_par_values() {
780 let mut alloc = HandleAllocator::new();
781 for i in 0..1000 {
782 let _ = alloc.allocate(i);
783 }
784
785 let sum: i32 = alloc.par_values().sum();
786 assert_eq!(sum, (0..1000).sum());
787 }
788
789 #[test]
790 fn test_par_values_mut() {
791 let mut alloc = HandleAllocator::new();
792 for i in 0..100 {
793 let _ = alloc.allocate(i);
794 }
795
796 alloc.par_values_mut().for_each(|v| *v *= 2);
797
798 let sum: i32 = alloc.values().copied().sum();
799 assert_eq!(sum, (0..100).map(|i| i * 2).sum());
800 }
801
802 #[test]
803 fn test_concurrent_allocator_basic() {
804 let alloc = ConcurrentHandleAllocator::new();
805 let h1 = alloc.allocate(42);
806 let h2 = alloc.allocate(100);
807
808 assert!(alloc.is_valid(h1));
809 assert!(alloc.is_valid(h2));
810 assert_eq!(alloc.len(), 2);
811
812 assert_eq!(*alloc.get(h1).unwrap(), 42);
813 assert_eq!(*alloc.get(h2).unwrap(), 100);
814 }
815
816 #[test]
817 fn test_concurrent_allocator_deallocate() {
818 let alloc = ConcurrentHandleAllocator::new();
819 let h1 = alloc.allocate(42);
820
821 assert_eq!(alloc.deallocate(h1), Some(42));
822 assert!(!alloc.is_valid(h1));
823 assert!(alloc.is_empty());
824 }
825
826 #[test]
827 fn test_concurrent_allocator_stale_handle() {
828 let alloc = ConcurrentHandleAllocator::new();
829 let h1 = alloc.allocate(42);
830 alloc.deallocate(h1);
831 let h2 = alloc.allocate(100);
832
833 assert!(!alloc.is_valid(h1));
834 assert!(alloc.is_valid(h2));
835 assert_eq!(h2.index(), h1.index());
836 assert_ne!(h2.generation(), h1.generation());
837 }
838
839 #[test]
840 fn test_concurrent_allocator_threaded() {
841 use std::sync::Arc;
842 use std::thread;
843
844 let alloc = Arc::new(ConcurrentHandleAllocator::new());
845 let mut handles = Vec::new();
846
847 let threads: Vec<_> = (0..4)
849 .map(|t| {
850 let alloc = Arc::clone(&alloc);
851 thread::spawn(move || {
852 let mut local_handles = Vec::new();
853 for i in 0..100 {
854 local_handles.push(alloc.allocate(t * 100 + i));
855 }
856 local_handles
857 })
858 })
859 .collect();
860
861 for t in threads {
862 handles.extend(t.join().unwrap());
863 }
864
865 assert_eq!(alloc.len(), 400);
866
867 for handle in &handles {
869 assert!(alloc.is_valid(*handle));
870 }
871 }
872}