1 use super::common::GearId; |
1 use super::common::GearId; |
2 use std::{ |
2 use std::{ |
3 any::TypeId, |
3 any::TypeId, |
4 mem::{size_of, MaybeUninit}, |
4 mem::{size_of, MaybeUninit}, |
5 num::NonZeroU16, |
5 num::NonZeroU16, |
6 ptr::NonNull, |
6 ptr::{copy_nonoverlapping, NonNull}, |
7 slice, |
7 slice, |
8 }; |
8 }; |
9 |
9 |
10 pub unsafe trait TypeTuple: Sized { |
10 pub unsafe trait TypeTuple: Sized { |
11 fn len() -> usize; |
11 fn len() -> usize; |
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 { std::mem::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 & (164 << i) != 0 { |
110 let type_id = TypeId::of::<T>(); |
110 let type_id = TypeId::of::<T>(); |
111 self.types.iter().position(|id| *id == type_id) |
111 self.types.iter().position(|id| *id == type_id) |
112 } |
112 } |
113 |
113 |
114 fn move_between_blocks(&mut self, from_block_index: u16, from_index: u16, to_block_index: u16) { |
114 fn move_between_blocks(&mut self, from_block_index: u16, from_index: u16, to_block_index: u16) { |
|
115 debug_assert!(from_block_index != to_block_index); |
115 let source_mask = self.block_masks[from_block_index as usize]; |
116 let source_mask = self.block_masks[from_block_index as usize]; |
116 let destination_mask = self.block_masks[to_block_index as usize]; |
117 let destination_mask = self.block_masks[to_block_index as usize]; |
117 debug_assert!(source_mask & destination_mask == source_mask); |
118 debug_assert!(source_mask & destination_mask == source_mask); |
118 |
119 |
119 let source = &self.blocks[from_block_index as usize]; |
120 let source = &self.blocks[from_block_index as usize]; |
120 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); |
|
123 debug_assert!(!destination.is_full()); |
|
124 |
121 for i in 0..64 { |
125 for i in 0..64 { |
122 unimplemented!() |
126 if source_mask & 1u64 << i != 0 { |
123 } |
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 } |
|
135 } |
|
136 self.blocks[from_block_index as usize].elements_count -= 1; |
|
137 self.blocks[to_block_index as usize].elements_count += 1; |
124 } |
138 } |
125 |
139 |
126 fn add_to_block<T: Clone>(&mut self, block_index: u16, value: &T) { |
140 fn add_to_block<T: Clone>(&mut self, block_index: u16, value: &T) { |
127 debug_assert!(self.block_masks[block_index as usize].count_ones() == 1); |
141 debug_assert!(self.block_masks[block_index as usize].count_ones() == 1); |
128 |
142 |
143 let block = &mut self.blocks[block_index as usize]; |
157 let block = &mut self.blocks[block_index as usize]; |
144 debug_assert!(index < block.elements_count); |
158 debug_assert!(index < block.elements_count); |
145 |
159 |
146 for (i, size) in self.element_sizes.iter().cloned().enumerate() { |
160 for (i, size) in self.element_sizes.iter().cloned().enumerate() { |
147 if index < block.elements_count - 1 { |
161 if index < block.elements_count - 1 { |
148 if let Some(mut ptr) = block.blocks[i] { |
162 if let Some(ptr) = block.blocks[i] { |
149 unsafe { |
163 unsafe { |
150 std::ptr::copy_nonoverlapping( |
164 copy_nonoverlapping( |
151 ptr.as_ptr() |
165 ptr.as_ptr() |
152 .add((size * (block.elements_count - 1)) as usize), |
166 .add((size * (block.elements_count - 1)) as usize), |
153 ptr.as_ptr().add((size * index) as usize), |
167 ptr.as_ptr().add((size * index) as usize), |
154 size as usize, |
168 size as usize, |
155 ); |
169 ); |
199 |
213 |
200 pub fn remove<T: 'static>(&mut self, gear_id: GearId) { |
214 pub fn remove<T: 'static>(&mut self, gear_id: GearId) { |
201 if let Some(type_index) = self.get_type_index::<T>() { |
215 if let Some(type_index) = self.get_type_index::<T>() { |
202 let entry = self.lookup[gear_id.get() as usize - 1]; |
216 let entry = self.lookup[gear_id.get() as usize - 1]; |
203 if let Some(index) = entry.index { |
217 if let Some(index) = entry.index { |
204 self.remove_from_block(entry.block_index, index.get() - 1); |
218 let destination_mask = |
205 } |
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 } |
|
231 } |
|
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); |
206 } |
241 } |
207 } |
242 } |
208 |
243 |
209 pub fn register<T: 'static>(&mut self) { |
244 pub fn register<T: 'static>(&mut self) { |
210 debug_assert!(!std::mem::needs_drop::<T>()); |
245 debug_assert!(!std::mem::needs_drop::<T>()); |