async_ecs/storage/mod.rs
1mod anti_storage;
2mod btree_storage;
3mod dense_vec_storage;
4mod drain;
5mod hash_map_storage;
6mod masked_storage;
7mod storage_wrapper;
8mod vec_storage;
9
10pub use anti_storage::AntiStorage;
11pub use btree_storage::BTreeStorage;
12pub use dense_vec_storage::DenseVecStorage;
13pub use drain::Drain;
14pub use hash_map_storage::HashMapStorage;
15pub use masked_storage::MaskedStorage;
16pub use storage_wrapper::StorageWrapper;
17pub use vec_storage::VecStorage;
18
19use hibitset::BitSetLike;
20
21use crate::{entity::Index, misc::TryDefault};
22
23/// Used by the framework to quickly join components.
24pub trait Storage<T>: TryDefault {
25 /// Tries reading the data associated with an `Index`.
26 /// This is unsafe because the external set used
27 /// to protect this storage is absent.
28 ///
29 /// # Safety
30 ///
31 /// May only be called after a call to `insert` with `id` and
32 /// no following call to `remove` with `id`.
33 ///
34 /// A mask should keep track of those states, and an `id` being contained
35 /// in the tracking mask is sufficient to call this method.
36 unsafe fn get(&self, index: Index) -> &T;
37
38 /// Tries mutating the data associated with an `Index`.
39 /// This is unsafe because the external set used
40 /// to protect this storage is absent.
41 ///
42 /// # Safety
43 ///
44 /// May only be called after a call to `insert` with `id` and
45 /// no following call to `remove` with `id`.
46 ///
47 /// A mask should keep track of those states, and an `id` being contained
48 /// in the tracking mask is sufficient to call this method.
49 unsafe fn get_mut(&mut self, index: Index) -> &mut T;
50
51 /// Inserts new data for a given `Index`.
52 ///
53 /// # Safety
54 ///
55 /// May only be called if `insert` was not called with `id` before, or
56 /// was reverted by a call to `remove` with `id.
57 ///
58 /// A mask should keep track of those states, and an `id` missing from the
59 /// mask is sufficient to call `insert`.
60 unsafe fn insert(&mut self, index: Index, value: T);
61
62 /// Removes the data associated with an `Index`.
63 ///
64 /// # Safety
65 ///
66 /// May only be called if an element with `id` was `insert`ed and not yet
67 /// removed / dropped.
68 unsafe fn remove(&mut self, index: Index) -> T;
69
70 /// Clean the storage given a bitset with bits set for valid indices.
71 /// Allows us to safely drop the storage.
72 ///
73 /// # Safety
74 ///
75 /// May only be called with the mask which keeps track of the elements
76 /// existing in this storage.
77 unsafe fn clean<B>(&mut self, has: B)
78 where
79 B: BitSetLike;
80
81 /// Drops the data associated with an `Index`.
82 /// This could be used when a more efficient implementation for it exists than `remove` when the data
83 /// is no longer needed.
84 /// Defaults to simply calling `remove`.
85 ///
86 /// # Safety
87 ///
88 /// May only be called if an element with `id` was `insert`ed and not yet
89 /// removed / dropped.
90 unsafe fn drop(&mut self, index: Index) {
91 self.remove(index);
92 }
93}
94
95/// This is a marker trait which requires you to uphold the following guarantee:
96///
97/// > Multiple threads may call `get_mut()` with distinct indices without
98/// causing > undefined behavior.
99///
100/// This is for example valid for `Vec`:
101///
102/// ```rust
103/// vec![1, 2, 3];
104/// ```
105///
106/// We may modify both element 1 and 2 at the same time; indexing the vector
107/// mutably does not modify anything else than the respective elements.
108///
109/// As a counter example, we may have some kind of cached storage; it caches
110/// elements when they're retrieved, so pushes a new element to some
111/// cache-vector. This storage is not allowed to implement `DistinctStorage`.
112///
113/// Implementing this trait marks the storage safe for concurrent mutation (of
114/// distinct elements), thus allows `join_par()`.
115pub trait DistinctStorage {}