# HG changeset patch # User alfadur # Date 1567279829 -10800 # Node ID 90a79670de528fd2a6bc1c70cf237218dc2788b4 # Parent 2805681aca54d52841be95bc881d9279d0d42188 allow registering zero-sized types diff -r 2805681aca54 -r 90a79670de52 rust/hwphysics/src/data.rs --- a/rust/hwphysics/src/data.rs Sat Aug 31 20:31:10 2019 +0200 +++ b/rust/hwphysics/src/data.rs Sat Aug 31 22:30:29 2019 +0300 @@ -10,7 +10,7 @@ pub trait TypeTuple: Sized { fn get_types(types: &mut Vec); - unsafe fn iter(slices: &[*mut u8], count: usize, mut f: F); + unsafe fn iter(slices: &[*mut u8], count: usize, f: F); } macro_rules! type_tuple_impl { @@ -166,10 +166,37 @@ } } +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +struct BlockMask { + type_mask: u64, + tag_mask: u64, +} + +impl BlockMask { + #[inline] + fn new(type_mask: u64, tag_mask: u64) -> Self { + Self { + type_mask, + tag_mask, + } + } + + #[inline] + fn with_type(&self, type_bit: u64) -> Self { + Self::new(self.type_mask | type_bit, self.tag_mask) + } + + #[inline] + fn with_tag(&self, tag_bit: u64) -> Self { + Self::new(self.type_mask, self.tag_mask | tag_bit) + } +} + pub struct GearDataManager { types: Vec, + tags: Vec, blocks: Vec, - block_masks: Vec, + block_masks: Vec, element_sizes: Box<[u16; 64]>, lookup: Box<[LookupEntry]>, } @@ -177,7 +204,8 @@ impl GearDataManager { pub fn new() -> Self { Self { - types: vec![], + types: Vec::with_capacity(64), + tags: Vec::with_capacity(64), blocks: vec![], block_masks: vec![], element_sizes: Box::new([0; 64]), @@ -191,11 +219,17 @@ self.types.iter().position(|id| *id == type_id) } + #[inline] + fn get_tag_index(&self) -> Option { + let type_id = TypeId::of::(); + self.tags.iter().position(|id| *id == type_id) + } + fn move_between_blocks(&mut self, src_block_index: u16, src_index: u16, dest_block_index: u16) { debug_assert!(src_block_index != dest_block_index); let src_mask = self.block_masks[src_block_index as usize]; let dest_mask = self.block_masks[dest_block_index as usize]; - debug_assert!(src_mask & dest_mask == src_mask); + debug_assert!(src_mask.type_mask & dest_mask.type_mask == src_mask.type_mask); let src_block = &self.blocks[src_block_index as usize]; let dest_block = &self.blocks[dest_block_index as usize]; @@ -204,7 +238,7 @@ let dest_index = dest_block.elements_count; for i in 0..self.types.len() { - if src_mask & (1 << i as u64) != 0 { + if src_mask.type_mask & (1 << i as u64) != 0 { let size = self.element_sizes[i]; let src_ptr = src_block.component_blocks[i].unwrap().as_ptr(); let dest_ptr = dest_block.component_blocks[i].unwrap().as_ptr(); @@ -248,7 +282,12 @@ } fn add_to_block(&mut self, gear_id: GearId, block_index: u16, value: &T) { - debug_assert!(self.block_masks[block_index as usize].count_ones() == 1); + debug_assert!( + self.block_masks[block_index as usize] + .type_mask + .count_ones() + == 1 + ); let block = &mut self.blocks[block_index as usize]; debug_assert!(block.elements_count < block.max_elements); @@ -299,7 +338,7 @@ } #[inline] - fn ensure_block(&mut self, mask: u64) -> u16 { + fn ensure_block(&mut self, mask: BlockMask) -> u16 { if let Some(index) = self .block_masks .iter() @@ -309,7 +348,7 @@ index as u16 } else { self.blocks.push(DataBlock::new( - mask, + mask.type_mask, &self.element_sizes[0..self.types.len()], )); self.block_masks.push(mask); @@ -324,14 +363,14 @@ if let Some(index) = entry.index { let mask = self.block_masks[entry.block_index as usize]; - let new_mask = mask | type_bit; + let new_mask = mask.with_type(type_bit); if new_mask != mask { let dest_block_index = self.ensure_block(new_mask); self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index); } } else { - let dest_block_index = self.ensure_block(type_bit); + let dest_block_index = self.ensure_block(BlockMask::new(type_bit, 0)); self.add_to_block(gear_id, dest_block_index, value); } } else { @@ -339,15 +378,36 @@ } } + pub fn add_tag(&mut self, gear_id: GearId) { + if let Some(tag_index) = self.get_tag_index::() { + let tag_bit = 1 << tag_index as u64; + let entry = self.lookup[gear_id.get() as usize - 1]; + + if let Some(index) = entry.index { + let mask = self.block_masks[entry.block_index as usize]; + let new_mask = mask.with_tag(tag_bit); + + if new_mask != mask { + let dest_block_index = self.ensure_block(new_mask); + self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index); + } + } else { + panic!("Cannot tag a gear with no data") + } + } else { + panic!("Unregistered tag") + } + } + pub fn remove(&mut self, gear_id: GearId) { if let Some(type_index) = self.get_type_index::() { let entry = self.lookup[gear_id.get() as usize - 1]; if let Some(index) = entry.index { - let dest_mask = - self.block_masks[entry.block_index as usize] & !(1 << type_index as u64); + let mut dest_mask = self.block_masks[entry.block_index as usize]; + dest_mask.type_mask &= !(1 << type_index as u64); - if dest_mask == 0 { - self.remove_all(gear_id) + if dest_mask.type_mask == 0 { + self.remove_from_block(entry.block_index, index.get() - 1); } else { let dest_block_index = self.ensure_block(dest_mask); self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index); @@ -367,16 +427,24 @@ pub fn register(&mut self) { debug_assert!(!std::mem::needs_drop::()); - debug_assert!(self.types.len() <= 64); debug_assert!(size_of::() <= u16::max_value() as usize); let id = TypeId::of::(); - if !self.types.contains(&id) { - self.element_sizes[self.types.len()] = size_of::() as u16; - self.types.push(id); + if size_of::() == 0 { + if !self.tags.contains(&id) { + debug_assert!(self.tags.len() <= 64); + self.tags.push(id) + } + } else { + if !self.types.contains(&id) { + debug_assert!(self.types.len() <= 64); + self.element_sizes[self.types.len()] = size_of::() as u16; + self.types.push(id); + } } } + #[inline] pub fn iter(&mut self, mut f: F) { self.iter_id(|_, x| f(x)); } @@ -401,7 +469,7 @@ let mut slices = vec![null_mut(); arg_types.len() + 1]; for (block_index, mask) in self.block_masks.iter().enumerate() { - if mask & selector == selector { + if mask.type_mask & selector == selector { let block = &mut self.blocks[block_index]; slices[0] = block.data.as_mut_ptr();