@@ -125,61 +125,20 @@ void register_lifecycle_actions(
125
125
// will register it as a component, and verify whether the input is consistent.
126
126
template <typename T>
127
127
struct cpp_type_impl {
128
- // Initialize component identifier
129
- static void init (
130
- entity_t entity,
131
- bool allow_tag = true )
132
- {
133
- if (s_reset_count != ecs_cpp_reset_count_get ()) {
134
- reset ();
135
- }
136
-
137
- // If an identifier was already set, check for consistency
138
- if (s_id) {
139
- ecs_assert (s_id == entity, ECS_INCONSISTENT_COMPONENT_ID,
140
- type_name<T>());
141
- ecs_assert (allow_tag == s_allow_tag, ECS_INVALID_PARAMETER, NULL );
142
-
143
- // Component was already registered and data is consistent with new
144
- // identifier, so nothing else to be done.
145
- return ;
146
- }
147
-
148
- // Component wasn't registered yet, set the values. Register component
149
- // name as the fully qualified flecs path.
150
- s_id = entity;
151
- s_allow_tag = allow_tag;
152
- s_size = sizeof (T);
153
- s_alignment = alignof (T);
154
- if (is_empty<T>::value && allow_tag) {
155
- s_size = 0 ;
156
- s_alignment = 0 ;
157
- }
158
-
159
- s_reset_count = ecs_cpp_reset_count_get ();
160
- }
161
-
162
128
// Obtain a component identifier for explicit component registration.
163
- static entity_t id_explicit (world_t *world = nullptr ,
129
+ static entity_t id_explicit (world_t *world,
164
130
const char *name = nullptr , bool allow_tag = true , flecs::id_t id = 0 ,
165
131
bool is_component = true , bool *existing = nullptr )
166
132
{
167
- if (!s_id) {
168
- // If no world was provided the component cannot be registered
169
- ecs_assert (world != nullptr , ECS_COMPONENT_NOT_REGISTERED, name);
170
- } else {
171
- ecs_assert (!id || s_id == id, ECS_INCONSISTENT_COMPONENT_ID, NULL );
172
- }
173
-
174
- // If no id has been registered yet for the component (indicating the
175
- // component has not yet been registered, or the component is used
176
- // across more than one binary), or if the id does not exists in the
177
- // world (indicating a multi-world application), register it. */
178
- if (!s_id || (world && !ecs_exists (world, s_id))) {
179
- init (s_id ? s_id : id, allow_tag);
180
-
181
- ecs_assert (!id || s_id == id, ECS_INTERNAL_ERROR, NULL );
133
+ ecs_assert (world != nullptr , ECS_INTERNAL_ERROR, name);
182
134
135
+ if (const ecs_cached_component_info_t * info = ecs_lookup_cached_component_info (world, index )) {
136
+ return info->component ;
137
+ } else {
138
+ // If no id has been registered yet for the component (indicating the
139
+ // component has not yet been registered), or if the id does not
140
+ // exists in the world (indicating a multi-world application),
141
+ // register it. */
183
142
const char *symbol = nullptr ;
184
143
if (id) {
185
144
symbol = ecs_get_symbol (world, id);
@@ -188,23 +147,37 @@ struct cpp_type_impl {
188
147
symbol = symbol_name<T>();
189
148
}
190
149
191
- entity_t entity = ecs_cpp_component_register_explicit (
192
- world, s_id, id, name, type_name<T>(), symbol,
193
- s_size, s_alignment, is_component, existing);
150
+ const bool is_tag = is_empty<T>::value && allow_tag;
151
+
152
+ const size_t component_size = is_tag ? 0U : size ();
153
+ const size_t component_alignment = is_tag ? 0U : alignment ();
154
+
155
+ const entity_t entity = ecs_cpp_component_register_explicit (
156
+ world, 0 , id, name, type_name<T>(), symbol,
157
+ component_size, component_alignment, is_component, existing);
158
+
159
+ // Component wasn't registered yet, set the values. Register component
160
+ // name as the fully qualified flecs path.
161
+ ecs_cached_component_info_t * inserted =
162
+ ecs_get_or_create_cached_component_info (world, index );
194
163
195
- s_id = entity;
164
+ ecs_assert (!!inserted, ECS_INTERNAL_ERROR, NULL );
165
+ ecs_assert (!ecs_is_cached_component_info_valid (inserted), ECS_INTERNAL_ERROR,
166
+ NULL );
167
+
168
+ inserted->component = entity;
169
+ inserted->size = static_cast <ecs_size_t >(component_size);
170
+ inserted->alignment = static_cast <ecs_size_t >(component_alignment);
171
+
172
+ ecs_assert (ecs_is_cached_component_info_valid (inserted), ECS_INTERNAL_ERROR, NULL );
196
173
197
174
// If component is enum type, register constants
198
175
#if FLECS_CPP_ENUM_REFLECTION_SUPPORT
199
176
_::init_enum<T>(world, entity);
200
177
#endif
201
- }
202
178
203
- // By now the identifier must be valid and known with the world.
204
- ecs_assert (s_id != 0 && ecs_exists (world, s_id),
205
- ECS_INTERNAL_ERROR, NULL );
206
-
207
- return s_id;
179
+ return entity;
180
+ }
208
181
}
209
182
210
183
// Obtain a component identifier for implicit component registration. This
@@ -213,29 +186,28 @@ struct cpp_type_impl {
213
186
// Additionally, implicit registration temporarily resets the scope & with
214
187
// state of the world, so that the component is not implicitly created with
215
188
// the scope/with of the code it happens to be first used by.
216
- static id_t id (world_t *world = nullptr , const char *name = nullptr ,
189
+ static id_t id (world_t *world, const char *name = nullptr ,
217
190
bool allow_tag = true )
218
191
{
219
- // If no id has been registered yet, do it now.
220
- if (!registered (world)) {
221
- ecs_entity_t prev_scope = 0 ;
222
- ecs_id_t prev_with = 0 ;
223
-
224
- if (world) {
225
- prev_scope = ecs_set_scope (world, 0 );
226
- prev_with = ecs_set_with (world, 0 );
227
- }
192
+ ecs_assert (world != nullptr , ECS_INTERNAL_ERROR, name);
193
+
194
+ if (const ecs_cached_component_info_t * info = ecs_lookup_cached_component_info (world, index )) {
195
+ return info->component ;
196
+ } else {
197
+ // If no id has been registered yet, do it now.
198
+ const ecs_entity_t prev_scope = ecs_set_scope (world, 0 );
199
+ const ecs_id_t prev_with = ecs_set_with (world, 0 );
228
200
229
201
// This will register a component id, but will not register
230
202
// lifecycle callbacks.
231
203
bool existing;
232
- id_explicit (world, name, allow_tag, 0 , true , &existing);
204
+ const entity_t id = id_explicit (world, name, allow_tag, 0 , true , &existing);
233
205
234
206
// Register lifecycle callbacks, but only if the component has a
235
207
// size. Components that don't have a size are tags, and tags don't
236
208
// require construction/destruction/copy/move's. */
237
209
if (size () && !existing) {
238
- register_lifecycle_actions<T>(world, s_id );
210
+ register_lifecycle_actions<T>(world, id );
239
211
}
240
212
241
213
if (prev_with) {
@@ -244,62 +216,41 @@ struct cpp_type_impl {
244
216
if (prev_scope) {
245
217
ecs_set_scope (world, prev_scope);
246
218
}
247
- }
248
-
249
- // By now we should have a valid identifier
250
- ecs_assert (s_id != 0 , ECS_INTERNAL_ERROR, NULL );
251
219
252
- return s_id;
220
+ return id;
221
+ }
253
222
}
254
223
255
- // Return the size of a component.
256
- static size_t size () {
257
- ecs_assert (s_id != 0 , ECS_INTERNAL_ERROR, NULL );
258
- return s_size;
224
+ // / Looks the assigned component up in the provided world.
225
+ // / It can happen that the component has not been initialized yet.
226
+ static entity_t lookup (const world_t * world) {
227
+ const ecs_cached_component_info_t * info = ecs_lookup_cached_component_info (world, index );
228
+ return info ? info->component : 0 ;
259
229
}
260
230
261
- // Return the alignment of a component.
262
- static size_t alignment () {
263
- ecs_assert (s_id != 0 , ECS_INTERNAL_ERROR, NULL );
264
- return s_alignment;
231
+ // Was the component already registered.
232
+ static bool registered (const world_t * world) {
233
+ return !!lookup (world);
265
234
}
266
235
267
- // Was the component already registered.
268
- static bool registered (flecs::world_t *world) {
269
- if (s_reset_count != ecs_cpp_reset_count_get ()) {
270
- reset ();
271
- }
272
- if (s_id == 0 ) {
273
- return false ;
274
- }
275
- if (world && !ecs_exists (world, s_id)) {
276
- return false ;
277
- }
278
- return true ;
236
+ // Return the size of this component.
237
+ static size_t size () {
238
+ return sizeof (T);
279
239
}
280
240
281
- // This function is only used to test cross-translation unit features. No
282
- // code other than test cases should invoke this function.
283
- static void reset () {
284
- s_id = 0 ;
285
- s_size = 0 ;
286
- s_alignment = 0 ;
287
- s_allow_tag = true ;
241
+ // Return the alignment of this component.
242
+ static size_t alignment () {
243
+ return alignof (T);
288
244
}
289
245
290
- static entity_t s_id;
291
- static size_t s_size;
292
- static size_t s_alignment;
293
- static bool s_allow_tag;
294
- static int32_t s_reset_count;
246
+ // Acquire a per instance incremental index for a world-local component id cache.
247
+ static ecs_component_cache_index_t index;
295
248
};
296
249
297
250
// Global templated variables that hold component identifier and other info
298
- template <typename T> entity_t cpp_type_impl<T>::s_id;
299
- template <typename T> size_t cpp_type_impl<T>::s_size;
300
- template <typename T> size_t cpp_type_impl<T>::s_alignment;
301
- template <typename T> bool cpp_type_impl<T>::s_allow_tag( true );
302
- template <typename T> int32_t cpp_type_impl<T>::s_reset_count;
251
+ template <typename T>
252
+ ecs_component_cache_index_t cpp_type_impl<T>::index{
253
+ ecs_cpp_component_id_storage_add ()};
303
254
304
255
// Front facing class for implicitly registering a component & obtaining
305
256
// static component data
@@ -375,10 +326,9 @@ struct component : untyped_component {
375
326
implicit_name = true ;
376
327
}
377
328
378
- if (_::cpp_type<T>::registered (world)) {
379
- /* Obtain component id. Because the component is already registered,
380
- * this operation does nothing besides returning the existing id */
381
- id = _::cpp_type<T>::id_explicit (world, name, allow_tag, id);
329
+ /* Obtain a registered component id. */
330
+ if (const entity_t registered = _::cpp_type<T>::lookup (world)) {
331
+ id = registered;
382
332
383
333
ecs_cpp_component_validate (world, id, n, _::symbol_name<T>(),
384
334
_::cpp_type<T>::size (),
@@ -504,17 +454,6 @@ struct component : untyped_component {
504
454
}
505
455
};
506
456
507
- /* * Get id currently assigned to component. If no world has registered the
508
- * component yet, this operation will return 0. */
509
- template <typename T>
510
- flecs::entity_t type_id () {
511
- if (_::cpp_type<T>::s_reset_count == ecs_cpp_reset_count_get ()) {
512
- return _::cpp_type<T>::s_id;
513
- } else {
514
- return 0 ;
515
- }
516
- }
517
-
518
457
/* * Reset static component ids.
519
458
* When components are registered their component ids are stored in a static
520
459
* type specific variable. This stored id is passed into component registration
@@ -537,9 +476,9 @@ flecs::entity_t type_id() {
537
476
*
538
477
* \ingroup cpp_components
539
478
*/
540
- inline void reset () {
541
- ecs_cpp_reset_count_inc ();
542
- }
479
+ ECS_DEPRECATED ( " ecs_cpp_reset_count_inc was deprecated, world-local component "
480
+ " ids made it obsolete " )
481
+ inline void reset () { }
543
482
544
483
}
545
484
0 commit comments