my_ecs/ecs/sys/
request.rs

1use super::{
2    query::{
3        EntQueryInfo, EntQueryKey, EntQueryMut, Query, QueryInfo, QueryKey, QueryMut, ResQuery,
4        ResQueryInfo, ResQueryKey, ResQueryMut, StoreEntQueryInfo, StoreQueryInfo,
5        StoreResQueryInfo,
6    },
7    select::{
8        FilterInfo, FilterKey, FilteredRaw, SelectInfo, SelectKey, SelectedRaw, StoreFilterInfo,
9        StoreSelectInfo,
10    },
11};
12use crate::{
13    ds::{ATypeId, Borrowed, ManagedConstPtr, ManagedMutPtr},
14    ecs::resource::ResourceKey,
15    util::macros::debug_format,
16    DefaultRandomState,
17};
18use std::{
19    any,
20    collections::HashMap,
21    fmt,
22    hash::BuildHasher,
23    marker::PhantomData,
24    ptr::NonNull,
25    sync::{Arc, LazyLock, Mutex},
26};
27
28/// A storage including request, query and filter information together.
29//
30// When a system is registered, it's corresponding request and
31// related other information is registered here, and it can be shared from other systems.
32// When it comes to unregister, each system data will unregister itself from
33// this storage when it's dropped.
34pub(crate) static RINFO_STOR: LazyLock<Arc<Mutex<RequestInfoStorage<DefaultRandomState>>>> =
35    const { LazyLock::new(|| Arc::new(Mutex::new(RequestInfoStorage::new()))) };
36
37/// Storage containing request and other info.
38#[derive(Debug)]
39pub(crate) struct RequestInfoStorage<S> {
40    /// [`RequestKey`] -> [`RequestInfo`].
41    rinfo: HashMap<RequestKey, Arc<RequestInfo>, S>,
42
43    /// [`QueryKey`] -> [`QueryInfo`].
44    qinfo: HashMap<QueryKey, Arc<QueryInfo>, S>,
45
46    /// [`ResQueryKey`] -> [`ResQueryInfo`].
47    rqinfo: HashMap<ResQueryKey, Arc<ResQueryInfo>, S>,
48
49    /// [`EntQueryKey`] -> [`EntQueryInfo`].
50    eqinfo: HashMap<EntQueryKey, Arc<EntQueryInfo>, S>,
51
52    /// [`SelectKey`] -> [`SelectInfo`].
53    sinfo: HashMap<SelectKey, Arc<SelectInfo>, S>,
54
55    /// [`FilterKey`] -> [`FilterInfo`].
56    finfo: HashMap<FilterKey, Arc<FilterInfo>, S>,
57}
58
59impl<S> RequestInfoStorage<S>
60where
61    S: Default,
62{
63    fn new() -> Self {
64        Self {
65            rinfo: HashMap::default(),
66            qinfo: HashMap::default(),
67            rqinfo: HashMap::default(),
68            eqinfo: HashMap::default(),
69            sinfo: HashMap::default(),
70            finfo: HashMap::default(),
71        }
72    }
73}
74
75impl<S> RequestInfoStorage<S>
76where
77    S: BuildHasher,
78{
79    // for future use.
80    #[allow(dead_code)]
81    pub(crate) fn get_request_info(&self, key: &RequestKey) -> Option<&Arc<RequestInfo>> {
82        StoreRequestInfo::get(self, key)
83    }
84
85    // for future use.
86    #[allow(dead_code)]
87    pub(crate) fn get_query_info(&self, key: &QueryKey) -> Option<&Arc<QueryInfo>> {
88        StoreQueryInfo::get(self, key)
89    }
90
91    // for future use.
92    #[allow(dead_code)]
93    pub(crate) fn get_resource_query_info(&self, key: &ResQueryKey) -> Option<&Arc<ResQueryInfo>> {
94        StoreResQueryInfo::get(self, key)
95    }
96
97    // for future use.
98    #[allow(dead_code)]
99    pub(crate) fn get_entity_query_info(&self, key: &EntQueryKey) -> Option<&Arc<EntQueryInfo>> {
100        StoreEntQueryInfo::get(self, key)
101    }
102
103    // for future use.
104    #[allow(dead_code)]
105    pub(crate) fn get_select_info(&self, key: &SelectKey) -> Option<&Arc<SelectInfo>> {
106        StoreSelectInfo::get(self, key)
107    }
108
109    // for future use.
110    #[allow(dead_code)]
111    pub(crate) fn get_filter_info(&self, key: &FilterKey) -> Option<&Arc<FilterInfo>> {
112        StoreFilterInfo::get(self, key)
113    }
114
115    fn remove(&mut self, key: &RequestKey) {
116        // Removes request info if it's not referenced from external anymore.
117        if matches!(self.rinfo.get(key), Some(x) if Arc::strong_count(x) == 1) {
118            // Safety: We checked it in matches.
119            let rinfo = unsafe { self.rinfo.remove(key).unwrap_unchecked() };
120
121            // `RequestInfo` contains other info, so copy keys and drop rinfo first
122            // in order to keep remove code simple.
123            let read_key = rinfo.read().0;
124            let write_key = rinfo.write().0;
125            let res_read_key = rinfo.res_read().0;
126            let res_write_key = rinfo.res_write().0;
127            let ent_write_key = rinfo.ent_write().0;
128            drop(rinfo);
129
130            // Removes read & write query and select info.
131            remove_qinfo_sinfo(self, &read_key);
132            remove_qinfo_sinfo(self, &write_key);
133
134            // Removes read & write resource info.
135            remove_rqinfo(self, &res_read_key);
136            remove_rqinfo(self, &res_write_key);
137
138            // Removes write entity info.
139            remove_eqinfo(self, &ent_write_key);
140        }
141
142        // Removes query and select info if it's not referenced from external anymore.
143        // This function must be called inside `remove()`.
144        fn remove_qinfo_sinfo<S>(this: &mut RequestInfoStorage<S>, key: &QueryKey)
145        where
146            S: BuildHasher,
147        {
148            // `self.qinfo` = 1.
149            const QINFO_EMPTY_STRONG_CNT: usize = 1;
150
151            if matches! (
152                this.qinfo.get(key),
153                Some(x) if Arc::strong_count(x) == QINFO_EMPTY_STRONG_CNT
154            ) {
155                // `QueryInfo` contains `FilterInfo` in it.
156                // We need to remove `FilterInfo` first.
157                // Safety: We checked it in matches.
158                let qinfo = unsafe { this.qinfo.remove(key).unwrap_unchecked() };
159
160                // Removes filter info it's not referenced from external anymore.
161                for (fkey, sinfo) in qinfo.selectors() {
162                    // `sinfo` + `self.sinfo` = 2.
163                    const FINFO_EMPTY_STRONG_CNT: usize = 2;
164
165                    if Arc::strong_count(sinfo) == FINFO_EMPTY_STRONG_CNT {
166                        this.sinfo.remove(fkey);
167                    }
168                }
169            }
170        }
171
172        // Removes resource query info if it's not referenced from external anymore.
173        // This function must be called inside `remove()`.
174        fn remove_rqinfo<S>(this: &mut RequestInfoStorage<S>, key: &ResQueryKey)
175        where
176            S: BuildHasher,
177        {
178            // `self.rqinfo` = 1.
179            const EMPTY_STRONG_CNT: usize = 1;
180
181            if matches! (
182                this.rqinfo.get(key),
183                Some(x) if Arc::strong_count(x) == EMPTY_STRONG_CNT
184            ) {
185                this.rqinfo.remove(key);
186            }
187        }
188
189        // Removes entity query info if it's not referenced from external anymore.
190        // This function must be called inside `remove()`.
191        fn remove_eqinfo<S>(this: &mut RequestInfoStorage<S>, key: &EntQueryKey)
192        where
193            S: BuildHasher,
194        {
195            // `self.eqinfo` = 1.
196            const EMPTY_STRONG_CNT: usize = 1;
197
198            if matches! (
199                this.eqinfo.get(key),
200                Some(x) if Arc::strong_count(x) == EMPTY_STRONG_CNT
201            ) {
202                this.eqinfo.remove(key);
203            }
204        }
205    }
206}
207
208impl<S> Default for RequestInfoStorage<S>
209where
210    S: Default,
211{
212    fn default() -> Self {
213        Self::new()
214    }
215}
216
217impl<S> StoreRequestInfo for RequestInfoStorage<S>
218where
219    S: BuildHasher,
220{
221    fn contains(&self, key: &RequestKey) -> bool {
222        self.rinfo.contains_key(key)
223    }
224
225    fn get(&self, key: &RequestKey) -> Option<&Arc<RequestInfo>> {
226        self.rinfo.get(key)
227    }
228
229    fn insert(&mut self, key: RequestKey, info: Arc<RequestInfo>) {
230        self.rinfo.insert(key, info);
231    }
232
233    // Top level cleaner.
234    fn remove(&mut self, key: &RequestKey) {
235        self.remove(key)
236    }
237}
238
239impl<S> StoreQueryInfo for RequestInfoStorage<S>
240where
241    S: BuildHasher,
242{
243    fn contains(&self, key: &QueryKey) -> bool {
244        self.qinfo.contains_key(key)
245    }
246
247    fn get(&self, key: &QueryKey) -> Option<&Arc<QueryInfo>> {
248        self.qinfo.get(key)
249    }
250
251    fn insert(&mut self, key: QueryKey, info: Arc<QueryInfo>) {
252        self.qinfo.insert(key, info);
253    }
254}
255
256impl<S> StoreResQueryInfo for RequestInfoStorage<S>
257where
258    S: BuildHasher,
259{
260    fn contains(&self, key: &ResQueryKey) -> bool {
261        self.rqinfo.contains_key(key)
262    }
263
264    fn get(&self, key: &ResQueryKey) -> Option<&Arc<ResQueryInfo>> {
265        self.rqinfo.get(key)
266    }
267
268    fn insert(&mut self, key: ResQueryKey, info: Arc<ResQueryInfo>) {
269        self.rqinfo.insert(key, info);
270    }
271}
272
273impl<S> StoreEntQueryInfo for RequestInfoStorage<S>
274where
275    S: BuildHasher,
276{
277    fn contains(&self, key: &EntQueryKey) -> bool {
278        self.eqinfo.contains_key(key)
279    }
280
281    fn get(&self, key: &EntQueryKey) -> Option<&Arc<EntQueryInfo>> {
282        self.eqinfo.get(key)
283    }
284
285    fn insert(&mut self, key: EntQueryKey, info: Arc<EntQueryInfo>) {
286        self.eqinfo.insert(key, info);
287    }
288}
289
290impl<S> StoreSelectInfo for RequestInfoStorage<S>
291where
292    S: BuildHasher,
293{
294    fn contains(&self, key: &SelectKey) -> bool {
295        self.sinfo.contains_key(key)
296    }
297
298    fn get(&self, key: &SelectKey) -> Option<&Arc<SelectInfo>> {
299        self.sinfo.get(key)
300    }
301
302    fn insert(&mut self, key: SelectKey, info: Arc<SelectInfo>) {
303        self.sinfo.insert(key, info);
304    }
305}
306
307impl<S> StoreFilterInfo for RequestInfoStorage<S>
308where
309    S: BuildHasher,
310{
311    fn contains(&self, key: &FilterKey) -> bool {
312        self.finfo.contains_key(key)
313    }
314
315    fn get(&self, key: &FilterKey) -> Option<&Arc<FilterInfo>> {
316        self.finfo.get(key)
317    }
318
319    fn insert(&mut self, key: FilterKey, info: Arc<FilterInfo>) {
320        self.finfo.insert(key, info);
321    }
322}
323
324/// A system request for a components, resources, and entity containers.
325///
326/// All systems must declare their own requests in advance. The crate exploits
327/// the information to avoid data race and dead-lock between systems. A request
328/// consists of read and write requests like so,
329///
330/// * Read - Read request for a set of components.
331/// * Write - Write request for a set of components.
332/// * ResRead - Read request for a set of resources.
333/// * ResWrite - Write request for a set of resources.
334/// * EntWrite - Write request for a set of entity containers.
335#[allow(private_interfaces, private_bounds)]
336pub trait Request: 'static {
337    type Read: Query;
338    type Write: QueryMut;
339    type ResRead: ResQuery;
340    type ResWrite: ResQueryMut;
341    type EntWrite: EntQueryMut;
342
343    #[doc(hidden)]
344    fn key() -> RequestKey {
345        RequestKey::of::<Self>()
346    }
347
348    #[doc(hidden)]
349    fn get_info_from<S>(stor: &mut S) -> &Arc<RequestInfo>
350    where
351        S: StoreRequestInfo + ?Sized,
352    {
353        let key = Self::key();
354
355        if !StoreRequestInfo::contains(stor, &key) {
356            let rinfo = Arc::new(Self::info_from(stor));
357            StoreRequestInfo::insert(stor, key, rinfo);
358        }
359
360        // Safety: Inserted right before.
361        unsafe { StoreRequestInfo::get(stor, &key).unwrap_unchecked() }
362    }
363
364    #[doc(hidden)]
365    fn info_from<S>(stor: &mut S) -> RequestInfo
366    where
367        S: StoreRequestInfo + ?Sized,
368    {
369        // TODO: create new()
370        RequestInfo {
371            name: any::type_name::<Self>(),
372            read: (
373                Self::Read::key(),
374                Arc::clone(Self::Read::get_info_from(stor)),
375            ),
376            write: (
377                Self::Write::key(),
378                Arc::clone(Self::Write::get_info_from(stor)),
379            ),
380            res_read: (
381                Self::ResRead::key(),
382                Arc::clone(Self::ResRead::get_info_from(stor)),
383            ),
384            res_write: (
385                Self::ResWrite::key(),
386                Arc::clone(Self::ResWrite::get_info_from(stor)),
387            ),
388            ent_write: (
389                Self::EntWrite::key(),
390                Arc::clone(Self::EntWrite::get_info_from(stor)),
391            ),
392        }
393    }
394}
395
396/// Blanket implementation of [`Request`] for tuples of queries.
397impl<R, W, RR, RW, EW> Request for (R, W, RR, RW, EW)
398where
399    R: Query,
400    W: QueryMut,
401    RR: ResQuery,
402    RW: ResQueryMut,
403    EW: EntQueryMut,
404{
405    type Read = R;
406    type Write = W;
407    type ResRead = RR;
408    type ResWrite = RW;
409    type EntWrite = EW;
410}
411
412pub(crate) trait StoreRequestInfo:
413    StoreQueryInfo + StoreResQueryInfo + StoreEntQueryInfo
414{
415    fn contains(&self, key: &RequestKey) -> bool;
416    fn get(&self, key: &RequestKey) -> Option<&Arc<RequestInfo>>;
417    fn insert(&mut self, key: RequestKey, info: Arc<RequestInfo>);
418    fn remove(&mut self, key: &RequestKey);
419}
420
421/// Unique identifier for a type implementing [`Request`].
422pub(crate) type RequestKey = ATypeId<RequestKey_>;
423pub(crate) struct RequestKey_;
424
425#[derive(Clone)]
426pub(crate) struct RequestInfo {
427    read: (QueryKey, Arc<QueryInfo>),
428    write: (QueryKey, Arc<QueryInfo>),
429    res_read: (ResQueryKey, Arc<ResQueryInfo>),
430    res_write: (ResQueryKey, Arc<ResQueryInfo>),
431    ent_write: (EntQueryKey, Arc<EntQueryInfo>),
432    name: &'static str,
433}
434
435impl fmt::Debug for RequestInfo {
436    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
437        f.debug_struct("RequestInfo")
438            .field("name", &self.name())
439            .field("read", &self.read())
440            .field("write", &self.write())
441            .field("res_read", &self.res_read())
442            .field("res_write", &self.res_write())
443            .field("ent_write", &self.ent_write())
444            .finish()
445    }
446}
447
448impl RequestInfo {
449    pub(crate) const fn read(&self) -> &(QueryKey, Arc<QueryInfo>) {
450        &self.read
451    }
452
453    pub(crate) const fn write(&self) -> &(QueryKey, Arc<QueryInfo>) {
454        &self.write
455    }
456
457    pub(crate) const fn res_read(&self) -> &(ResQueryKey, Arc<ResQueryInfo>) {
458        &self.res_read
459    }
460
461    pub(crate) const fn res_write(&self) -> &(ResQueryKey, Arc<ResQueryInfo>) {
462        &self.res_write
463    }
464
465    pub(crate) const fn ent_write(&self) -> &(EntQueryKey, Arc<EntQueryInfo>) {
466        &self.ent_write
467    }
468
469    pub(crate) const fn name(&self) -> &'static str {
470        self.name
471    }
472
473    pub(crate) fn resource_keys(&self) -> impl Iterator<Item = &ResourceKey> {
474        let read = self.res_read().1.as_ref();
475        let write = self.res_write().1.as_ref();
476        read.resource_keys().iter().chain(write.resource_keys())
477    }
478
479    pub(crate) fn filters(&self) -> &[(FilterKey, Arc<FilterInfo>)] {
480        self.ent_write().1.as_ref().filters()
481    }
482
483    /// Determines whether the request info is valid or not in terms of
484    /// `Read`, `Write`, `ResRead`, and `ResWrite`.
485    /// Request info that meets conditions below is valid.
486    /// - Write query selectors are disjoint against other selectors.
487    /// - Write resource query doesn't overlap other read or write resource query.
488    ///
489    /// Note that request info cannot validate `EntWrite` itself.
490    /// That must be validated outside.
491    pub(crate) fn validate(&self) -> Result<(), String> {
492        // 1. Write query contains disjoint selectors only?
493        let (_, r_qinfo) = self.read();
494        let (_, w_qinfo) = self.write();
495        let r_sels = r_qinfo.selectors();
496        let w_sels = w_qinfo.selectors();
497        for i in 0..w_sels.len() {
498            // Doesn't overlap other write?
499            for j in i + 1..w_sels.len() {
500                if !w_sels[i].1.is_disjoint(&w_sels[j].1) {
501                    let reason = debug_format!(
502                        "`{}` and `{}` are not disjoint in request `{}`",
503                        w_sels[i].1.name(),
504                        w_sels[j].1.name(),
505                        self.name(),
506                    );
507                    return Err(reason);
508                }
509            }
510            // Doesn't overlap read?
511            for (_, r_sel) in r_sels.iter() {
512                if !w_sels[i].1.is_disjoint(r_sel) {
513                    let reason = debug_format!(
514                        "`{}` and `{}` are not disjoint in request `{}`",
515                        w_sels[i].1.name(),
516                        r_sel.name(),
517                        self.name(),
518                    );
519                    return Err(reason);
520                }
521            }
522        }
523
524        // 2. Write resource query doesn't overlap other resource queries?
525        let (_, r_rqinfo) = self.res_read();
526        let (_, w_rqinfo) = self.res_write();
527        let r_keys = r_rqinfo.resource_keys();
528        let w_keys = w_rqinfo.resource_keys();
529        for i in 0..w_keys.len() {
530            // Doesn't overlap other write?
531            for j in i + 1..w_keys.len() {
532                if w_keys[i] == w_keys[j] {
533                    let reason = debug_format!(
534                        "duplicate resource query `{:?}` in request `{}`",
535                        w_keys[i],
536                        self.name(),
537                    );
538                    return Err(reason);
539                }
540            }
541            // Doesn't overlap read?
542            for r_key in r_keys.iter() {
543                if &w_keys[i] == r_key {
544                    let reason = debug_format!(
545                        "duplicate resource query `{:?}` in request `{}`",
546                        w_keys[i],
547                        self.name(),
548                    );
549                    return Err(reason);
550                }
551            }
552        }
553
554        Ok(())
555    }
556}
557
558/// Empty request.
559impl Request for () {
560    type Read = ();
561    type Write = ();
562    type ResRead = ();
563    type ResWrite = ();
564    type EntWrite = ();
565}
566
567/// System buffer for its request.
568///
569/// System request, [`Request`], is composed of requests for read, write,
570/// resource read, resource write, and entity write. They are actually pointers
571/// to the requesting data. Each request means,
572/// - Read or write: Read or write requests for specific
573///   [`Component`](crate::ecs::ent::component::Component)s.
574/// - Resource read or write: Read or write requests for specific
575///   [`Resource`](crate::ecs::resource::Resource)s.
576/// - Entity write: Write requests for specific entity containers.
577//
578// Why buffer for system rather than request?
579// Q. Many systems may have the same request, so is they be able to share the
580//    same buffer?
581// A. Because of borrow check, we need system-individual buffer.
582// - We check borrow status, so we need to borrow and release data everytime.
583//   * Borrow check helps us avoid running into hidden data race during
584//     development.
585#[derive(Debug)]
586pub struct SystemBuffer {
587    /// Buffer for read-only borrowed component arrays for the system's request.
588    pub(crate) read: Box<[SelectedRaw]>,
589
590    /// Buffer for writable borrowed component arrays for the system's request.
591    pub(crate) write: Box<[SelectedRaw]>,
592
593    /// Buffer for read-only borrowed resources for the system's request.
594    pub(crate) res_read: Vec<Borrowed<ManagedConstPtr<u8>>>,
595
596    /// Buffer for writable borrowed resources for the system's request.
597    pub(crate) res_write: Vec<Borrowed<ManagedMutPtr<u8>>>,
598
599    /// Buffer for writable borrowed entity container for the system's request.
600    pub(crate) ent_write: Box<[FilteredRaw]>,
601}
602
603// We're going to send this buffer to other threads with a system implementation.
604// So it's needed to be `Send` like `dyn Invoke + Send`.
605// Obviously, it includes raw pointers, which are unsafe to be sent.
606// But scheduler guarantees there will be no violation.
607unsafe impl Send for SystemBuffer {}
608
609impl SystemBuffer {
610    pub(crate) fn new() -> Self {
611        Self {
612            read: [].into(),
613            write: [].into(),
614            res_read: Vec::new(),
615            res_write: Vec::new(),
616            ent_write: [].into(),
617        }
618    }
619
620    pub(crate) fn clear(&mut self) {
621        #[cfg(feature = "check")]
622        self.clear_force();
623    }
624
625    pub(crate) fn clear_force(&mut self) {
626        for read in self.read.iter_mut() {
627            read.clear();
628        }
629        for write in self.write.iter_mut() {
630            write.clear();
631        }
632        self.res_read.clear();
633        self.res_write.clear();
634        for ent_write in self.ent_write.iter_mut() {
635            ent_write.clear();
636        }
637    }
638}
639
640impl Default for SystemBuffer {
641    fn default() -> Self {
642        Self::new()
643    }
644}
645
646/// A response corresponding to a [`Request`].
647pub struct Response<'buf, Req: Request> {
648    pub read: <Req::Read as Query>::Output<'buf>,
649    pub write: <Req::Write as QueryMut>::Output<'buf>,
650    pub res_read: <Req::ResRead as ResQuery>::Output<'buf>,
651    pub res_write: <Req::ResWrite as ResQueryMut>::Output<'buf>,
652    pub ent_write: <Req::EntWrite as EntQueryMut>::Output<'buf>,
653    _cleaner: BufferCleaner<'buf>,
654}
655
656impl<'buf, Req: Request> Response<'buf, Req> {
657    pub(crate) fn new(buf: &'buf mut SystemBuffer) -> Self {
658        // Safety: Infallible.
659        let _cleaner = BufferCleaner {
660            buf_ptr: unsafe { NonNull::new_unchecked(buf as *mut _) },
661            _marker: PhantomData,
662        };
663
664        Self {
665            read: <Req::Read as Query>::convert(&mut buf.read),
666            write: <Req::Write as QueryMut>::convert(&mut buf.write),
667            res_read: <Req::ResRead as ResQuery>::convert(&mut buf.res_read),
668            res_write: <Req::ResWrite as ResQueryMut>::convert(&mut buf.res_write),
669            ent_write: <Req::EntWrite as EntQueryMut>::convert(&mut buf.ent_write),
670            _cleaner,
671        }
672    }
673}
674
675struct BufferCleaner<'buf> {
676    buf_ptr: NonNull<SystemBuffer>,
677    _marker: PhantomData<&'buf ()>,
678}
679
680impl Drop for BufferCleaner<'_> {
681    fn drop(&mut self) {
682        // Safety: We're actually borrowing `SystemBuffer` via `buf lifetime.
683        let buf = unsafe { self.buf_ptr.as_mut() };
684        buf.clear();
685    }
686}