Skip to main content

ConceptModelRegistry.ixx File

Generic type-indexed registry for type-erased wrappers. More...

Included Headers

#include <cassert> #include <memory> #include <span> #include <vector> #include <helios.engine.common.concepts>

Namespaces Index

namespacehelios
namespacecore

Core utilities shared across the helios engine. More...

namespacecontainer

Generic container types shared across the engine. More...

Classes Index

classConceptModelRegistry<AnyT, IdProvider>

Generic type-indexed registry for type-erased wrapper instances. More...

Description

Generic type-indexed registry for type-erased wrappers.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file ConceptModelRegistry.ixx
3 * @brief Generic type-indexed registry for type-erased wrappers.
4 */
5module;
6
7#include <cassert>
8#include <memory>
9#include <span>
10#include <vector>
11
12
13export module helios.core.container.ConceptModelRegistry;
14
15import helios.engine.common.concepts;
16
18
19export namespace helios::core::container {
20
21 /**
22 * @brief Generic type-indexed registry for type-erased wrapper instances.
23 *
24 * @details ConceptModelRegistry stores instances of a type-erased wrapper
25 * `AnyT` (e.g. System, Manager) and indexes them by a compile-time
26 * `IdProvider` (e.g. SystemTypeId, ResourceTypeId). This provides:
27 *
28 * - **O(1) lookup** by concrete type via `item<T>()`
29 * - **Insertion-order iteration** via `items()` for deterministic processing
30 * - **Type-safe registration** via `add<T>(args...)` returning a reference
31 * to the underlying concrete instance
32 *
33 * The registry is used as the backend for `SystemRegistry` and
34 * `ManagerRegistry`.
35 *
36 * ## Instantiations
37 *
38 * | Alias | AnyT | IdProvider |
39 * |-------|------|------------|
40 * | `SystemRegistry` | `System` | `SystemTypeId` |
41 * | `ManagerRegistry` | `Manager` | `ResourceTypeId` |
42 *
43 * @tparam AnyT The type-erased wrapper type (must support `underlying()`).
44 * @tparam IdProvider Compile-time ID generator (must provide `id<T>().value()`).
45 *
46 * @see SystemRegistry
47 * @see ManagerRegistry
48 *
49 * @todo this impl needs to make sure that memory allocations / moves do not invalidate
50 * the fastAccess in ResourceRegistry
51 */
52 template<typename AnyT, typename IdProvider>
54
55 /**
56 * @brief Owning storage for wrapped AnyT instances, indexed by type ID.
57 */
58 mutable std::vector<AnyT> items_;
59
60 /**
61 * @brief Cached raw pointers to the underlying concrete instances.
62 */
63 std::vector<void*> underlyingAnyT_;
64
65 /**
66 * @brief Records insertion order for deterministic iteration.
67 */
68 std::vector<size_t> insertionOrder_;
69
70 /**
71 * @brief Lazily-built view of AnyT pointers in insertion order.
72 */
73 mutable std::vector<AnyT*> itemView_;
74
75 /**
76 * @brief Dirty flag indicating itemView_ needs rebuilding.
77 */
78 mutable bool needsUpdate_ = false;
79
80 /**
81 * @brief Rebuilds the insertion-ordered view if dirty.
82 */
83 void update() const {
84
85 if (!needsUpdate_) {
86 return;
87 }
88
89 itemView_.clear();
90 itemView_.reserve(insertionOrder_.size());
91
92 for (const auto insertionIndex : insertionOrder_) {
93 itemView_.push_back(const_cast<AnyT*>(&items_[insertionIndex]));
94 }
95
96 needsUpdate_ = false;
97
98 }
99
100
101 public:
102
103 /**
104 * @brief Returns a read-only span of registered items in insertion order.
105 *
106 * @return Span of const AnyT pointers.
107 */
108 [[nodiscard]] std::span<AnyT* const> items() const noexcept {
109 update();
110 return itemView_;
111 }
112
113 /**
114 * @brief Returns a mutable span of registered items in insertion order.
115 *
116 * @return Span of AnyT pointers.
117 */
118 [[nodiscard]] std::span<AnyT*> items() noexcept {
119 update();
120 return itemView_;
121 }
122
123
124 /**
125 * @brief Registers and wraps a concrete instance of type T.
126 *
127 * @details Constructs T in-place from the forwarded arguments, wraps it
128 * in an AnyT, and stores it at the index determined by `IdProvider::id<T>()`.
129 * Returns a reference to the underlying concrete T instance.
130 *
131 * @tparam T The concrete type to register.
132 * @tparam Args Constructor argument types for T.
133 *
134 * @param args Arguments forwarded to the T constructor.
135 *
136 * @return Reference to the registered T instance.
137 *
138 * @pre T must not already be registered.
139 */
140 template<typename T, typename... Args>
141 T& add(Args&&... args) {
142
143 assert(!has<T>() && "AnyT already registered with GameLoopPhase");
144
145 AnyT wrapper{T{std::forward<Args>(args)...}};
146
147 const auto idx = IdProvider::template id<T>().value();
148
149 if (items_.size() <= idx) {
150 items_.resize(idx + 1);
151 }
152 if (underlyingAnyT_.size() <= idx) {
153 underlyingAnyT_.resize(idx + 1);
154 }
155
156 items_[idx] = std::move(wrapper);
157 void* rawUnderlying = items_[idx].underlying();
158 underlyingAnyT_[idx] = rawUnderlying;
159
160
161 insertionOrder_.push_back(idx);
162
163 needsUpdate_ = true;
164 return *static_cast<T*>(rawUnderlying);
165 }
166
167
168 /**
169 * @brief Checks whether a concrete type T is registered.
170 *
171 * @tparam T The type to check.
172 *
173 * @return True if T has been added.
174 */
175 template<typename T>
176 [[nodiscard]] bool has() const {
177 return item<T>() != nullptr;
178 }
179
180 /**
181 * @brief Returns a pointer to the registered instance of type T.
182 *
183 * @tparam T The concrete type to look up.
184 *
185 * @return Pointer to T, or nullptr if not registered.
186 */
187 template<typename T>
188 [[nodiscard]] T* item() const {
189
190 const auto idx = IdProvider::template id<T>().value();
191 if (items_.size() <= idx || underlyingAnyT_.size() <= idx) {
192 return nullptr;
193 }
194
195 return underlyingAnyT_[idx] ? static_cast<T*>(underlyingAnyT_[idx]) : nullptr;
196 }
197
198 };
199
200
201}
202

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.