mtb_entity_slab/
policy.rs

1use 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}