legion_core/
entity.rs

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/// A handle to an entity.
16#[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/// Manages the allocation and deletion of `Entity` IDs within a world.
251#[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    /// Determines if the given `Entity` is considered alive.
266    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    /// Allocates a new unused `Entity` ID.
276    pub fn create_entity(&self) -> Entity { self.create_entities().next().unwrap() }
277
278    /// Creates an iterator which allocates new `Entity` IDs.
279    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 any entity in the block is in an allocated state, clear
299                // and repopulate the free list. This forces all entities into an
300                // unallocated state. Bump versions of all entity indexes to
301                // ensure that we don't reuse the same entity.
302                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        // try and allocate from the block we last used
336        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        // search for a block with spare entities
343        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        // allocate a new block
358        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}