rust/hwphysics/src/data.rs
changeset 15358 b5e0a39856fd
parent 15357 135c29237a56
child 15367 d6b4586b271f
equal deleted inserted replaced
15357:135c29237a56 15358:b5e0a39856fd
     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 }