1use crate::index::ArchetypeIndex;
2use crate::index::ChunkIndex;
3use crate::index::ComponentIndex;
4use crate::index::SetIndex;
5use parking_lot::{Mutex, RwLock, RwLockWriteGuard};
6use std::fmt::Display;
7use std::num::Wrapping;
8use std::ops::Deref;
9use std::ops::DerefMut;
10use std::sync::Arc;
11
12pub type EntityIndex = u32;
13pub(crate) type EntityVersion = Wrapping<u32>;
14
15#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
17pub struct Entity {
18 index: EntityIndex,
19 version: EntityVersion,
20}
21
22impl Entity {
23 pub(crate) fn new(index: EntityIndex, version: EntityVersion) -> Entity {
24 Entity { index, version }
25 }
26
27 pub fn index(self) -> EntityIndex { self.index }
28}
29
30impl Display for Entity {
31 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
32 write!(f, "{}#{}", self.index, self.version)
33 }
34}
35
36#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
37pub struct EntityLocation {
38 archetype_index: ArchetypeIndex,
39 set_index: SetIndex,
40 chunk_index: ChunkIndex,
41 component_index: ComponentIndex,
42}
43
44impl EntityLocation {
45 pub(crate) fn new(
46 archetype_index: ArchetypeIndex,
47 set_index: SetIndex,
48 chunk_index: ChunkIndex,
49 component_index: ComponentIndex,
50 ) -> Self {
51 EntityLocation {
52 archetype_index,
53 set_index,
54 chunk_index,
55 component_index,
56 }
57 }
58
59 pub fn archetype(&self) -> ArchetypeIndex { self.archetype_index }
60
61 pub fn set(&self) -> SetIndex { self.set_index }
62
63 pub fn chunk(&self) -> ChunkIndex { self.chunk_index }
64
65 pub fn component(&self) -> ComponentIndex { self.component_index }
66}
67
68pub(crate) struct Locations {
69 blocks: Vec<Option<Vec<EntityLocation>>>,
70}
71
72impl Locations {
73 pub fn new() -> Self { Locations { blocks: Vec::new() } }
74
75 fn index(entity: EntityIndex) -> (usize, usize) {
76 let block = entity as usize / BlockAllocator::BLOCK_SIZE;
77 let index = entity as usize - block * BlockAllocator::BLOCK_SIZE;
78 (block, index)
79 }
80
81 pub fn get(&self, entity: Entity) -> Option<EntityLocation> {
82 let (block, index) = Locations::index(entity.index());
83 self.blocks
84 .get(block)
85 .map(|b| b.as_ref())
86 .flatten()
87 .map(|b| b[index])
88 }
89
90 pub fn set(&mut self, entity: Entity, location: EntityLocation) {
91 let (block_index, index) = Locations::index(entity.index());
92 if self.blocks.len() <= block_index {
93 let fill = block_index - self.blocks.len() + 1;
94 self.blocks.extend((0..fill).map(|_| None));
95 }
96
97 let block_opt = &mut self.blocks[block_index];
98 let block = block_opt.get_or_insert_with(|| {
99 std::iter::repeat(EntityLocation::new(
100 ArchetypeIndex(0),
101 SetIndex(0),
102 ChunkIndex(0),
103 ComponentIndex(0),
104 ))
105 .take(BlockAllocator::BLOCK_SIZE)
106 .collect()
107 });
108
109 block[index] = location;
110 }
111}
112
113#[derive(Debug)]
114pub(crate) struct BlockAllocator {
115 allocated: usize,
116 free: Vec<EntityBlock>,
117}
118
119impl BlockAllocator {
120 const BLOCK_SIZE: usize = 1024;
121
122 pub(crate) fn new() -> Self {
123 BlockAllocator {
124 allocated: 0,
125 free: Vec::new(),
126 }
127 }
128
129 pub fn allocate(&mut self) -> EntityBlock {
130 if let Some(block) = self.free.pop() {
131 block
132 } else {
133 let block = EntityBlock::new(self.allocated as EntityIndex, BlockAllocator::BLOCK_SIZE);
134 self.allocated += BlockAllocator::BLOCK_SIZE;
135 block
136 }
137 }
138
139 pub fn free(&mut self, block: EntityBlock) { self.free.push(block); }
140}
141
142#[derive(Debug)]
143pub struct EntityBlock {
144 start: EntityIndex,
145 len: usize,
146 versions: Vec<EntityVersion>,
147 free: Vec<EntityIndex>,
148}
149
150impl EntityBlock {
151 pub fn new(start: EntityIndex, len: usize) -> EntityBlock {
152 EntityBlock {
153 start,
154 len,
155 versions: Vec::with_capacity(len),
156 free: Vec::new(),
157 }
158 }
159
160 fn index(&self, index: EntityIndex) -> usize { (index - self.start) as usize }
161
162 pub fn in_range(&self, index: EntityIndex) -> bool {
163 index >= self.start && index < (self.start + self.len as u32)
164 }
165
166 pub fn is_alive(&self, entity: Entity) -> Option<bool> {
167 if entity.index >= self.start {
168 let i = self.index(entity.index);
169 self.versions.get(i).map(|v| *v == entity.version)
170 } else {
171 None
172 }
173 }
174
175 pub fn allocate(&mut self) -> Option<Entity> {
176 if let Some(index) = self.free.pop() {
177 let i = self.index(index);
178 Some(Entity::new(index, self.versions[i]))
179 } else if self.versions.len() < self.len {
180 let index = self.start + self.versions.len() as EntityIndex;
181 self.versions.push(Wrapping(1));
182 Some(Entity::new(index, Wrapping(1)))
183 } else {
184 None
185 }
186 }
187
188 pub fn free(&mut self, entity: Entity) -> bool {
189 if let Some(true) = self.is_alive(entity) {
190 let i = self.index(entity.index);
191 self.versions[i] += Wrapping(1);
192 self.free.push(entity.index);
193 true
194 } else {
195 false
196 }
197 }
198}
199
200#[derive(Debug)]
201struct Blocks {
202 blocks: Vec<Option<EntityBlock>>,
203}
204
205impl Blocks {
206 fn new() -> Self { Self { blocks: Vec::new() } }
207
208 pub fn index(entity: EntityIndex) -> usize { entity as usize / BlockAllocator::BLOCK_SIZE }
209
210 fn find(&self, entity: EntityIndex) -> Option<&EntityBlock> {
211 let i = Blocks::index(entity);
212 self.blocks.get(i).map(|b| b.as_ref()).flatten()
213 }
214
215 fn find_mut(&mut self, entity: EntityIndex) -> Option<&mut EntityBlock> {
216 let i = Blocks::index(entity);
217 self.blocks.get_mut(i).map(|b| b.as_mut()).flatten()
218 }
219
220 fn push(&mut self, block: EntityBlock) -> usize {
221 let i = Blocks::index(block.start);
222 if self.blocks.len() > i {
223 self.blocks[i] = Some(block);
224 } else {
225 let fill = i - self.blocks.len();
226 self.blocks.extend((0..fill).map(|_| None));
227 self.blocks.push(Some(block));
228 }
229 i
230 }
231
232 fn append(&mut self, other: &mut Blocks) {
233 for block in other.blocks.drain(..) {
234 if let Some(block) = block {
235 self.push(block);
236 }
237 }
238 }
239}
240
241impl Deref for Blocks {
242 type Target = [Option<EntityBlock>];
243 fn deref(&self) -> &Self::Target { self.blocks.deref() }
244}
245
246impl DerefMut for Blocks {
247 fn deref_mut(&mut self) -> &mut Self::Target { self.blocks.deref_mut() }
248}
249
250#[derive(Debug)]
252pub struct EntityAllocator {
253 allocator: Arc<Mutex<BlockAllocator>>,
254 blocks: RwLock<Blocks>,
255}
256
257impl EntityAllocator {
258 pub(crate) fn new(allocator: Arc<Mutex<BlockAllocator>>) -> Self {
259 EntityAllocator {
260 allocator,
261 blocks: RwLock::new(Blocks::new()),
262 }
263 }
264
265 pub fn is_alive(&self, entity: Entity) -> bool {
267 self.blocks
268 .read()
269 .find(entity.index())
270 .map(|b| b.is_alive(entity))
271 .flatten()
272 .unwrap_or(false)
273 }
274
275 pub fn create_entity(&self) -> Entity { self.create_entities().next().unwrap() }
277
278 pub fn create_entities(&self) -> CreateEntityIter {
280 CreateEntityIter {
281 blocks: self.blocks.write(),
282 allocator: &self.allocator,
283 current_block: None,
284 }
285 }
286
287 pub(crate) fn delete_entity(&self, entity: Entity) -> bool {
288 self.blocks
289 .write()
290 .find_mut(entity.index())
291 .map(|b| b.free(entity))
292 .unwrap_or(false)
293 }
294
295 pub(crate) fn delete_all_entities(&self) {
296 for block in self.blocks.write().blocks.drain(..) {
297 if let Some(mut block) = block {
298 if block.free.len() < block.versions.len() {
303 block.free.clear();
304 for (i, version) in block.versions.iter_mut().enumerate() {
305 *version += Wrapping(1);
306 block.free.push(i as u32 + block.start);
307 }
308 }
309
310 self.allocator.lock().free(block);
311 }
312 }
313 }
314
315 pub(crate) fn merge(&self, other: EntityAllocator) {
316 assert!(Arc::ptr_eq(&self.allocator, &other.allocator));
317 self.blocks.write().append(&mut *other.blocks.write());
318 }
319}
320
321impl Drop for EntityAllocator {
322 fn drop(&mut self) { self.delete_all_entities(); }
323}
324
325pub struct CreateEntityIter<'a> {
326 current_block: Option<usize>,
327 blocks: RwLockWriteGuard<'a, Blocks>,
328 allocator: &'a Mutex<BlockAllocator>,
329}
330
331impl<'a> Iterator for CreateEntityIter<'a> {
332 type Item = Entity;
333
334 fn next(&mut self) -> Option<Self::Item> {
335 if let Some(block) = self.current_block {
337 if let Some(entity) = self.blocks[block].as_mut().unwrap().allocate() {
338 return Some(entity);
339 }
340 }
341
342 for (i, allocated) in self
344 .blocks
345 .iter_mut()
346 .enumerate()
347 .rev()
348 .filter(|(_, b)| b.is_some())
349 .map(|(i, b)| (i, b.as_mut().unwrap().allocate()))
350 {
351 if let Some(entity) = allocated {
352 self.current_block = Some(i);
353 return Some(entity);
354 }
355 }
356
357 let mut block = self.allocator.lock().allocate();
359 let entity = block.allocate().unwrap();
360 self.current_block = Some(self.blocks.push(block));
361 Some(entity)
362 }
363}
364
365#[cfg(test)]
366mod tests {
367 use crate::entity::*;
368 use std::collections::HashSet;
369
370 #[test]
371 fn create_entity() {
372 let allocator = EntityAllocator::new(Arc::from(Mutex::new(BlockAllocator::new())));
373 allocator.create_entity();
374 }
375
376 #[test]
377 fn create_entity_many() {
378 let allocator = EntityAllocator::new(Arc::from(Mutex::new(BlockAllocator::new())));
379
380 for _ in 0..512 {
381 allocator.create_entity();
382 }
383 }
384
385 #[test]
386 fn create_entity_many_blocks() {
387 let allocator = EntityAllocator::new(Arc::from(Mutex::new(BlockAllocator::new())));
388
389 for _ in 0..3000 {
390 allocator.create_entity();
391 }
392 }
393
394 #[test]
395 fn create_entity_recreate() {
396 let allocator = EntityAllocator::new(Arc::from(Mutex::new(BlockAllocator::new())));
397
398 for _ in 0..3 {
399 let entities: Vec<Entity> = (0..512).map(|_| allocator.create_entity()).collect();
400 for e in entities {
401 allocator.delete_entity(e);
402 }
403 }
404 }
405
406 #[test]
407 fn is_alive_allocated() {
408 let allocator = EntityAllocator::new(Arc::from(Mutex::new(BlockAllocator::new())));
409 let entity = allocator.create_entity();
410
411 assert_eq!(true, allocator.is_alive(entity));
412 }
413
414 #[test]
415 fn is_alive_unallocated() {
416 let allocator = EntityAllocator::new(Arc::from(Mutex::new(BlockAllocator::new())));
417 let entity = Entity::new(10 as EntityIndex, Wrapping(10));
418
419 assert_eq!(false, allocator.is_alive(entity));
420 }
421
422 #[test]
423 fn is_alive_killed() {
424 let allocator = EntityAllocator::new(Arc::from(Mutex::new(BlockAllocator::new())));
425 let entity = allocator.create_entity();
426 allocator.delete_entity(entity);
427
428 assert_eq!(false, allocator.is_alive(entity));
429 }
430
431 #[test]
432 fn delete_entity_was_alive() {
433 let allocator = EntityAllocator::new(Arc::from(Mutex::new(BlockAllocator::new())));
434 let entity = allocator.create_entity();
435
436 assert_eq!(true, allocator.delete_entity(entity));
437 }
438
439 #[test]
440 fn delete_entity_was_dead() {
441 let allocator = EntityAllocator::new(Arc::from(Mutex::new(BlockAllocator::new())));
442 let entity = allocator.create_entity();
443 allocator.delete_entity(entity);
444
445 assert_eq!(false, allocator.delete_entity(entity));
446 }
447
448 #[test]
449 fn delete_entity_was_unallocated() {
450 let allocator = EntityAllocator::new(Arc::from(Mutex::new(BlockAllocator::new())));
451 let entity = Entity::new(10 as EntityIndex, Wrapping(10));
452
453 assert_eq!(false, allocator.delete_entity(entity));
454 }
455
456 #[test]
457 fn multiple_allocators_unique_ids() {
458 let blocks = Arc::from(Mutex::new(BlockAllocator::new()));
459 let allocator_a = EntityAllocator::new(blocks.clone());
460 let allocator_b = EntityAllocator::new(blocks);
461
462 let mut entities_a = HashSet::<Entity>::default();
463 let mut entities_b = HashSet::<Entity>::default();
464
465 for _ in 0..5 {
466 entities_a.extend((0..1500).map(|_| allocator_a.create_entity()));
467 entities_b.extend((0..1500).map(|_| allocator_b.create_entity()));
468 }
469
470 assert_eq!(true, entities_a.is_disjoint(&entities_b));
471
472 for e in entities_a {
473 assert_eq!(true, allocator_a.is_alive(e));
474 assert_eq!(false, allocator_b.is_alive(e));
475 }
476
477 for e in entities_b {
478 assert_eq!(false, allocator_a.is_alive(e));
479 assert_eq!(true, allocator_b.is_alive(e));
480 }
481 }
482}