1 use std::any::{Any, TypeId}; |
1 use super::common::GearId; |
2 |
2 use std::{ |
3 const BLOCK_SIZE: usize = 8192; |
3 any::TypeId, |
4 |
4 mem::{size_of, MaybeUninit}, |
5 pub trait TypeTuple { |
5 num::NonZeroU16, |
6 type Storage: Default; |
6 ptr::NonNull, |
7 |
7 slice, |
|
8 }; |
|
9 |
|
10 pub trait TypeTuple: Sized { |
8 fn len() -> usize; |
11 fn len() -> usize; |
9 fn get_types(dest: &mut Vec<TypeId>); |
12 fn get_types(dest: &mut Vec<TypeId>); |
10 } |
13 unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, f: F) |
11 |
14 where |
12 //TODO macroise this template for tuples up to sufficient size |
15 F: Fn(Self); |
13 impl<T: 'static> TypeTuple for (T,) { |
16 } |
14 type Storage = (Vec<T>,); |
17 |
15 |
18 impl<T: 'static> TypeTuple for (&T,) { |
16 #[inline] |
|
17 fn len() -> usize { |
19 fn len() -> usize { |
18 1 |
20 1 |
19 } |
21 } |
20 |
22 |
21 #[inline] |
|
22 fn get_types(dest: &mut Vec<TypeId>) { |
23 fn get_types(dest: &mut Vec<TypeId>) { |
23 dest.push(TypeId::of::<T>()); |
24 dest.push(TypeId::of::<T>()); |
24 } |
25 } |
25 } |
26 |
26 |
27 unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, f: F) |
27 pub struct GearDataCollection<T: TypeTuple> { |
28 where |
28 len: usize, |
29 F: Fn(Self), |
29 blocks: T::Storage, |
30 { |
30 } |
31 let slice1 = slice::from_raw_parts(slices[0].as_ptr() as *const T, count); |
31 |
32 for i in 0..count { |
32 impl<T: TypeTuple> GearDataCollection<T> { |
33 f((slice1.get_unchecked(i),)); |
33 fn new() -> Self { |
34 } |
|
35 } |
|
36 } |
|
37 |
|
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], |
|
45 } |
|
46 |
|
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]> = |
|
60 Box::new(unsafe { std::mem::MaybeUninit::uninit().assume_init() }); |
|
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 } |
34 Self { |
70 Self { |
35 len: 0, |
71 elements_count: 0, |
36 blocks: T::Storage::default(), |
72 max_elements, |
37 } |
73 data, |
38 } |
74 blocks, |
39 |
75 } |
40 fn iter<F: Fn(T)>(&self, f: F) {} |
76 } |
41 } |
77 |
42 |
78 fn is_full(&self) -> bool { |
43 pub struct GearDataGroup { |
79 self.elements_count == self.max_elements |
44 group_selector: u64, |
80 } |
45 data: Box<dyn Any + 'static>, |
81 } |
46 } |
82 |
47 |
83 #[derive(Clone, Copy, Debug, Default)] |
48 impl GearDataGroup { |
84 pub struct LookupEntry { |
49 fn iter() {} |
85 index: Option<NonZeroU16>, |
|
86 block_index: u16, |
50 } |
87 } |
51 |
88 |
52 pub struct GearDataManager { |
89 pub struct GearDataManager { |
53 types: Vec<TypeId>, |
90 types: Vec<TypeId>, |
54 groups: Vec<GearDataGroup>, |
91 blocks: Vec<DataBlock>, |
|
92 block_masks: Vec<u64>, |
|
93 element_sizes: Box<[u16; 64]>, |
|
94 lookup: Box<[LookupEntry]>, |
55 } |
95 } |
56 |
96 |
57 impl GearDataManager { |
97 impl GearDataManager { |
58 pub fn new() -> Self { |
98 pub fn new() -> Self { |
59 Self { |
99 Self { |
60 types: vec![], |
100 types: vec![], |
61 groups: vec![], |
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) { |
|
115 let source_mask = self.block_masks[from_block_index as usize]; |
|
116 let destination_mask = self.block_masks[to_block_index as usize]; |
|
117 debug_assert!(source_mask & destination_mask == source_mask); |
|
118 |
|
119 let source = &self.blocks[from_block_index as usize]; |
|
120 let destination = &self.blocks[to_block_index as usize]; |
|
121 for i in 0..64 { |
|
122 unimplemented!() |
|
123 } |
|
124 } |
|
125 |
|
126 fn add_to_block<T>(&mut self, block_index: u16, value: &T) { |
|
127 unimplemented!() |
|
128 } |
|
129 |
|
130 fn remove_from_block(&mut self, block_index: u16, index: u16) { |
|
131 unimplemented!() |
|
132 } |
|
133 |
|
134 #[inline] |
|
135 fn ensure_group(&mut self, mask: u64) -> u16 { |
|
136 if let Some(index) = self |
|
137 .block_masks |
|
138 .iter() |
|
139 .enumerate() |
|
140 .position(|(i, m)| *m == mask && !self.blocks[i].is_full()) |
|
141 { |
|
142 index as u16 |
|
143 } else { |
|
144 self.blocks.push(DataBlock::new(mask, &self.element_sizes)); |
|
145 (self.blocks.len() - 1) as u16 |
|
146 } |
|
147 } |
|
148 |
|
149 pub fn add<T: Clone + 'static>(&mut self, gear_id: GearId, value: &T) { |
|
150 if let Some(type_index) = self.get_type_index::<T>() { |
|
151 let type_bit = 1u64 << type_index as u64; |
|
152 let entry = self.lookup[gear_id.get() as usize - 1]; |
|
153 |
|
154 if let Some(index) = entry.index { |
|
155 let mask = self.block_masks[entry.block_index as usize]; |
|
156 let new_mask = mask | type_bit; |
|
157 |
|
158 if new_mask != mask { |
|
159 let dest_block_index = self.ensure_group(new_mask); |
|
160 self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index); |
|
161 } |
|
162 } else { |
|
163 let dest_block_index = self.ensure_group(type_bit); |
|
164 self.add_to_block(dest_block_index, value); |
|
165 } |
|
166 } else { |
|
167 panic!("Unregistered type") |
|
168 } |
|
169 } |
|
170 |
|
171 pub fn remove<T: 'static>(&mut self, gear_id: GearId) { |
|
172 if let Some(type_index) = self.get_type_index::<T>() { |
|
173 let entry = self.lookup[gear_id.get() as usize - 1]; |
|
174 if let Some(index) = entry.index { |
|
175 self.remove_from_block(entry.block_index, index.get() - 1); |
|
176 } |
62 } |
177 } |
63 } |
178 } |
64 |
179 |
65 pub fn register<T: 'static>(&mut self) { |
180 pub fn register<T: 'static>(&mut self) { |
|
181 assert!(!std::mem::needs_drop::<T>()); |
66 assert!(self.types.len() <= 64); |
182 assert!(self.types.len() <= 64); |
|
183 assert!(size_of::<T>() <= u16::max_value() as usize); |
|
184 |
67 let id = TypeId::of::<T>(); |
185 let id = TypeId::of::<T>(); |
68 if !self.types.contains(&id) { |
186 if !self.types.contains(&id) { |
|
187 self.element_sizes[self.types.len()] = size_of::<T>() as u16; |
69 self.types.push(id); |
188 self.types.push(id); |
70 } |
189 } |
71 } |
190 } |
72 |
191 |
73 fn create_selector(&self, types: &[TypeId]) -> u64 { |
192 fn create_selector(&self, types: &[TypeId]) -> u64 { |
74 let mut selector = 0u64; |
193 let mut selector = 0u64; |
75 for (i, typ) in self.types.iter().enumerate() { |
194 for (i, typ) in self.types.iter().enumerate() { |
76 if types.contains(&typ) { |
195 if types.contains(&typ) { |
77 selector |= 1 << (i as u64) |
196 selector |= 1u64 << (i as u64) |
78 } |
197 } |
79 } |
198 } |
80 selector |
199 selector |
81 } |
200 } |
82 |
201 |
83 pub fn iter<T: TypeTuple + 'static, F: Fn(T) + Copy>(&self, f: F) { |
202 pub fn iter<T: TypeTuple + 'static, F: Fn(T) + Copy>(&self, f: F) { |
84 let mut types = vec![]; |
203 let mut types = vec![]; |
85 T::get_types(&mut types); |
204 T::get_types(&mut types); |
|
205 let types_count = types.len(); |
|
206 |
86 let selector = self.create_selector(&types); |
207 let selector = self.create_selector(&types); |
87 for group in &self.groups { |
208 for (block_index, mask) in self.block_masks.iter().enumerate() { |
88 if group.group_selector & selector == selector { |
209 if mask & selector == selector { |
89 group |
210 let block = &self.blocks[block_index]; |
90 .data |
211 for element_index in 0..block.max_elements { |
91 .downcast_ref::<GearDataCollection<T>>() |
212 unimplemented!() |
92 .unwrap() |
213 } |
93 .iter(f); |
214 } |
94 } |
215 } |
95 } |
216 } |
96 } |
217 } |
97 } |
218 |
|
219 #[cfg(test)] |
|
220 mod test { |
|
221 use super::GearDataManager; |
|
222 |
|
223 struct Datum { |
|
224 value: u32, |
|
225 } |
|
226 |
|
227 #[test] |
|
228 fn iteration() { |
|
229 let mut manager = GearDataManager::new(); |
|
230 manager.register::<Datum>(); |
|
231 manager.iter(|d: (&Datum,)| {}); |
|
232 } |
|
233 } |