15359
|
1 |
use super::common::GearId;
|
|
2 |
use std::{
|
|
3 |
any::TypeId,
|
|
4 |
mem::{size_of, MaybeUninit},
|
|
5 |
num::NonZeroU16,
|
15362
|
6 |
ptr::{copy_nonoverlapping, NonNull},
|
15359
|
7 |
slice,
|
|
8 |
};
|
15310
|
9 |
|
15361
|
10 |
pub unsafe trait TypeTuple: Sized {
|
15310
|
11 |
fn len() -> usize;
|
|
12 |
fn get_types(dest: &mut Vec<TypeId>);
|
15359
|
13 |
unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, f: F)
|
|
14 |
where
|
|
15 |
F: Fn(Self);
|
15310
|
16 |
}
|
|
17 |
|
15361
|
18 |
unsafe impl<T: 'static> TypeTuple for (&T,) {
|
15310
|
19 |
fn len() -> usize {
|
|
20 |
1
|
|
21 |
}
|
|
22 |
|
|
23 |
fn get_types(dest: &mut Vec<TypeId>) {
|
|
24 |
dest.push(TypeId::of::<T>());
|
|
25 |
}
|
15359
|
26 |
|
|
27 |
unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, f: F)
|
|
28 |
where
|
|
29 |
F: Fn(Self),
|
|
30 |
{
|
|
31 |
let slice1 = slice::from_raw_parts(slices[0].as_ptr() as *const T, count);
|
|
32 |
for i in 0..count {
|
|
33 |
f((slice1.get_unchecked(i),));
|
|
34 |
}
|
|
35 |
}
|
15310
|
36 |
}
|
|
37 |
|
15359
|
38 |
const BLOCK_SIZE: usize = 32768;
|
|
39 |
|
|
40 |
struct DataBlock {
|
|
41 |
max_elements: u16,
|
|
42 |
elements_count: u16,
|
|
43 |
data: Box<[u8; BLOCK_SIZE]>,
|
|
44 |
blocks: [Option<NonNull<u8>>; 64],
|
15310
|
45 |
}
|
|
46 |
|
15359
|
47 |
impl Unpin for DataBlock {}
|
|
48 |
|
|
49 |
impl DataBlock {
|
|
50 |
fn new(mask: u64, element_sizes: &[u16; 64]) -> Self {
|
|
51 |
let total_size: u16 = element_sizes
|
|
52 |
.iter()
|
|
53 |
.enumerate()
|
|
54 |
.filter(|(i, _)| mask & (164 << *i as u64) != 0)
|
|
55 |
.map(|(_, size)| *size)
|
|
56 |
.sum();
|
|
57 |
let max_elements = (BLOCK_SIZE / total_size as usize) as u16;
|
|
58 |
|
|
59 |
let mut data: Box<[u8; BLOCK_SIZE]> =
|
15362
|
60 |
Box::new(unsafe { MaybeUninit::uninit().assume_init() });
|
15359
|
61 |
let mut blocks = [None; 64];
|
|
62 |
let mut offset = 0;
|
|
63 |
|
|
64 |
for i in 0..64 {
|
|
65 |
if mask & (164 << i) != 0 {
|
|
66 |
blocks[i] = Some(NonNull::new(data[offset..].as_mut_ptr()).unwrap());
|
|
67 |
offset += element_sizes[i] as usize * max_elements as usize;
|
|
68 |
}
|
|
69 |
}
|
15310
|
70 |
Self {
|
15359
|
71 |
elements_count: 0,
|
|
72 |
max_elements,
|
|
73 |
data,
|
|
74 |
blocks,
|
15310
|
75 |
}
|
|
76 |
}
|
|
77 |
|
15359
|
78 |
fn is_full(&self) -> bool {
|
|
79 |
self.elements_count == self.max_elements
|
|
80 |
}
|
15310
|
81 |
}
|
|
82 |
|
15359
|
83 |
#[derive(Clone, Copy, Debug, Default)]
|
|
84 |
pub struct LookupEntry {
|
|
85 |
index: Option<NonZeroU16>,
|
|
86 |
block_index: u16,
|
15310
|
87 |
}
|
|
88 |
|
|
89 |
pub struct GearDataManager {
|
|
90 |
types: Vec<TypeId>,
|
15359
|
91 |
blocks: Vec<DataBlock>,
|
|
92 |
block_masks: Vec<u64>,
|
|
93 |
element_sizes: Box<[u16; 64]>,
|
|
94 |
lookup: Box<[LookupEntry]>,
|
15310
|
95 |
}
|
|
96 |
|
|
97 |
impl GearDataManager {
|
|
98 |
pub fn new() -> Self {
|
|
99 |
Self {
|
|
100 |
types: vec![],
|
15359
|
101 |
blocks: vec![],
|
|
102 |
block_masks: vec![],
|
|
103 |
element_sizes: Box::new([0; 64]),
|
|
104 |
lookup: vec![LookupEntry::default(); u16::max_value() as usize].into_boxed_slice(),
|
|
105 |
}
|
|
106 |
}
|
|
107 |
|
|
108 |
#[inline]
|
|
109 |
fn get_type_index<T: 'static>(&self) -> Option<usize> {
|
|
110 |
let type_id = TypeId::of::<T>();
|
|
111 |
self.types.iter().position(|id| *id == type_id)
|
|
112 |
}
|
|
113 |
|
|
114 |
fn move_between_blocks(&mut self, from_block_index: u16, from_index: u16, to_block_index: u16) {
|
15362
|
115 |
debug_assert!(from_block_index != to_block_index);
|
15359
|
116 |
let source_mask = self.block_masks[from_block_index as usize];
|
|
117 |
let destination_mask = self.block_masks[to_block_index as usize];
|
|
118 |
debug_assert!(source_mask & destination_mask == source_mask);
|
|
119 |
|
|
120 |
let source = &self.blocks[from_block_index as usize];
|
|
121 |
let destination = &self.blocks[to_block_index as usize];
|
15362
|
122 |
debug_assert!(from_index < source.elements_count);
|
|
123 |
debug_assert!(!destination.is_full());
|
|
124 |
|
15359
|
125 |
for i in 0..64 {
|
15362
|
126 |
if source_mask & 1u64 << i != 0 {
|
|
127 |
unsafe {
|
|
128 |
copy_nonoverlapping(
|
|
129 |
source.blocks[i].unwrap().as_ptr(),
|
|
130 |
destination.blocks[i].unwrap().as_ptr(),
|
|
131 |
self.element_sizes[i] as usize,
|
|
132 |
);
|
|
133 |
}
|
|
134 |
}
|
15359
|
135 |
}
|
15362
|
136 |
self.blocks[from_block_index as usize].elements_count -= 1;
|
|
137 |
self.blocks[to_block_index as usize].elements_count += 1;
|
15359
|
138 |
}
|
|
139 |
|
15361
|
140 |
fn add_to_block<T: Clone>(&mut self, block_index: u16, value: &T) {
|
|
141 |
debug_assert!(self.block_masks[block_index as usize].count_ones() == 1);
|
|
142 |
|
|
143 |
let block = &mut self.blocks[block_index as usize];
|
|
144 |
debug_assert!(block.elements_count < block.max_elements);
|
|
145 |
|
|
146 |
unsafe {
|
|
147 |
let slice = slice::from_raw_parts_mut(
|
|
148 |
block.data.as_mut_ptr() as *mut T,
|
|
149 |
block.max_elements as usize,
|
|
150 |
);
|
|
151 |
*slice.get_unchecked_mut(block.elements_count as usize) = value.clone();
|
|
152 |
};
|
|
153 |
block.elements_count += 1;
|
15359
|
154 |
}
|
|
155 |
|
|
156 |
fn remove_from_block(&mut self, block_index: u16, index: u16) {
|
15361
|
157 |
let block = &mut self.blocks[block_index as usize];
|
|
158 |
debug_assert!(index < block.elements_count);
|
|
159 |
|
|
160 |
for (i, size) in self.element_sizes.iter().cloned().enumerate() {
|
|
161 |
if index < block.elements_count - 1 {
|
15362
|
162 |
if let Some(ptr) = block.blocks[i] {
|
15361
|
163 |
unsafe {
|
15362
|
164 |
copy_nonoverlapping(
|
15361
|
165 |
ptr.as_ptr()
|
|
166 |
.add((size * (block.elements_count - 1)) as usize),
|
|
167 |
ptr.as_ptr().add((size * index) as usize),
|
|
168 |
size as usize,
|
|
169 |
);
|
|
170 |
}
|
|
171 |
}
|
|
172 |
}
|
|
173 |
}
|
|
174 |
block.elements_count -= 1;
|
15359
|
175 |
}
|
|
176 |
|
|
177 |
#[inline]
|
|
178 |
fn ensure_group(&mut self, mask: u64) -> u16 {
|
|
179 |
if let Some(index) = self
|
|
180 |
.block_masks
|
|
181 |
.iter()
|
|
182 |
.enumerate()
|
|
183 |
.position(|(i, m)| *m == mask && !self.blocks[i].is_full())
|
|
184 |
{
|
|
185 |
index as u16
|
|
186 |
} else {
|
|
187 |
self.blocks.push(DataBlock::new(mask, &self.element_sizes));
|
|
188 |
(self.blocks.len() - 1) as u16
|
|
189 |
}
|
|
190 |
}
|
|
191 |
|
|
192 |
pub fn add<T: Clone + 'static>(&mut self, gear_id: GearId, value: &T) {
|
|
193 |
if let Some(type_index) = self.get_type_index::<T>() {
|
|
194 |
let type_bit = 1u64 << type_index as u64;
|
|
195 |
let entry = self.lookup[gear_id.get() as usize - 1];
|
|
196 |
|
|
197 |
if let Some(index) = entry.index {
|
|
198 |
let mask = self.block_masks[entry.block_index as usize];
|
|
199 |
let new_mask = mask | type_bit;
|
|
200 |
|
|
201 |
if new_mask != mask {
|
|
202 |
let dest_block_index = self.ensure_group(new_mask);
|
|
203 |
self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index);
|
|
204 |
}
|
|
205 |
} else {
|
|
206 |
let dest_block_index = self.ensure_group(type_bit);
|
|
207 |
self.add_to_block(dest_block_index, value);
|
|
208 |
}
|
|
209 |
} else {
|
|
210 |
panic!("Unregistered type")
|
|
211 |
}
|
|
212 |
}
|
|
213 |
|
|
214 |
pub fn remove<T: 'static>(&mut self, gear_id: GearId) {
|
|
215 |
if let Some(type_index) = self.get_type_index::<T>() {
|
|
216 |
let entry = self.lookup[gear_id.get() as usize - 1];
|
|
217 |
if let Some(index) = entry.index {
|
15362
|
218 |
let destination_mask =
|
|
219 |
self.block_masks[entry.block_index as usize] & !(1u64 << type_index as u64);
|
|
220 |
|
|
221 |
if destination_mask == 0 {
|
|
222 |
self.remove_all(gear_id)
|
|
223 |
} else {
|
|
224 |
let destination_block_index = self.ensure_group(destination_mask);
|
|
225 |
self.move_between_blocks(
|
|
226 |
entry.block_index,
|
|
227 |
index.get() - 1,
|
|
228 |
destination_block_index,
|
|
229 |
);
|
|
230 |
}
|
15359
|
231 |
}
|
15362
|
232 |
} else {
|
|
233 |
panic!("Unregistered type")
|
|
234 |
}
|
|
235 |
}
|
|
236 |
|
|
237 |
pub fn remove_all(&mut self, gear_id: GearId) {
|
|
238 |
let entry = self.lookup[gear_id.get() as usize - 1];
|
|
239 |
if let Some(index) = entry.index {
|
|
240 |
self.remove_from_block(entry.block_index, index.get() - 1);
|
15310
|
241 |
}
|
|
242 |
}
|
|
243 |
|
|
244 |
pub fn register<T: 'static>(&mut self) {
|
15361
|
245 |
debug_assert!(!std::mem::needs_drop::<T>());
|
|
246 |
debug_assert!(self.types.len() <= 64);
|
|
247 |
debug_assert!(size_of::<T>() <= u16::max_value() as usize);
|
15359
|
248 |
|
15310
|
249 |
let id = TypeId::of::<T>();
|
|
250 |
if !self.types.contains(&id) {
|
15359
|
251 |
self.element_sizes[self.types.len()] = size_of::<T>() as u16;
|
15310
|
252 |
self.types.push(id);
|
|
253 |
}
|
|
254 |
}
|
|
255 |
|
|
256 |
fn create_selector(&self, types: &[TypeId]) -> u64 {
|
|
257 |
let mut selector = 0u64;
|
|
258 |
for (i, typ) in self.types.iter().enumerate() {
|
|
259 |
if types.contains(&typ) {
|
15359
|
260 |
selector |= 1u64 << (i as u64)
|
15310
|
261 |
}
|
|
262 |
}
|
|
263 |
selector
|
|
264 |
}
|
|
265 |
|
|
266 |
pub fn iter<T: TypeTuple + 'static, F: Fn(T) + Copy>(&self, f: F) {
|
|
267 |
let mut types = vec![];
|
|
268 |
T::get_types(&mut types);
|
15361
|
269 |
debug_assert!(types.iter().all(|t| self.types.contains(t)));
|
15359
|
270 |
|
15361
|
271 |
let types_count = types.len();
|
15310
|
272 |
let selector = self.create_selector(&types);
|
15361
|
273 |
|
15359
|
274 |
for (block_index, mask) in self.block_masks.iter().enumerate() {
|
|
275 |
if mask & selector == selector {
|
|
276 |
let block = &self.blocks[block_index];
|
|
277 |
for element_index in 0..block.max_elements {
|
15361
|
278 |
unsafe {
|
|
279 |
T::iter(unimplemented!(), block.elements_count as usize, f);
|
|
280 |
}
|
15359
|
281 |
}
|
15310
|
282 |
}
|
|
283 |
}
|
|
284 |
}
|
|
285 |
}
|
15359
|
286 |
|
|
287 |
#[cfg(test)]
|
|
288 |
mod test {
|
|
289 |
use super::GearDataManager;
|
|
290 |
|
|
291 |
struct Datum {
|
|
292 |
value: u32,
|
|
293 |
}
|
|
294 |
|
|
295 |
#[test]
|
|
296 |
fn iteration() {
|
|
297 |
let mut manager = GearDataManager::new();
|
|
298 |
manager.register::<Datum>();
|
|
299 |
manager.iter(|d: (&Datum,)| {});
|
|
300 |
}
|
|
301 |
}
|