mtb_entity_slab/
policy.rs1use crate::{
2 NULL_INDEXED_ID,
3 bitalloc::{BitAlloc, IBitAlloc, SummaryAlloc},
4 chunk::Unit,
5};
6use std::marker::PhantomData;
7
8pub trait IEntityAllocPolicy<E> {
9 const CHUNK_SIZE_LOG2: usize;
10 const CHUNK_SIZE: usize;
11 const BITSET_LEN: usize;
12 const INDEXED_ID_PMASK: usize;
13
14 type BitAllocT: IBitAlloc;
15 type Units: AsRef<[Unit<E>]> + AsMut<[Unit<E>]> + IntoIterator<Item = Unit<E>>;
16
17 fn units_uninit_array() -> Box<Self::Units>;
18
19 fn compose_indexed_id(chunk_id: u32, unit_id: u16) -> usize {
20 debug_assert!(
21 unit_id < Self::CHUNK_SIZE as u16,
22 "unit_id {unit_id} out of bounds {}",
23 Self::CHUNK_SIZE
24 );
25 let chunk_size_log2 = Self::CHUNK_SIZE_LOG2;
26 ((chunk_id as usize) << chunk_size_log2) | (unit_id as usize)
27 }
28 fn split_indexed_id(indexed_id: usize) -> (u32, u16) {
29 let chunk_size_log2 = Self::CHUNK_SIZE_LOG2;
30 let chunk_id = (indexed_id >> chunk_size_log2) as u32;
31 let unit_id = (indexed_id & ((1usize << chunk_size_log2) - 1)) as u16;
32 (chunk_id, unit_id)
33 }
34 fn unit_of_indexed_id(indexed_id: usize) -> u16 {
35 let chunk_size_log2 = Self::CHUNK_SIZE_LOG2;
36 (indexed_id & ((1usize << chunk_size_log2) - 1)) as u16
37 }
38 fn chunk_of_indexed_id(indexed_id: usize) -> u32 {
39 let chunk_size_log2 = Self::CHUNK_SIZE_LOG2;
40 (indexed_id >> chunk_size_log2) as u32
41 }
42}
43
44pub struct EntityAllocPolicy128<E>(PhantomData<E>);
45impl<E> IEntityAllocPolicy<E> for EntityAllocPolicy128<E> {
46 const CHUNK_SIZE_LOG2: usize = 7;
47 const CHUNK_SIZE: usize = 1usize << Self::CHUNK_SIZE_LOG2;
48 const BITSET_LEN: usize = 1usize << (Self::CHUNK_SIZE_LOG2 - 6);
49 const INDEXED_ID_PMASK: usize = Self::CHUNK_SIZE - 1;
50
51 type BitAllocT = BitAlloc<2>;
52 type Units = [Unit<E>; 128];
53
54 fn units_uninit_array() -> Box<Self::Units> {
55 units_uninit_array()
56 }
57}
58
59pub struct EntityAllocPolicy256<E>(PhantomData<E>);
60impl<E> IEntityAllocPolicy<E> for EntityAllocPolicy256<E> {
61 const CHUNK_SIZE_LOG2: usize = 8;
62 const CHUNK_SIZE: usize = 1usize << Self::CHUNK_SIZE_LOG2;
63 const BITSET_LEN: usize = 1usize << (Self::CHUNK_SIZE_LOG2 - 6);
64 const INDEXED_ID_PMASK: usize = Self::CHUNK_SIZE - 1;
65
66 type BitAllocT = BitAlloc<4>;
67 type Units = [Unit<E>; 256];
68
69 fn units_uninit_array() -> Box<Self::Units> {
70 units_uninit_array()
71 }
72}
73
74pub struct EntityAllocPolicy512<E>(PhantomData<E>);
75impl<E> IEntityAllocPolicy<E> for EntityAllocPolicy512<E> {
76 const CHUNK_SIZE_LOG2: usize = 9;
77 const CHUNK_SIZE: usize = 1usize << Self::CHUNK_SIZE_LOG2;
78 const BITSET_LEN: usize = 1usize << (Self::CHUNK_SIZE_LOG2 - 6);
79 const INDEXED_ID_PMASK: usize = Self::CHUNK_SIZE - 1;
80
81 type BitAllocT = BitAlloc<8>;
82 type Units = [Unit<E>; 512];
83
84 fn units_uninit_array() -> Box<Self::Units> {
85 units_uninit_array()
86 }
87}
88
89pub struct EntityAllocPolicy1024<E>(PhantomData<E>);
90impl<E> IEntityAllocPolicy<E> for EntityAllocPolicy1024<E> {
91 const CHUNK_SIZE_LOG2: usize = 10;
92 const CHUNK_SIZE: usize = 1usize << Self::CHUNK_SIZE_LOG2;
93 const BITSET_LEN: usize = 1usize << (Self::CHUNK_SIZE_LOG2 - 6);
94 const INDEXED_ID_PMASK: usize = Self::CHUNK_SIZE - 1;
95
96 type BitAllocT = SummaryAlloc<16>;
97 type Units = [Unit<E>; 1024];
98
99 fn units_uninit_array() -> Box<Self::Units> {
100 units_uninit_array()
101 }
102}
103
104pub struct EntityAllocPolicy2048<E>(PhantomData<E>);
105impl<E> IEntityAllocPolicy<E> for EntityAllocPolicy2048<E> {
106 const CHUNK_SIZE_LOG2: usize = 11;
107 const CHUNK_SIZE: usize = 1usize << Self::CHUNK_SIZE_LOG2;
108 const BITSET_LEN: usize = 1usize << (Self::CHUNK_SIZE_LOG2 - 6);
109 const INDEXED_ID_PMASK: usize = Self::CHUNK_SIZE - 1;
110
111 type BitAllocT = SummaryAlloc<32>;
112 type Units = [Unit<E>; 2048];
113
114 fn units_uninit_array() -> Box<Self::Units> {
115 units_uninit_array()
116 }
117}
118
119pub struct EntityAllocPolicy4096<E>(PhantomData<E>);
120impl<E> IEntityAllocPolicy<E> for EntityAllocPolicy4096<E> {
121 const CHUNK_SIZE_LOG2: usize = 12;
122 const CHUNK_SIZE: usize = 1usize << Self::CHUNK_SIZE_LOG2;
123 const BITSET_LEN: usize = 1usize << (Self::CHUNK_SIZE_LOG2 - 6);
124 const INDEXED_ID_PMASK: usize = Self::CHUNK_SIZE - 1;
125
126 type BitAllocT = SummaryAlloc<64>;
127 type Units = [Unit<E>; 4096];
128
129 fn units_uninit_array() -> Box<Self::Units> {
130 units_uninit_array()
131 }
132}
133
134fn units_uninit_array<E, const N: usize>() -> Box<[Unit<E>; N]> {
135 let mut ret: Box<[Unit<E>; N]> = unsafe { Box::new_uninit().assume_init() };
136 for unit in ret.iter_mut() {
137 unit.indexed_id = NULL_INDEXED_ID;
138 }
139 ret
140}