sky_ecs 0.1.2

High-performance typed chunk-based ECS for Rust
Documentation
use super::parallel::{self, ParallelJobCache, ParallelJobSnapshot};
use super::{CachedArchetype, PreparedCache, QueryDescriptor, QueryFilter, QuerySpec};
use crate::ecs::World;
use rustc_hash::FxHashMap;
use std::any::TypeId;
use std::cell::RefCell;
use std::sync::Arc;

struct QueryCacheEntry {
    descriptor: QueryDescriptor,
    prepared: PreparedCache,
    parallel_jobs: ParallelJobCache,
}

#[derive(Default)]
pub(crate) struct QueryCacheStore {
    entries: RefCell<FxHashMap<TypeId, QueryCacheEntry>>,
}

impl QueryCacheStore {
    pub(crate) fn snapshot<Q, Flt>(&self, world: &World) -> Arc<Vec<CachedArchetype>>
    where
        Q: QuerySpec + 'static,
        Flt: QueryFilter + 'static,
    {
        let key = TypeId::of::<(Q, Flt)>();
        let mut entries = self.entries.borrow_mut();
        let entry = entries.entry(key).or_insert_with(|| QueryCacheEntry {
            descriptor: Q::descriptor(),
            prepared: PreparedCache::default(),
            parallel_jobs: ParallelJobCache::default(),
        });

        let QueryCacheEntry {
            descriptor,
            prepared,
            ..
        } = entry;
        prepared.prepare::<Flt>(world, descriptor);
        Arc::clone(&prepared.archetypes)
    }

    pub(crate) fn parallel_snapshot<Q, Flt>(
        &self,
        world: &World,
        archetypes: &[CachedArchetype],
    ) -> ParallelJobSnapshot
    where
        Q: QuerySpec + 'static,
        Flt: QueryFilter + 'static,
    {
        let key = TypeId::of::<(Q, Flt)>();
        let mut entries = self.entries.borrow_mut();
        let entry = entries
            .get_mut(&key)
            .expect("query plan must be prepared before parallel iteration");
        parallel::prepare_job_snapshot(&mut entry.parallel_jobs, archetypes, world)
    }

    #[cfg(test)]
    pub(crate) fn len(&self) -> usize {
        self.entries.borrow().len()
    }

    #[cfg(test)]
    pub(crate) fn parallel_rebuild_count<Q, Flt>(&self) -> usize
    where
        Q: QuerySpec + 'static,
        Flt: QueryFilter + 'static,
    {
        let key = TypeId::of::<(Q, Flt)>();
        self.entries
            .borrow()
            .get(&key)
            .map_or(0, |entry| parallel::rebuild_count(&entry.parallel_jobs))
    }
}