8 }; |
8 }; |
9 |
9 |
10 pub unsafe trait TypeTuple: Sized { |
10 pub unsafe trait TypeTuple: Sized { |
11 fn len() -> usize; |
11 fn len() -> usize; |
12 fn get_types(dest: &mut Vec<TypeId>); |
12 fn get_types(dest: &mut Vec<TypeId>); |
13 unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, f: F) |
13 unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, mut f: F) |
14 where |
14 where |
15 F: Fn(Self); |
15 F: FnMut(Self); |
16 } |
16 } |
17 |
17 |
18 unsafe impl<T: 'static> TypeTuple for (&T,) { |
18 unsafe impl<T: 'static> TypeTuple for (&T,) { |
19 fn len() -> usize { |
19 fn len() -> usize { |
20 1 |
20 1 |
22 |
22 |
23 fn get_types(dest: &mut Vec<TypeId>) { |
23 fn get_types(dest: &mut Vec<TypeId>) { |
24 dest.push(TypeId::of::<T>()); |
24 dest.push(TypeId::of::<T>()); |
25 } |
25 } |
26 |
26 |
27 unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, f: F) |
27 unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, mut f: F) |
28 where |
28 where |
29 F: Fn(Self), |
29 F: FnMut(Self), |
30 { |
30 { |
31 let slice1 = slice::from_raw_parts(slices[0].as_ptr() as *const T, count); |
31 let slice1 = slice::from_raw_parts(slices[0].as_ptr() as *const T, count); |
32 for i in 0..count { |
32 for i in 0..count { |
33 f((slice1.get_unchecked(i),)); |
33 f((slice1.get_unchecked(i),)); |
34 } |
34 } |
39 |
39 |
40 struct DataBlock { |
40 struct DataBlock { |
41 max_elements: u16, |
41 max_elements: u16, |
42 elements_count: u16, |
42 elements_count: u16, |
43 data: Box<[u8; BLOCK_SIZE]>, |
43 data: Box<[u8; BLOCK_SIZE]>, |
44 blocks: [Option<NonNull<u8>>; 64], |
44 component_blocks: [Option<NonNull<u8>>; 64], |
45 } |
45 } |
46 |
46 |
47 impl Unpin for DataBlock {} |
47 impl Unpin for DataBlock {} |
48 |
48 |
49 impl DataBlock { |
49 impl DataBlock { |
50 fn new(mask: u64, element_sizes: &[u16; 64]) -> Self { |
50 fn new(mask: u64, element_sizes: &[u16; 64]) -> Self { |
51 let total_size: u16 = element_sizes |
51 let total_size: u16 = element_sizes |
52 .iter() |
52 .iter() |
53 .enumerate() |
53 .enumerate() |
54 .filter(|(i, _)| mask & (164 << *i as u64) != 0) |
54 .filter(|(i, _)| mask & (1 << *i as u64) != 0) |
55 .map(|(_, size)| *size) |
55 .map(|(_, size)| *size) |
56 .sum(); |
56 .sum(); |
57 let max_elements = (BLOCK_SIZE / total_size as usize) as u16; |
57 let max_elements = (BLOCK_SIZE / total_size as usize) as u16; |
58 |
58 |
59 let mut data: Box<[u8; BLOCK_SIZE]> = |
59 let mut data: Box<[u8; BLOCK_SIZE]> = |
60 Box::new(unsafe { MaybeUninit::uninit().assume_init() }); |
60 Box::new(unsafe { MaybeUninit::uninit().assume_init() }); |
61 let mut blocks = [None; 64]; |
61 let mut blocks = [None; 64]; |
62 let mut offset = 0; |
62 let mut offset = 0; |
63 |
63 |
64 for i in 0..64 { |
64 for i in 0..64 { |
65 if mask & (164 << i) != 0 { |
65 if mask & (1 << i) != 0 { |
66 blocks[i] = Some(NonNull::new(data[offset..].as_mut_ptr()).unwrap()); |
66 blocks[i] = Some(NonNull::new(data[offset..].as_mut_ptr()).unwrap()); |
67 offset += element_sizes[i] as usize * max_elements as usize; |
67 offset += element_sizes[i] as usize * max_elements as usize; |
68 } |
68 } |
69 } |
69 } |
70 Self { |
70 Self { |
71 elements_count: 0, |
71 elements_count: 0, |
72 max_elements, |
72 max_elements, |
73 data, |
73 data, |
74 blocks, |
74 component_blocks: blocks, |
75 } |
75 } |
76 } |
76 } |
77 |
77 |
78 fn is_full(&self) -> bool { |
78 fn is_full(&self) -> bool { |
79 self.elements_count == self.max_elements |
79 self.elements_count == self.max_elements |
121 let destination = &self.blocks[to_block_index as usize]; |
121 let destination = &self.blocks[to_block_index as usize]; |
122 debug_assert!(from_index < source.elements_count); |
122 debug_assert!(from_index < source.elements_count); |
123 debug_assert!(!destination.is_full()); |
123 debug_assert!(!destination.is_full()); |
124 |
124 |
125 for i in 0..64 { |
125 for i in 0..64 { |
126 if source_mask & 1u64 << i != 0 { |
126 if source_mask & 1 << i != 0 { |
127 unsafe { |
127 unsafe { |
128 copy_nonoverlapping( |
128 copy_nonoverlapping( |
129 source.blocks[i].unwrap().as_ptr(), |
129 source.component_blocks[i].unwrap().as_ptr(), |
130 destination.blocks[i].unwrap().as_ptr(), |
130 destination.component_blocks[i].unwrap().as_ptr(), |
131 self.element_sizes[i] as usize, |
131 self.element_sizes[i] as usize, |
132 ); |
132 ); |
133 } |
133 } |
134 } |
134 } |
135 } |
135 } |
157 let block = &mut self.blocks[block_index as usize]; |
157 let block = &mut self.blocks[block_index as usize]; |
158 debug_assert!(index < block.elements_count); |
158 debug_assert!(index < block.elements_count); |
159 |
159 |
160 for (i, size) in self.element_sizes.iter().cloned().enumerate() { |
160 for (i, size) in self.element_sizes.iter().cloned().enumerate() { |
161 if index < block.elements_count - 1 { |
161 if index < block.elements_count - 1 { |
162 if let Some(ptr) = block.blocks[i] { |
162 if let Some(ptr) = block.component_blocks[i] { |
163 unsafe { |
163 unsafe { |
164 copy_nonoverlapping( |
164 copy_nonoverlapping( |
165 ptr.as_ptr() |
165 ptr.as_ptr() |
166 .add((size * (block.elements_count - 1)) as usize), |
166 .add((size * (block.elements_count - 1)) as usize), |
167 ptr.as_ptr().add((size * index) as usize), |
167 ptr.as_ptr().add((size * index) as usize), |
173 } |
173 } |
174 block.elements_count -= 1; |
174 block.elements_count -= 1; |
175 } |
175 } |
176 |
176 |
177 #[inline] |
177 #[inline] |
178 fn ensure_group(&mut self, mask: u64) -> u16 { |
178 fn ensure_block(&mut self, mask: u64) -> u16 { |
179 if let Some(index) = self |
179 if let Some(index) = self |
180 .block_masks |
180 .block_masks |
181 .iter() |
181 .iter() |
182 .enumerate() |
182 .enumerate() |
183 .position(|(i, m)| *m == mask && !self.blocks[i].is_full()) |
183 .position(|(i, m)| *m == mask && !self.blocks[i].is_full()) |
184 { |
184 { |
185 index as u16 |
185 index as u16 |
186 } else { |
186 } else { |
187 self.blocks.push(DataBlock::new(mask, &self.element_sizes)); |
187 self.blocks.push(DataBlock::new(mask, &self.element_sizes)); |
|
188 self.block_masks.push(mask); |
188 (self.blocks.len() - 1) as u16 |
189 (self.blocks.len() - 1) as u16 |
189 } |
190 } |
190 } |
191 } |
191 |
192 |
192 pub fn add<T: Clone + 'static>(&mut self, gear_id: GearId, value: &T) { |
193 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 if let Some(type_index) = self.get_type_index::<T>() { |
194 let type_bit = 1u64 << type_index as u64; |
195 let type_bit = 1 << type_index as u64; |
195 let entry = self.lookup[gear_id.get() as usize - 1]; |
196 let entry = self.lookup[gear_id.get() as usize - 1]; |
196 |
197 |
197 if let Some(index) = entry.index { |
198 if let Some(index) = entry.index { |
198 let mask = self.block_masks[entry.block_index as usize]; |
199 let mask = self.block_masks[entry.block_index as usize]; |
199 let new_mask = mask | type_bit; |
200 let new_mask = mask | type_bit; |
200 |
201 |
201 if new_mask != mask { |
202 if new_mask != mask { |
202 let dest_block_index = self.ensure_group(new_mask); |
203 let dest_block_index = self.ensure_block(new_mask); |
203 self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index); |
204 self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index); |
204 } |
205 } |
205 } else { |
206 } else { |
206 let dest_block_index = self.ensure_group(type_bit); |
207 let dest_block_index = self.ensure_block(type_bit); |
207 self.add_to_block(dest_block_index, value); |
208 self.add_to_block(dest_block_index, value); |
208 } |
209 } |
209 } else { |
210 } else { |
210 panic!("Unregistered type") |
211 panic!("Unregistered type") |
211 } |
212 } |
214 pub fn remove<T: 'static>(&mut self, gear_id: GearId) { |
215 pub fn remove<T: 'static>(&mut self, gear_id: GearId) { |
215 if let Some(type_index) = self.get_type_index::<T>() { |
216 if let Some(type_index) = self.get_type_index::<T>() { |
216 let entry = self.lookup[gear_id.get() as usize - 1]; |
217 let entry = self.lookup[gear_id.get() as usize - 1]; |
217 if let Some(index) = entry.index { |
218 if let Some(index) = entry.index { |
218 let destination_mask = |
219 let destination_mask = |
219 self.block_masks[entry.block_index as usize] & !(1u64 << type_index as u64); |
220 self.block_masks[entry.block_index as usize] & !(1 << type_index as u64); |
220 |
221 |
221 if destination_mask == 0 { |
222 if destination_mask == 0 { |
222 self.remove_all(gear_id) |
223 self.remove_all(gear_id) |
223 } else { |
224 } else { |
224 let destination_block_index = self.ensure_group(destination_mask); |
225 let destination_block_index = self.ensure_block(destination_mask); |
225 self.move_between_blocks( |
226 self.move_between_blocks( |
226 entry.block_index, |
227 entry.block_index, |
227 index.get() - 1, |
228 index.get() - 1, |
228 destination_block_index, |
229 destination_block_index, |
229 ); |
230 ); |
252 self.types.push(id); |
253 self.types.push(id); |
253 } |
254 } |
254 } |
255 } |
255 |
256 |
256 fn create_selector(&self, types: &[TypeId]) -> u64 { |
257 fn create_selector(&self, types: &[TypeId]) -> u64 { |
257 let mut selector = 0u64; |
258 let mut selector = 0; |
258 for (i, typ) in self.types.iter().enumerate() { |
259 for (i, typ) in self.types.iter().enumerate() { |
259 if types.contains(&typ) { |
260 if types.contains(&typ) { |
260 selector |= 1u64 << (i as u64) |
261 selector |= 1 << (i as u64) |
261 } |
262 } |
262 } |
263 } |
263 selector |
264 selector |
264 } |
265 } |
265 |
266 |
266 pub fn iter<T: TypeTuple + 'static, F: Fn(T) + Copy>(&self, f: F) { |
267 pub fn iter<T: TypeTuple + 'static, F: FnMut(T)>(&self, mut f: F) { |
267 let mut types = vec![]; |
268 let mut types = vec![]; |
268 T::get_types(&mut types); |
269 T::get_types(&mut types); |
269 debug_assert!(types.iter().all(|t| self.types.contains(t))); |
270 debug_assert!(types.iter().all(|t| self.types.contains(t))); |
270 |
271 |
271 let types_count = types.len(); |
272 let types_count = types.len(); |
272 let selector = self.create_selector(&types); |
273 let selector = self.create_selector(&types); |
273 |
274 |
|
275 let mut slices = Vec::with_capacity(64); |
|
276 |
274 for (block_index, mask) in self.block_masks.iter().enumerate() { |
277 for (block_index, mask) in self.block_masks.iter().enumerate() { |
275 if mask & selector == selector { |
278 if mask & selector == selector { |
|
279 slices.clear(); |
276 let block = &self.blocks[block_index]; |
280 let block = &self.blocks[block_index]; |
277 for element_index in 0..block.max_elements { |
281 |
278 unsafe { |
282 for (i, ptr_opt) in block.component_blocks.iter().cloned().enumerate() { |
279 T::iter(unimplemented!(), block.elements_count as usize, f); |
283 if let Some(ptr) = ptr_opt { |
|
284 slices.push(ptr); |
280 } |
285 } |
|
286 } |
|
287 |
|
288 unsafe { |
|
289 T::iter(&slices[..], block.elements_count as usize, |x| f(x)); |
281 } |
290 } |
282 } |
291 } |
283 } |
292 } |
284 } |
293 } |
285 } |
294 } |
286 |
295 |
287 #[cfg(test)] |
296 #[cfg(test)] |
288 mod test { |
297 mod test { |
289 use super::GearDataManager; |
298 use super::{super::common::GearId, GearDataManager}; |
290 |
299 |
|
300 #[derive(Clone)] |
291 struct Datum { |
301 struct Datum { |
292 value: u32, |
302 value: u32, |
293 } |
303 } |
294 |
304 |
295 #[test] |
305 #[test] |
296 fn iteration() { |
306 fn single_component_iteration() { |
|
307 assert!(std::mem::size_of::<Datum>() > 0); |
|
308 |
297 let mut manager = GearDataManager::new(); |
309 let mut manager = GearDataManager::new(); |
298 manager.register::<Datum>(); |
310 manager.register::<Datum>(); |
299 manager.iter(|d: (&Datum,)| {}); |
311 for i in 1..=5 { |
300 } |
312 manager.add(GearId::new(i as u16).unwrap(), &Datum { value: i }); |
301 } |
313 } |
|
314 |
|
315 let mut sum = 0; |
|
316 manager.iter(|(d,): (&Datum,)| sum += d.value); |
|
317 |
|
318 assert_eq!(sum, 15); |
|
319 } |
|
320 } |