From 4339065a13a06a606892a5144e462c1a967538eb Mon Sep 17 00:00:00 2001 From: Javier Peletier Date: Tue, 19 Nov 2024 00:15:13 +0100 Subject: [PATCH] Refactor illegal checks to flags --- distr/flecs.c | 467 +++++++++--------- distr/flecs.h | 153 +++--- include/flecs.h | 60 +-- include/flecs/addons/cpp/component.hpp | 20 +- include/flecs/addons/cpp/lifecycle_traits.hpp | 73 +-- src/addons/meta/rtt_lifecycle.c | 200 +++----- src/entity.c | 117 ----- src/world.c | 150 +++++- test/meta/src/RuntimeTypes.c | 112 ++--- 9 files changed, 625 insertions(+), 727 deletions(-) diff --git a/distr/flecs.c b/distr/flecs.c index c388bbf8f..518444637 100644 --- a/distr/flecs.c +++ b/distr/flecs.c @@ -10338,123 +10338,6 @@ bool flecs_defer_purge( return false; } -/* Define noreturn attribute only for GCC or Clang. - * Certain builds in Windows require this for functions that abort - * (-Wmissing-noreturn) -*/ -#if defined(__GNUC__) || defined(__clang__) - #define NORETURN __attribute__((noreturn)) -#else - #define NORETURN -#endif - -NORETURN -static -void ecs_ctor_illegal( - void * dst, - int32_t count, - const ecs_type_info_t *ti) { - (void)dst; /* silence unused warning */ - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid constructor for %s", ti->name); -} - -ecs_xtor_t ecs_ctor_illegal_(void) -{ - return ecs_ctor_illegal; -} - -NORETURN -static -void ecs_dtor_illegal( - void *dst, - int32_t count, - const ecs_type_info_t *ti) { - (void)dst; /* silence unused warning */ - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid destructor for %s", ti->name); -} - -ecs_xtor_t ecs_dtor_illegal_(void) -{ - return ecs_dtor_illegal; -} - -NORETURN -static -void ecs_copy_illegal( - void *dst, - const void *src, - int32_t count, - const ecs_type_info_t *ti) -{ - (void)dst; /* silence unused warning */ - (void)src; - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid copy assignment for %s", ti->name); -} - -ecs_copy_t ecs_copy_illegal_(void) -{ - return ecs_copy_illegal; -} - -NORETURN -static -void ecs_move_illegal( - void * dst, - void * src, - int32_t count, - const ecs_type_info_t *ti) { - (void)dst; /* silence unused warning */ - (void)src; - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid move assignment for %s", ti->name); -} - -ecs_move_t ecs_move_illegal_(void) -{ - return ecs_move_illegal; -} - -NORETURN -static -void ecs_copy_ctor_illegal( - void *dst, - const void *src, - int32_t count, - const ecs_type_info_t *ti) -{ - (void)dst; /* silence unused warning */ - (void)src; - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid copy construct for %s", ti->name); -} - -ecs_copy_t ecs_copy_ctor_illegal_(void) -{ - return ecs_copy_ctor_illegal; -} - -NORETURN -static -void ecs_move_ctor_illegal( - void *dst, - void *src, - int32_t count, - const ecs_type_info_t *ti) -{ - (void)dst; /* silence unused warning */ - (void)src; - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid move construct for %s", ti->name); -} - -ecs_move_t ecs_move_ctor_illegal_(void) -{ - return ecs_move_ctor_illegal; -} - /** * @file entity_name.c * @brief Functions for working with named entities. @@ -19039,6 +18922,94 @@ void flecs_default_move_w_dtor(void *dst_ptr, void *src_ptr, cl->dtor(src_ptr, count, ti); } +/* Define noreturn attribute only for GCC or Clang. + * Certain builds in Windows require this for functions that abort + * (-Wmissing-noreturn) +*/ +#if defined(__GNUC__) || defined(__clang__) + #define NORETURN __attribute__((noreturn)) +#else + #define NORETURN +#endif + +NORETURN +static +void ecs_ctor_illegal( + void * dst, + int32_t count, + const ecs_type_info_t *ti) { + (void)dst; /* silence unused warning */ + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid constructor for %s", ti->name); +} + +NORETURN +static +void ecs_dtor_illegal( + void *dst, + int32_t count, + const ecs_type_info_t *ti) { + (void)dst; /* silence unused warning */ + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid destructor for %s", ti->name); +} + +NORETURN +static +void ecs_copy_illegal( + void *dst, + const void *src, + int32_t count, + const ecs_type_info_t *ti) +{ + (void)dst; /* silence unused warning */ + (void)src; + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid copy assignment for %s", ti->name); +} + +NORETURN +static +void ecs_move_illegal( + void * dst, + void * src, + int32_t count, + const ecs_type_info_t *ti) { + (void)dst; /* silence unused warning */ + (void)src; + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid move assignment for %s", ti->name); +} + +NORETURN +static +void ecs_copy_ctor_illegal( + void *dst, + const void *src, + int32_t count, + const ecs_type_info_t *ti) +{ + (void)dst; /* silence unused warning */ + (void)src; + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid copy construct for %s", ti->name); +} + +NORETURN +static +void ecs_move_ctor_illegal( + void *dst, + void *src, + int32_t count, + const ecs_type_info_t *ti) +{ + (void)dst; /* silence unused warning */ + (void)src; + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid move construct for %s", ti->name); +} + + void ecs_set_hooks_id( ecs_world_t *world, ecs_entity_t component, @@ -19074,6 +19045,7 @@ void ecs_set_hooks_id( ti->alignment = component_ptr->alignment; } + ti->hooks.flags = h->flags; if (h->ctor) ti->hooks.ctor = h->ctor; if (h->dtor) ti->hooks.dtor = h->dtor; if (h->copy) ti->hooks.copy = h->copy; @@ -19103,35 +19075,42 @@ void ecs_set_hooks_id( } /* Set default copy ctor, move ctor and merge */ + ecs_type_hooks_flags_t flags = h->flags; if (!h->copy_ctor) { - if(h->copy == ECS_COPY_ILLEGAL || h->ctor == ECS_CTOR_ILLEGAL) { - ti->hooks.copy_ctor = ECS_COPY_CTOR_ILLEGAL; + if(flags & ECS_COPY_ILLEGAL || flags & ECS_CTOR_ILLEGAL) { + flags |= ECS_COPY_CTOR_ILLEGAL; } else if(h->copy) { ti->hooks.copy_ctor = flecs_default_copy_ctor; } } if (!h->move_ctor) { - if(h->move == ECS_MOVE_ILLEGAL || h->ctor == ECS_CTOR_ILLEGAL) { - ti->hooks.move_ctor = ECS_MOVE_CTOR_ILLEGAL; + if(flags & ECS_MOVE_ILLEGAL || flags & ECS_CTOR_ILLEGAL) { + flags |= ECS_MOVE_CTOR_ILLEGAL; } else if (h->move) { ti->hooks.move_ctor = flecs_default_move_ctor; } } if (!h->ctor_move_dtor) { + ecs_type_hooks_flags_t illegal_check = 0; if (h->move) { + illegal_check |= ECS_MOVE_ILLEGAL; if (h->dtor) { + illegal_check |= ECS_DTOR_ILLEGAL; if (h->move_ctor) { + illegal_check |= ECS_MOVE_CTOR_ILLEGAL; /* If an explicit move ctor has been set, use callback * that uses the move ctor vs. using a ctor+move */ ti->hooks.ctor_move_dtor = flecs_default_move_ctor_w_dtor; } else { + illegal_check |= ECS_CTOR_ILLEGAL; /* If no explicit move_ctor has been set, use * combination of ctor + move + dtor */ ti->hooks.ctor_move_dtor = flecs_default_ctor_w_move_w_dtor; } } else { + illegal_check |= ECS_MOVE_CTOR_ILLEGAL; /* If no dtor has been set, this is just a move ctor */ ti->hooks.ctor_move_dtor = ti->hooks.move_ctor; } @@ -19139,29 +19118,75 @@ void ecs_set_hooks_id( /* If move is not set but move_ctor and dtor is, we can still set * ctor_move_dtor. */ if (h->move_ctor) { + illegal_check |= ECS_MOVE_CTOR_ILLEGAL; if (h->dtor) { + illegal_check |= ECS_DTOR_ILLEGAL; ti->hooks.ctor_move_dtor = flecs_default_move_ctor_w_dtor; } else { ti->hooks.ctor_move_dtor = ti->hooks.move_ctor; } } } + if(flags & illegal_check) { + flags |= ECS_CTOR_MOVE_DTOR_ILLEGAL; + } } if (!h->move_dtor) { + ecs_type_hooks_flags_t illegal_check = 0; if (h->move) { + illegal_check |= ECS_MOVE_ILLEGAL; if (h->dtor) { + illegal_check |= ECS_DTOR_ILLEGAL; ti->hooks.move_dtor = flecs_default_move_w_dtor; } else { ti->hooks.move_dtor = flecs_default_move; } } else { if (h->dtor) { + illegal_check |= ECS_DTOR_ILLEGAL; ti->hooks.move_dtor = flecs_default_dtor; } } + if(flags & illegal_check) { + flags |= ECS_MOVE_DTOR_ILLEGAL; + } + } + + if(flags & ECS_CTOR_ILLEGAL) { + ti->hooks.ctor = ecs_ctor_illegal; + } + + if(flags & ECS_DTOR_ILLEGAL) { + ti->hooks.dtor = ecs_dtor_illegal; + } + + if(flags & ECS_COPY_ILLEGAL) { + ti->hooks.copy = ecs_copy_illegal; } + if(flags & ECS_MOVE_ILLEGAL) { + ti->hooks.move = ecs_move_illegal; + } + + if(flags & ECS_COPY_CTOR_ILLEGAL) { + ti->hooks.copy_ctor = ecs_copy_ctor_illegal; + } + + if(ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL) { + ti->hooks.move_ctor = ecs_move_ctor_illegal; + } + + if(ti->hooks.flags & ECS_CTOR_MOVE_DTOR_ILLEGAL) { + ti->hooks.ctor_move_dtor = ecs_move_ctor_illegal; + } + + if(ti->hooks.flags & ECS_MOVE_DTOR_ILLEGAL) { + ti->hooks.ctor_move_dtor = ecs_move_ctor_illegal; + } + + ti->hooks.flags = flags; + error: return; } @@ -51494,78 +51519,15 @@ void flecs_rtt_free_lifecycle_struct_ctx( ecs_os_free(ctx); } -typedef enum hook_req_t { - HookDefault = 0, /* Hook is a default hook */ - HookForward = 1, /* Hook is set and valid */ - HookIllegal = 2 /* Hook is set and calling it is illegal */ -} hook_req_t; - - -#define GET_HOOK(req, forward, illegal) ((req) & HookIllegal ? (illegal) : (req & HookForward ? (forward) : NULL)) - -/* Helper functions for hook requirements */ -static -hook_req_t -get_ctor_hook_req( - const ecs_type_info_t *member_ti) { - if (member_ti->hooks.ctor == ECS_CTOR_ILLEGAL) { - return HookIllegal; - } - if (member_ti->hooks.ctor && member_ti->hooks.ctor != flecs_default_ctor) { - return HookForward; - } - return HookDefault; -} - -static -hook_req_t get_dtor_hook_req( - const ecs_type_info_t *member_ti) -{ - if (member_ti->hooks.dtor == ECS_DTOR_ILLEGAL) { - return HookIllegal; - } - if (member_ti->hooks.dtor != NULL) { - return HookForward; - } - return HookDefault; -} - -static -hook_req_t get_move_hook_req( - const ecs_type_info_t *member_ti) -{ - if (member_ti->hooks.move == ECS_MOVE_ILLEGAL) { - return HookIllegal; - } - if (member_ti->hooks.move != NULL) { - return HookForward; - } - return HookDefault; -} - -static -hook_req_t get_copy_hook_req( - const ecs_type_info_t *member_ti) -{ - if (member_ti->hooks.copy == ECS_COPY_ILLEGAL) { - return HookIllegal; - } - if (member_ti->hooks.copy != NULL) { - return HookForward; - } - return HookDefault; -} - - - static ecs_rtt_struct_ctx_t * flecs_rtt_configure_struct_hooks( ecs_world_t *world, const ecs_type_info_t *ti, - hook_req_t ctor_req, - hook_req_t dtor_req, - hook_req_t move_req, - hook_req_t copy_req) + ecs_type_hooks_flags_t flags, + bool ctor, + bool dtor, + bool move, + bool copy) { ecs_type_hooks_t hooks = ti->hooks; if (hooks.lifecycle_ctx_free) { @@ -51573,10 +51535,7 @@ ecs_rtt_struct_ctx_t * flecs_rtt_configure_struct_hooks( } ecs_rtt_struct_ctx_t *rtt_ctx = NULL; - if (ctor_req == HookForward || - dtor_req == HookForward || - move_req == HookForward || - copy_req == HookForward) { + if (ctor || dtor || move || copy) { rtt_ctx = ecs_os_malloc_t(ecs_rtt_struct_ctx_t); ecs_vec_init_t(NULL, &rtt_ctx->vctor, ecs_rtt_call_data_t, 0); ecs_vec_init_t(NULL, &rtt_ctx->vdtor, ecs_rtt_call_data_t, 0); @@ -51584,16 +51543,24 @@ ecs_rtt_struct_ctx_t * flecs_rtt_configure_struct_hooks( ecs_vec_init_t(NULL, &rtt_ctx->vcopy, ecs_rtt_call_data_t, 0); hooks.lifecycle_ctx = rtt_ctx; hooks.lifecycle_ctx_free = flecs_rtt_free_lifecycle_struct_ctx; + + if (ctor) { + hooks.ctor = flecs_rtt_struct_ctor; + } + if (dtor) { + hooks.dtor = flecs_rtt_struct_dtor; + } + if (move) { + hooks.move = flecs_rtt_struct_move; + } + if (copy) { + hooks.copy = flecs_rtt_struct_copy; + } } else { hooks.lifecycle_ctx = NULL; hooks.lifecycle_ctx_free = NULL; } - - hooks.ctor = GET_HOOK(ctor_req, flecs_rtt_struct_ctor, ECS_CTOR_ILLEGAL); - hooks.dtor = GET_HOOK(dtor_req, flecs_rtt_struct_dtor, ECS_DTOR_ILLEGAL); - hooks.move = GET_HOOK(move_req, flecs_rtt_struct_move, ECS_MOVE_ILLEGAL); - hooks.copy = GET_HOOK(copy_req, flecs_rtt_struct_copy, ECS_COPY_ILLEGAL); - + hooks.flags |= flags; ecs_set_hooks_id(world, ti->component, &hooks); return rtt_ctx; } @@ -51611,27 +51578,27 @@ void flecs_rtt_init_default_hooks_struct( const EcsStruct *struct_info = ecs_get(world, component, EcsStruct); ecs_assert(struct_info != NULL, ECS_INTERNAL_ERROR, NULL); - /* These flags will be updated to the type of hook required */ - hook_req_t ctor_req = HookDefault, - dtor_req = HookDefault, - move_req = HookDefault, - copy_req = HookDefault; + /* These flags will be set to true if we determine we need to generate a + * hook of a particular type: */ + bool ctor_hook_required = false; + bool dtor_hook_required = false; + bool move_hook_required = false; + bool copy_hook_required = false; /* Iterate all struct members and see if any member type has hooks. If so, - * the struct itself will need to have that hook. - * If any struct member has an illegal hook, then the struct itself will - * have an illegal hook. - */ + * the struct itself will need to have that hook: */ int i, member_count = ecs_vec_count(&struct_info->members); ecs_member_t *members = ecs_vec_first(&struct_info->members); + ecs_type_hooks_flags_t flags = 0; for (i = 0; i < member_count; i++) { ecs_member_t *m = &members[i]; const ecs_type_info_t *member_ti = ecs_get_type_info(world, m->type); - - ctor_req |= get_ctor_hook_req(member_ti); - dtor_req |= get_dtor_hook_req(member_ti); - move_req |= get_move_hook_req(member_ti); - copy_req |= get_copy_hook_req(member_ti); + ctor_hook_required |= member_ti->hooks.ctor && + member_ti->hooks.ctor != flecs_default_ctor; + dtor_hook_required |= member_ti->hooks.dtor != NULL; + move_hook_required |= member_ti->hooks.move != NULL; + copy_hook_required |= member_ti->hooks.copy != NULL; + flags |= member_ti->hooks.flags; } /* If any hook is required, then create a lifecycle context and configure a @@ -51639,22 +51606,23 @@ void flecs_rtt_init_default_hooks_struct( ecs_rtt_struct_ctx_t *rtt_ctx = flecs_rtt_configure_struct_hooks( world, ti, - ctor_req, - dtor_req, - move_req, - copy_req); + flags, + ctor_hook_required, + dtor_hook_required, + move_hook_required, + copy_hook_required); if (!rtt_ctx) { - return; /* no forwarding required */ + return; /* no hooks required */ } - /* At least a hook forward was configured, therefore examine each struct member to + /* At least a hook was configured, therefore examine each struct member to * build the vector of calls that will then be executed by the generic hook * handler: */ for (i = 0; i < member_count; i++) { ecs_member_t *m = &members[i]; const ecs_type_info_t *member_ti = ecs_get_type_info(world, m->type); - if (ctor_req == HookForward) { + if (ctor_hook_required) { ecs_rtt_call_data_t *ctor_data = ecs_vec_append_t(NULL, &rtt_ctx->vctor, ecs_rtt_call_data_t); ctor_data->count = m->count; @@ -51666,7 +51634,7 @@ void flecs_rtt_init_default_hooks_struct( ctor_data->hook.xtor = flecs_default_ctor; } } - if (dtor_req == HookForward && member_ti->hooks.dtor) { + if (dtor_hook_required && member_ti->hooks.dtor) { ecs_rtt_call_data_t *dtor_data = ecs_vec_append_t(NULL, &rtt_ctx->vdtor, ecs_rtt_call_data_t); dtor_data->count = m->count; @@ -51674,7 +51642,7 @@ void flecs_rtt_init_default_hooks_struct( dtor_data->type_info = member_ti; dtor_data->hook.xtor = member_ti->hooks.dtor; } - if (move_req == HookForward) { + if (move_hook_required) { ecs_rtt_call_data_t *move_data = ecs_vec_append_t(NULL, &rtt_ctx->vmove, ecs_rtt_call_data_t); move_data->offset = m->offset; @@ -51686,7 +51654,7 @@ void flecs_rtt_init_default_hooks_struct( move_data->hook.move = flecs_rtt_default_move; } } - if (copy_req == HookForward) { + if (copy_hook_required) { ecs_rtt_call_data_t *copy_data = ecs_vec_append_t(NULL, &rtt_ctx->vcopy, ecs_rtt_call_data_t); copy_data->offset = m->offset; @@ -51806,37 +51774,46 @@ void flecs_rtt_init_default_hooks_array( ecs_assert(array_info != NULL, ECS_INTERNAL_ERROR, NULL); const ecs_type_info_t *array_ti = ecs_get_type_info(world, array_info->type); - hook_req_t ctor_req = get_ctor_hook_req(array_ti); - hook_req_t dtor_req = get_dtor_hook_req(array_ti); - hook_req_t move_req = get_move_hook_req(array_ti); - hook_req_t copy_req = get_copy_hook_req(array_ti); + bool ctor_hook_required = + array_ti->hooks.ctor && array_ti->hooks.ctor != flecs_default_ctor; + bool dtor_hook_required = array_ti->hooks.dtor != NULL; + bool move_hook_required = array_ti->hooks.move != NULL; + bool copy_hook_required = array_ti->hooks.copy != NULL; + ecs_type_hooks_flags_t flags = array_ti->hooks.flags; - ecs_type_hooks_t hooks = *ecs_get_hooks_id(world, component); + if (!ctor_hook_required && !dtor_hook_required && !move_hook_required && + !copy_hook_required) { + return; /* no hooks required */ + } + ecs_rtt_array_ctx_t *rtt_ctx = ecs_os_malloc_t(ecs_rtt_array_ctx_t); + rtt_ctx->type_info = array_ti; + rtt_ctx->elem_count = array_info->count; + ecs_type_hooks_t hooks = *ecs_get_hooks_id(world, component); if (hooks.lifecycle_ctx_free) { hooks.lifecycle_ctx_free(hooks.lifecycle_ctx); } - if (ctor_req == HookForward || - dtor_req == HookForward || - move_req == HookForward || - copy_req == HookForward) { - - ecs_rtt_array_ctx_t *rtt_ctx = ecs_os_malloc_t(ecs_rtt_array_ctx_t); - rtt_ctx->type_info = array_ti; - rtt_ctx->elem_count = array_info->count; + hooks.lifecycle_ctx = rtt_ctx; + hooks.lifecycle_ctx_free = flecs_rtt_free_lifecycle_array_ctx; - hooks.lifecycle_ctx = rtt_ctx; - hooks.lifecycle_ctx_free = flecs_rtt_free_lifecycle_array_ctx; - } else { - hooks.lifecycle_ctx = NULL; - hooks.lifecycle_ctx_free = NULL; + if (ctor_hook_required) { + hooks.ctor = flecs_rtt_array_ctor; + } + + if (dtor_hook_required) { + hooks.dtor = flecs_rtt_array_dtor; + } + + if (move_hook_required) { + hooks.move = flecs_rtt_array_move; + } + + if (copy_hook_required) { + hooks.copy = flecs_rtt_array_copy; } - hooks.ctor = GET_HOOK(ctor_req, flecs_rtt_array_ctor, ECS_CTOR_ILLEGAL); - hooks.dtor = GET_HOOK(dtor_req, flecs_rtt_array_dtor, ECS_DTOR_ILLEGAL); - hooks.move = GET_HOOK(move_req, flecs_rtt_array_move, ECS_MOVE_ILLEGAL); - hooks.copy = GET_HOOK(copy_req, flecs_rtt_array_copy, ECS_COPY_ILLEGAL); + hooks.flags |= flags; ecs_set_hooks_id(world, component, &hooks); } diff --git a/distr/flecs.h b/distr/flecs.h index c2a9c21dd..7602df3c7 100644 --- a/distr/flecs.h +++ b/distr/flecs.h @@ -3522,6 +3522,19 @@ struct ecs_observer_t { * * @ingroup components */ + +/* Hook flags */ +#define ECS_CTOR_ILLEGAL (1 << 0) +#define ECS_DTOR_ILLEGAL (1 << 1) +#define ECS_COPY_ILLEGAL (1 << 2) +#define ECS_MOVE_ILLEGAL (1 << 3) +#define ECS_COPY_CTOR_ILLEGAL (1 << 4) +#define ECS_MOVE_CTOR_ILLEGAL (1 << 5) +#define ECS_CTOR_MOVE_DTOR_ILLEGAL (1 << 6) +#define ECS_MOVE_DTOR_ILLEGAL (1 << 7) + +typedef uint8_t ecs_type_hooks_flags_t; + struct ecs_type_hooks_t { ecs_xtor_t ctor; /**< ctor */ ecs_xtor_t dtor; /**< dtor */ @@ -3546,6 +3559,12 @@ struct ecs_type_hooks_t { * not set explicitly it will be derived from other callbacks. */ ecs_move_t move_dtor; + /** Hook flags + * Indicates if any hook is illegal. + * Setting any flag will configure an aborting hook + */ + ecs_type_hooks_flags_t flags; + /** Callback that is invoked when an instance of a component is added. This * callback is invoked before triggers are invoked. */ ecs_iter_action_t on_add; @@ -7384,47 +7403,6 @@ const ecs_type_info_t* ecs_get_type_info( const ecs_world_t *world, ecs_id_t id); - -/** - * @defgroup illegal_hooks Illegal lifecycle hooks - * Functions to mark specific lifecycle hooks as illegal - * - * @{ - */ - -/* Illegal constructor handler and constant */ -FLECS_API -ecs_xtor_t ecs_ctor_illegal_(void); -#define ECS_CTOR_ILLEGAL (ecs_ctor_illegal_()) - -/* Illegal destructor handler and constant */ -FLECS_API -ecs_xtor_t ecs_dtor_illegal_(void); -#define ECS_DTOR_ILLEGAL (ecs_dtor_illegal_()) - -/* Illegal copy-assign handler and constant */ -FLECS_API -ecs_copy_t ecs_copy_illegal_(void); -#define ECS_COPY_ILLEGAL (ecs_copy_illegal_()) - -/* Illegal move-assign handler and constant */ -FLECS_API -ecs_move_t ecs_move_illegal_(void); -#define ECS_MOVE_ILLEGAL (ecs_move_illegal_()) - -/* Illegal copy constructor handler and constant */ -FLECS_API -ecs_copy_t ecs_copy_ctor_illegal_(void); -#define ECS_COPY_CTOR_ILLEGAL (ecs_copy_ctor_illegal_()) - -/* Illegal move constructor handler and constant */ -FLECS_API -ecs_move_t ecs_move_ctor_illegal_(void); -#define ECS_MOVE_CTOR_ILLEGAL (ecs_move_ctor_illegal_()) - -/** @} */ - - /** Register hooks for component. * Hooks allow for the execution of user code when components are constructed, * copied, moved, destructed, added, removed or set. Hooks can be assigned as @@ -20301,28 +20279,29 @@ namespace _ // Trivially constructible template ::value > = 0> -ecs_xtor_t ctor() { +ecs_xtor_t ctor(ecs_type_hooks_flags_t&) { return nullptr; } // Not constructible by flecs template ::value > = 0> -ecs_xtor_t ctor() { - return ECS_CTOR_ILLEGAL; +ecs_xtor_t ctor(ecs_type_hooks_flags_t& flags) { + flags |= ECS_CTOR_ILLEGAL; + return nullptr; } // Default constructible template ::value && std::is_default_constructible::value > = 0> -ecs_xtor_t ctor() { +ecs_xtor_t ctor(ecs_type_hooks_flags_t&) { return ctor_impl; } // No dtor template ::value > = 0> -ecs_xtor_t dtor() { +ecs_xtor_t dtor(ecs_type_hooks_flags_t&) { return nullptr; } @@ -20330,21 +20309,22 @@ ecs_xtor_t dtor() { template ::value && ! std::is_trivially_destructible::value > = 0> -ecs_xtor_t dtor() { +ecs_xtor_t dtor(ecs_type_hooks_flags_t&) { return dtor_impl; } // Assert when the type cannot be destructed template ::value > = 0> -ecs_xtor_t dtor() { +ecs_xtor_t dtor(ecs_type_hooks_flags_t& flags) { flecs_static_assert(always_false::value, "component type must be destructible"); - return ECS_DTOR_ILLEGAL; + flags |= ECS_DTOR_ILLEGAL; + return nullptr; } // Trivially copyable template ::value > = 0> -ecs_copy_t copy() { +ecs_copy_t copy(ecs_type_hooks_flags_t&) { return nullptr; } @@ -20352,77 +20332,82 @@ ecs_copy_t copy() { template ::value && ! std::is_copy_assignable::value > = 0> -ecs_copy_t copy() { - return ECS_COPY_ILLEGAL; +ecs_copy_t copy(ecs_type_hooks_flags_t& flags) { + flags |= ECS_COPY_ILLEGAL; + return nullptr; } // Copy assignment template ::value && ! std::is_trivially_copyable::value > = 0> -ecs_copy_t copy() { +ecs_copy_t copy(ecs_type_hooks_flags_t&) { return copy_impl; } // Trivially move assignable template ::value > = 0> -ecs_move_t move() { +ecs_move_t move(ecs_type_hooks_flags_t&) { return nullptr; } // Component types must be move assignable template ::value > = 0> -ecs_move_t move() { - return ECS_MOVE_ILLEGAL; +ecs_move_t move(ecs_type_hooks_flags_t& flags) { + flags |= ECS_MOVE_ILLEGAL; + return nullptr; } // Move assignment template ::value && ! std::is_trivially_move_assignable::value > = 0> -ecs_move_t move() { +ecs_move_t move(ecs_type_hooks_flags_t&) { return move_impl; } // Trivially copy constructible template ::value > = 0> -ecs_copy_t copy_ctor() { +ecs_copy_t copy_ctor(ecs_type_hooks_flags_t&) { return nullptr; } // No copy ctor template ::value > = 0> -ecs_copy_t copy_ctor() { - return ECS_COPY_CTOR_ILLEGAL; +ecs_copy_t copy_ctor(ecs_type_hooks_flags_t& flags) { + flags |= ECS_COPY_CTOR_ILLEGAL; + return nullptr; + } // Copy ctor template ::value && ! std::is_trivially_copy_constructible::value > = 0> -ecs_copy_t copy_ctor() { +ecs_copy_t copy_ctor(ecs_type_hooks_flags_t&) { return copy_ctor_impl; } // Trivially move constructible template ::value > = 0> -ecs_move_t move_ctor() { +ecs_move_t move_ctor(ecs_type_hooks_flags_t&) { return nullptr; } // Component types must be move constructible template ::value > = 0> -ecs_move_t move_ctor() { - return ECS_MOVE_CTOR_ILLEGAL; +ecs_move_t move_ctor(ecs_type_hooks_flags_t& flags) { + flags |= ECS_MOVE_CTOR_ILLEGAL; + return nullptr; } // Move ctor template ::value && ! std::is_trivially_move_constructible::value > = 0> -ecs_move_t move_ctor() { +ecs_move_t move_ctor(ecs_type_hooks_flags_t&) { return move_ctor_impl; } @@ -20430,7 +20415,7 @@ ecs_move_t move_ctor() { template ::value && std::is_trivially_destructible::value > = 0> -ecs_move_t ctor_move_dtor() { +ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t&) { return nullptr; } @@ -20438,8 +20423,9 @@ ecs_move_t ctor_move_dtor() { template ::value || ! std::is_destructible::value > = 0> -ecs_move_t ctor_move_dtor() { - return ECS_MOVE_CTOR_ILLEGAL; +ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t& flags) { + flags |= ECS_CTOR_MOVE_DTOR_ILLEGAL; + return nullptr; } // Merge ctor + dtor @@ -20448,7 +20434,7 @@ template ::value) && std::is_move_constructible::value && std::is_destructible::value > = 0> -ecs_move_t ctor_move_dtor() { +ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t&) { return ctor_move_dtor_impl; } @@ -20456,7 +20442,7 @@ ecs_move_t ctor_move_dtor() { template ::value && std::is_trivially_destructible::value > = 0> -ecs_move_t move_dtor() { +ecs_move_t move_dtor(ecs_type_hooks_flags_t&) { return nullptr; } @@ -20464,8 +20450,9 @@ ecs_move_t move_dtor() { template ::value || ! std::is_destructible::value > = 0> -ecs_move_t move_dtor() { - return ECS_MOVE_CTOR_ILLEGAL; +ecs_move_t move_dtor(ecs_type_hooks_flags_t& flags) { + flags |= ECS_MOVE_DTOR_ILLEGAL; + return nullptr; } // Merge assign + dtor @@ -20474,7 +20461,7 @@ template ::value) && std::is_move_assignable::value && std::is_destructible::value > = 0> -ecs_move_t move_dtor() { +ecs_move_t move_dtor(ecs_type_hooks_flags_t&) { return move_dtor_impl; } @@ -26824,20 +26811,20 @@ void register_lifecycle_actions( ecs_entity_t component) { ecs_type_hooks_t cl{}; - cl.ctor = ctor(); - cl.dtor = dtor(); + cl.ctor = ctor(cl.flags); + cl.dtor = dtor(cl.flags); - cl.copy = copy(); - cl.copy_ctor = copy_ctor(); - cl.move = move(); - cl.move_ctor = move_ctor(); + cl.copy = copy(cl.flags); + cl.copy_ctor = copy_ctor(cl.flags); + cl.move = move(cl.flags); + cl.move_ctor = move_ctor(cl.flags); - cl.ctor_move_dtor = ctor_move_dtor(); - cl.move_dtor = move_dtor(); + cl.ctor_move_dtor = ctor_move_dtor(cl.flags); + cl.move_dtor = move_dtor(cl.flags); - ecs_set_hooks_id( world, component, &cl); + ecs_set_hooks_id(world, component, &cl); - if (cl.move == ECS_MOVE_ILLEGAL || cl.move_ctor == ECS_MOVE_CTOR_ILLEGAL) { + if (cl.flags & ECS_MOVE_ILLEGAL || cl.flags & ECS_MOVE_CTOR_ILLEGAL) { ecs_add_id(world, component, flecs::Sparse); } } diff --git a/include/flecs.h b/include/flecs.h index 54d1602da..ef9deca78 100644 --- a/include/flecs.h +++ b/include/flecs.h @@ -861,6 +861,19 @@ struct ecs_observer_t { * * @ingroup components */ + +/* Hook flags */ +#define ECS_CTOR_ILLEGAL (1 << 0) +#define ECS_DTOR_ILLEGAL (1 << 1) +#define ECS_COPY_ILLEGAL (1 << 2) +#define ECS_MOVE_ILLEGAL (1 << 3) +#define ECS_COPY_CTOR_ILLEGAL (1 << 4) +#define ECS_MOVE_CTOR_ILLEGAL (1 << 5) +#define ECS_CTOR_MOVE_DTOR_ILLEGAL (1 << 6) +#define ECS_MOVE_DTOR_ILLEGAL (1 << 7) + +typedef uint8_t ecs_type_hooks_flags_t; + struct ecs_type_hooks_t { ecs_xtor_t ctor; /**< ctor */ ecs_xtor_t dtor; /**< dtor */ @@ -885,6 +898,12 @@ struct ecs_type_hooks_t { * not set explicitly it will be derived from other callbacks. */ ecs_move_t move_dtor; + /** Hook flags + * Indicates if any hook is illegal. + * Setting any flag will configure an aborting hook + */ + ecs_type_hooks_flags_t flags; + /** Callback that is invoked when an instance of a component is added. This * callback is invoked before triggers are invoked. */ ecs_iter_action_t on_add; @@ -4157,47 +4176,6 @@ const ecs_type_info_t* ecs_get_type_info( const ecs_world_t *world, ecs_id_t id); - -/** - * @defgroup illegal_hooks Illegal lifecycle hooks - * Functions to mark specific lifecycle hooks as illegal - * - * @{ - */ - -/* Illegal constructor handler and constant */ -FLECS_API -ecs_xtor_t ecs_ctor_illegal_(void); -#define ECS_CTOR_ILLEGAL (ecs_ctor_illegal_()) - -/* Illegal destructor handler and constant */ -FLECS_API -ecs_xtor_t ecs_dtor_illegal_(void); -#define ECS_DTOR_ILLEGAL (ecs_dtor_illegal_()) - -/* Illegal copy-assign handler and constant */ -FLECS_API -ecs_copy_t ecs_copy_illegal_(void); -#define ECS_COPY_ILLEGAL (ecs_copy_illegal_()) - -/* Illegal move-assign handler and constant */ -FLECS_API -ecs_move_t ecs_move_illegal_(void); -#define ECS_MOVE_ILLEGAL (ecs_move_illegal_()) - -/* Illegal copy constructor handler and constant */ -FLECS_API -ecs_copy_t ecs_copy_ctor_illegal_(void); -#define ECS_COPY_CTOR_ILLEGAL (ecs_copy_ctor_illegal_()) - -/* Illegal move constructor handler and constant */ -FLECS_API -ecs_move_t ecs_move_ctor_illegal_(void); -#define ECS_MOVE_CTOR_ILLEGAL (ecs_move_ctor_illegal_()) - -/** @} */ - - /** Register hooks for component. * Hooks allow for the execution of user code when components are constructed, * copied, moved, destructed, added, removed or set. Hooks can be assigned as diff --git a/include/flecs/addons/cpp/component.hpp b/include/flecs/addons/cpp/component.hpp index 98285ffc1..dd1003edd 100644 --- a/include/flecs/addons/cpp/component.hpp +++ b/include/flecs/addons/cpp/component.hpp @@ -101,20 +101,20 @@ void register_lifecycle_actions( ecs_entity_t component) { ecs_type_hooks_t cl{}; - cl.ctor = ctor(); - cl.dtor = dtor(); + cl.ctor = ctor(cl.flags); + cl.dtor = dtor(cl.flags); - cl.copy = copy(); - cl.copy_ctor = copy_ctor(); - cl.move = move(); - cl.move_ctor = move_ctor(); + cl.copy = copy(cl.flags); + cl.copy_ctor = copy_ctor(cl.flags); + cl.move = move(cl.flags); + cl.move_ctor = move_ctor(cl.flags); - cl.ctor_move_dtor = ctor_move_dtor(); - cl.move_dtor = move_dtor(); + cl.ctor_move_dtor = ctor_move_dtor(cl.flags); + cl.move_dtor = move_dtor(cl.flags); - ecs_set_hooks_id( world, component, &cl); + ecs_set_hooks_id(world, component, &cl); - if (cl.move == ECS_MOVE_ILLEGAL || cl.move_ctor == ECS_MOVE_CTOR_ILLEGAL) { + if (cl.flags & ECS_MOVE_ILLEGAL || cl.flags & ECS_MOVE_CTOR_ILLEGAL) { ecs_add_id(world, component, flecs::Sparse); } } diff --git a/include/flecs/addons/cpp/lifecycle_traits.hpp b/include/flecs/addons/cpp/lifecycle_traits.hpp index 69051fcd0..b0e54fafe 100644 --- a/include/flecs/addons/cpp/lifecycle_traits.hpp +++ b/include/flecs/addons/cpp/lifecycle_traits.hpp @@ -162,28 +162,29 @@ namespace _ // Trivially constructible template ::value > = 0> -ecs_xtor_t ctor() { +ecs_xtor_t ctor(ecs_type_hooks_flags_t&) { return nullptr; } // Not constructible by flecs template ::value > = 0> -ecs_xtor_t ctor() { - return ECS_CTOR_ILLEGAL; +ecs_xtor_t ctor(ecs_type_hooks_flags_t& flags) { + flags |= ECS_CTOR_ILLEGAL; + return nullptr; } // Default constructible template ::value && std::is_default_constructible::value > = 0> -ecs_xtor_t ctor() { +ecs_xtor_t ctor(ecs_type_hooks_flags_t&) { return ctor_impl; } // No dtor template ::value > = 0> -ecs_xtor_t dtor() { +ecs_xtor_t dtor(ecs_type_hooks_flags_t&) { return nullptr; } @@ -191,21 +192,22 @@ ecs_xtor_t dtor() { template ::value && ! std::is_trivially_destructible::value > = 0> -ecs_xtor_t dtor() { +ecs_xtor_t dtor(ecs_type_hooks_flags_t&) { return dtor_impl; } // Assert when the type cannot be destructed template ::value > = 0> -ecs_xtor_t dtor() { +ecs_xtor_t dtor(ecs_type_hooks_flags_t& flags) { flecs_static_assert(always_false::value, "component type must be destructible"); - return ECS_DTOR_ILLEGAL; + flags |= ECS_DTOR_ILLEGAL; + return nullptr; } // Trivially copyable template ::value > = 0> -ecs_copy_t copy() { +ecs_copy_t copy(ecs_type_hooks_flags_t&) { return nullptr; } @@ -213,77 +215,82 @@ ecs_copy_t copy() { template ::value && ! std::is_copy_assignable::value > = 0> -ecs_copy_t copy() { - return ECS_COPY_ILLEGAL; +ecs_copy_t copy(ecs_type_hooks_flags_t& flags) { + flags |= ECS_COPY_ILLEGAL; + return nullptr; } // Copy assignment template ::value && ! std::is_trivially_copyable::value > = 0> -ecs_copy_t copy() { +ecs_copy_t copy(ecs_type_hooks_flags_t&) { return copy_impl; } // Trivially move assignable template ::value > = 0> -ecs_move_t move() { +ecs_move_t move(ecs_type_hooks_flags_t&) { return nullptr; } // Component types must be move assignable template ::value > = 0> -ecs_move_t move() { - return ECS_MOVE_ILLEGAL; +ecs_move_t move(ecs_type_hooks_flags_t& flags) { + flags |= ECS_MOVE_ILLEGAL; + return nullptr; } // Move assignment template ::value && ! std::is_trivially_move_assignable::value > = 0> -ecs_move_t move() { +ecs_move_t move(ecs_type_hooks_flags_t&) { return move_impl; } // Trivially copy constructible template ::value > = 0> -ecs_copy_t copy_ctor() { +ecs_copy_t copy_ctor(ecs_type_hooks_flags_t&) { return nullptr; } // No copy ctor template ::value > = 0> -ecs_copy_t copy_ctor() { - return ECS_COPY_CTOR_ILLEGAL; +ecs_copy_t copy_ctor(ecs_type_hooks_flags_t& flags) { + flags |= ECS_COPY_CTOR_ILLEGAL; + return nullptr; + } // Copy ctor template ::value && ! std::is_trivially_copy_constructible::value > = 0> -ecs_copy_t copy_ctor() { +ecs_copy_t copy_ctor(ecs_type_hooks_flags_t&) { return copy_ctor_impl; } // Trivially move constructible template ::value > = 0> -ecs_move_t move_ctor() { +ecs_move_t move_ctor(ecs_type_hooks_flags_t&) { return nullptr; } // Component types must be move constructible template ::value > = 0> -ecs_move_t move_ctor() { - return ECS_MOVE_CTOR_ILLEGAL; +ecs_move_t move_ctor(ecs_type_hooks_flags_t& flags) { + flags |= ECS_MOVE_CTOR_ILLEGAL; + return nullptr; } // Move ctor template ::value && ! std::is_trivially_move_constructible::value > = 0> -ecs_move_t move_ctor() { +ecs_move_t move_ctor(ecs_type_hooks_flags_t&) { return move_ctor_impl; } @@ -291,7 +298,7 @@ ecs_move_t move_ctor() { template ::value && std::is_trivially_destructible::value > = 0> -ecs_move_t ctor_move_dtor() { +ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t&) { return nullptr; } @@ -299,8 +306,9 @@ ecs_move_t ctor_move_dtor() { template ::value || ! std::is_destructible::value > = 0> -ecs_move_t ctor_move_dtor() { - return ECS_MOVE_CTOR_ILLEGAL; +ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t& flags) { + flags |= ECS_CTOR_MOVE_DTOR_ILLEGAL; + return nullptr; } // Merge ctor + dtor @@ -309,7 +317,7 @@ template ::value) && std::is_move_constructible::value && std::is_destructible::value > = 0> -ecs_move_t ctor_move_dtor() { +ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t&) { return ctor_move_dtor_impl; } @@ -317,7 +325,7 @@ ecs_move_t ctor_move_dtor() { template ::value && std::is_trivially_destructible::value > = 0> -ecs_move_t move_dtor() { +ecs_move_t move_dtor(ecs_type_hooks_flags_t&) { return nullptr; } @@ -325,8 +333,9 @@ ecs_move_t move_dtor() { template ::value || ! std::is_destructible::value > = 0> -ecs_move_t move_dtor() { - return ECS_MOVE_CTOR_ILLEGAL; +ecs_move_t move_dtor(ecs_type_hooks_flags_t& flags) { + flags |= ECS_MOVE_DTOR_ILLEGAL; + return nullptr; } // Merge assign + dtor @@ -335,7 +344,7 @@ template ::value) && std::is_move_assignable::value && std::is_destructible::value > = 0> -ecs_move_t move_dtor() { +ecs_move_t move_dtor(ecs_type_hooks_flags_t&) { return move_dtor_impl; } diff --git a/src/addons/meta/rtt_lifecycle.c b/src/addons/meta/rtt_lifecycle.c index 066299d23..5c5b7339a 100644 --- a/src/addons/meta/rtt_lifecycle.c +++ b/src/addons/meta/rtt_lifecycle.c @@ -200,78 +200,15 @@ void flecs_rtt_free_lifecycle_struct_ctx( ecs_os_free(ctx); } -typedef enum hook_req_t { - HookDefault = 0, /* Hook is a default hook */ - HookForward = 1, /* Hook is set and valid */ - HookIllegal = 2 /* Hook is set and calling it is illegal */ -} hook_req_t; - - -#define GET_HOOK(req, forward, illegal) ((req) & HookIllegal ? (illegal) : (req & HookForward ? (forward) : NULL)) - -/* Helper functions for hook requirements */ -static -hook_req_t -get_ctor_hook_req( - const ecs_type_info_t *member_ti) { - if (member_ti->hooks.ctor == ECS_CTOR_ILLEGAL) { - return HookIllegal; - } - if (member_ti->hooks.ctor && member_ti->hooks.ctor != flecs_default_ctor) { - return HookForward; - } - return HookDefault; -} - -static -hook_req_t get_dtor_hook_req( - const ecs_type_info_t *member_ti) -{ - if (member_ti->hooks.dtor == ECS_DTOR_ILLEGAL) { - return HookIllegal; - } - if (member_ti->hooks.dtor != NULL) { - return HookForward; - } - return HookDefault; -} - -static -hook_req_t get_move_hook_req( - const ecs_type_info_t *member_ti) -{ - if (member_ti->hooks.move == ECS_MOVE_ILLEGAL) { - return HookIllegal; - } - if (member_ti->hooks.move != NULL) { - return HookForward; - } - return HookDefault; -} - -static -hook_req_t get_copy_hook_req( - const ecs_type_info_t *member_ti) -{ - if (member_ti->hooks.copy == ECS_COPY_ILLEGAL) { - return HookIllegal; - } - if (member_ti->hooks.copy != NULL) { - return HookForward; - } - return HookDefault; -} - - - static ecs_rtt_struct_ctx_t * flecs_rtt_configure_struct_hooks( ecs_world_t *world, const ecs_type_info_t *ti, - hook_req_t ctor_req, - hook_req_t dtor_req, - hook_req_t move_req, - hook_req_t copy_req) + ecs_type_hooks_flags_t flags, + bool ctor, + bool dtor, + bool move, + bool copy) { ecs_type_hooks_t hooks = ti->hooks; if (hooks.lifecycle_ctx_free) { @@ -279,10 +216,7 @@ ecs_rtt_struct_ctx_t * flecs_rtt_configure_struct_hooks( } ecs_rtt_struct_ctx_t *rtt_ctx = NULL; - if (ctor_req == HookForward || - dtor_req == HookForward || - move_req == HookForward || - copy_req == HookForward) { + if (ctor || dtor || move || copy) { rtt_ctx = ecs_os_malloc_t(ecs_rtt_struct_ctx_t); ecs_vec_init_t(NULL, &rtt_ctx->vctor, ecs_rtt_call_data_t, 0); ecs_vec_init_t(NULL, &rtt_ctx->vdtor, ecs_rtt_call_data_t, 0); @@ -290,16 +224,24 @@ ecs_rtt_struct_ctx_t * flecs_rtt_configure_struct_hooks( ecs_vec_init_t(NULL, &rtt_ctx->vcopy, ecs_rtt_call_data_t, 0); hooks.lifecycle_ctx = rtt_ctx; hooks.lifecycle_ctx_free = flecs_rtt_free_lifecycle_struct_ctx; + + if (ctor) { + hooks.ctor = flecs_rtt_struct_ctor; + } + if (dtor) { + hooks.dtor = flecs_rtt_struct_dtor; + } + if (move) { + hooks.move = flecs_rtt_struct_move; + } + if (copy) { + hooks.copy = flecs_rtt_struct_copy; + } } else { hooks.lifecycle_ctx = NULL; hooks.lifecycle_ctx_free = NULL; } - - hooks.ctor = GET_HOOK(ctor_req, flecs_rtt_struct_ctor, ECS_CTOR_ILLEGAL); - hooks.dtor = GET_HOOK(dtor_req, flecs_rtt_struct_dtor, ECS_DTOR_ILLEGAL); - hooks.move = GET_HOOK(move_req, flecs_rtt_struct_move, ECS_MOVE_ILLEGAL); - hooks.copy = GET_HOOK(copy_req, flecs_rtt_struct_copy, ECS_COPY_ILLEGAL); - + hooks.flags |= flags; ecs_set_hooks_id(world, ti->component, &hooks); return rtt_ctx; } @@ -317,27 +259,27 @@ void flecs_rtt_init_default_hooks_struct( const EcsStruct *struct_info = ecs_get(world, component, EcsStruct); ecs_assert(struct_info != NULL, ECS_INTERNAL_ERROR, NULL); - /* These flags will be updated to the type of hook required */ - hook_req_t ctor_req = HookDefault, - dtor_req = HookDefault, - move_req = HookDefault, - copy_req = HookDefault; + /* These flags will be set to true if we determine we need to generate a + * hook of a particular type: */ + bool ctor_hook_required = false; + bool dtor_hook_required = false; + bool move_hook_required = false; + bool copy_hook_required = false; /* Iterate all struct members and see if any member type has hooks. If so, - * the struct itself will need to have that hook. - * If any struct member has an illegal hook, then the struct itself will - * have an illegal hook. - */ + * the struct itself will need to have that hook: */ int i, member_count = ecs_vec_count(&struct_info->members); ecs_member_t *members = ecs_vec_first(&struct_info->members); + ecs_type_hooks_flags_t flags = 0; for (i = 0; i < member_count; i++) { ecs_member_t *m = &members[i]; const ecs_type_info_t *member_ti = ecs_get_type_info(world, m->type); - - ctor_req |= get_ctor_hook_req(member_ti); - dtor_req |= get_dtor_hook_req(member_ti); - move_req |= get_move_hook_req(member_ti); - copy_req |= get_copy_hook_req(member_ti); + ctor_hook_required |= member_ti->hooks.ctor && + member_ti->hooks.ctor != flecs_default_ctor; + dtor_hook_required |= member_ti->hooks.dtor != NULL; + move_hook_required |= member_ti->hooks.move != NULL; + copy_hook_required |= member_ti->hooks.copy != NULL; + flags |= member_ti->hooks.flags; } /* If any hook is required, then create a lifecycle context and configure a @@ -345,22 +287,23 @@ void flecs_rtt_init_default_hooks_struct( ecs_rtt_struct_ctx_t *rtt_ctx = flecs_rtt_configure_struct_hooks( world, ti, - ctor_req, - dtor_req, - move_req, - copy_req); + flags, + ctor_hook_required, + dtor_hook_required, + move_hook_required, + copy_hook_required); if (!rtt_ctx) { - return; /* no forwarding required */ + return; /* no hooks required */ } - /* At least a hook forward was configured, therefore examine each struct member to + /* At least a hook was configured, therefore examine each struct member to * build the vector of calls that will then be executed by the generic hook * handler: */ for (i = 0; i < member_count; i++) { ecs_member_t *m = &members[i]; const ecs_type_info_t *member_ti = ecs_get_type_info(world, m->type); - if (ctor_req == HookForward) { + if (ctor_hook_required) { ecs_rtt_call_data_t *ctor_data = ecs_vec_append_t(NULL, &rtt_ctx->vctor, ecs_rtt_call_data_t); ctor_data->count = m->count; @@ -372,7 +315,7 @@ void flecs_rtt_init_default_hooks_struct( ctor_data->hook.xtor = flecs_default_ctor; } } - if (dtor_req == HookForward && member_ti->hooks.dtor) { + if (dtor_hook_required && member_ti->hooks.dtor) { ecs_rtt_call_data_t *dtor_data = ecs_vec_append_t(NULL, &rtt_ctx->vdtor, ecs_rtt_call_data_t); dtor_data->count = m->count; @@ -380,7 +323,7 @@ void flecs_rtt_init_default_hooks_struct( dtor_data->type_info = member_ti; dtor_data->hook.xtor = member_ti->hooks.dtor; } - if (move_req == HookForward) { + if (move_hook_required) { ecs_rtt_call_data_t *move_data = ecs_vec_append_t(NULL, &rtt_ctx->vmove, ecs_rtt_call_data_t); move_data->offset = m->offset; @@ -392,7 +335,7 @@ void flecs_rtt_init_default_hooks_struct( move_data->hook.move = flecs_rtt_default_move; } } - if (copy_req == HookForward) { + if (copy_hook_required) { ecs_rtt_call_data_t *copy_data = ecs_vec_append_t(NULL, &rtt_ctx->vcopy, ecs_rtt_call_data_t); copy_data->offset = m->offset; @@ -512,37 +455,46 @@ void flecs_rtt_init_default_hooks_array( ecs_assert(array_info != NULL, ECS_INTERNAL_ERROR, NULL); const ecs_type_info_t *array_ti = ecs_get_type_info(world, array_info->type); - hook_req_t ctor_req = get_ctor_hook_req(array_ti); - hook_req_t dtor_req = get_dtor_hook_req(array_ti); - hook_req_t move_req = get_move_hook_req(array_ti); - hook_req_t copy_req = get_copy_hook_req(array_ti); + bool ctor_hook_required = + array_ti->hooks.ctor && array_ti->hooks.ctor != flecs_default_ctor; + bool dtor_hook_required = array_ti->hooks.dtor != NULL; + bool move_hook_required = array_ti->hooks.move != NULL; + bool copy_hook_required = array_ti->hooks.copy != NULL; + ecs_type_hooks_flags_t flags = array_ti->hooks.flags; + + if (!ctor_hook_required && !dtor_hook_required && !move_hook_required && + !copy_hook_required) { + return; /* no hooks required */ + } + ecs_rtt_array_ctx_t *rtt_ctx = ecs_os_malloc_t(ecs_rtt_array_ctx_t); + rtt_ctx->type_info = array_ti; + rtt_ctx->elem_count = array_info->count; ecs_type_hooks_t hooks = *ecs_get_hooks_id(world, component); - if (hooks.lifecycle_ctx_free) { hooks.lifecycle_ctx_free(hooks.lifecycle_ctx); } - if (ctor_req == HookForward || - dtor_req == HookForward || - move_req == HookForward || - copy_req == HookForward) { - - ecs_rtt_array_ctx_t *rtt_ctx = ecs_os_malloc_t(ecs_rtt_array_ctx_t); - rtt_ctx->type_info = array_ti; - rtt_ctx->elem_count = array_info->count; + hooks.lifecycle_ctx = rtt_ctx; + hooks.lifecycle_ctx_free = flecs_rtt_free_lifecycle_array_ctx; - hooks.lifecycle_ctx = rtt_ctx; - hooks.lifecycle_ctx_free = flecs_rtt_free_lifecycle_array_ctx; - } else { - hooks.lifecycle_ctx = NULL; - hooks.lifecycle_ctx_free = NULL; + if (ctor_hook_required) { + hooks.ctor = flecs_rtt_array_ctor; + } + + if (dtor_hook_required) { + hooks.dtor = flecs_rtt_array_dtor; + } + + if (move_hook_required) { + hooks.move = flecs_rtt_array_move; + } + + if (copy_hook_required) { + hooks.copy = flecs_rtt_array_copy; } - hooks.ctor = GET_HOOK(ctor_req, flecs_rtt_array_ctor, ECS_CTOR_ILLEGAL); - hooks.dtor = GET_HOOK(dtor_req, flecs_rtt_array_dtor, ECS_DTOR_ILLEGAL); - hooks.move = GET_HOOK(move_req, flecs_rtt_array_move, ECS_MOVE_ILLEGAL); - hooks.copy = GET_HOOK(copy_req, flecs_rtt_array_copy, ECS_COPY_ILLEGAL); + hooks.flags |= flags; ecs_set_hooks_id(world, component, &hooks); } diff --git a/src/entity.c b/src/entity.c index 815193b1b..99a20115a 100644 --- a/src/entity.c +++ b/src/entity.c @@ -5335,120 +5335,3 @@ bool flecs_defer_purge( error: return false; } - -/* Define noreturn attribute only for GCC or Clang. - * Certain builds in Windows require this for functions that abort - * (-Wmissing-noreturn) -*/ -#if defined(__GNUC__) || defined(__clang__) - #define NORETURN __attribute__((noreturn)) -#else - #define NORETURN -#endif - -NORETURN -static -void ecs_ctor_illegal( - void * dst, - int32_t count, - const ecs_type_info_t *ti) { - (void)dst; /* silence unused warning */ - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid constructor for %s", ti->name); -} - -ecs_xtor_t ecs_ctor_illegal_(void) -{ - return ecs_ctor_illegal; -} - -NORETURN -static -void ecs_dtor_illegal( - void *dst, - int32_t count, - const ecs_type_info_t *ti) { - (void)dst; /* silence unused warning */ - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid destructor for %s", ti->name); -} - -ecs_xtor_t ecs_dtor_illegal_(void) -{ - return ecs_dtor_illegal; -} - -NORETURN -static -void ecs_copy_illegal( - void *dst, - const void *src, - int32_t count, - const ecs_type_info_t *ti) -{ - (void)dst; /* silence unused warning */ - (void)src; - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid copy assignment for %s", ti->name); -} - -ecs_copy_t ecs_copy_illegal_(void) -{ - return ecs_copy_illegal; -} - -NORETURN -static -void ecs_move_illegal( - void * dst, - void * src, - int32_t count, - const ecs_type_info_t *ti) { - (void)dst; /* silence unused warning */ - (void)src; - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid move assignment for %s", ti->name); -} - -ecs_move_t ecs_move_illegal_(void) -{ - return ecs_move_illegal; -} - -NORETURN -static -void ecs_copy_ctor_illegal( - void *dst, - const void *src, - int32_t count, - const ecs_type_info_t *ti) -{ - (void)dst; /* silence unused warning */ - (void)src; - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid copy construct for %s", ti->name); -} - -ecs_copy_t ecs_copy_ctor_illegal_(void) -{ - return ecs_copy_ctor_illegal; -} - -NORETURN -static -void ecs_move_ctor_illegal( - void *dst, - void *src, - int32_t count, - const ecs_type_info_t *ti) -{ - (void)dst; /* silence unused warning */ - (void)src; - (void)count; - ecs_abort(ECS_INVALID_OPERATION, "invalid move construct for %s", ti->name); -} - -ecs_move_t ecs_move_ctor_illegal_(void) -{ - return ecs_move_ctor_illegal; -} diff --git a/src/world.c b/src/world.c index c71ffa8cb..f4eea0fae 100644 --- a/src/world.c +++ b/src/world.c @@ -1195,6 +1195,94 @@ void flecs_default_move_w_dtor(void *dst_ptr, void *src_ptr, cl->dtor(src_ptr, count, ti); } +/* Define noreturn attribute only for GCC or Clang. + * Certain builds in Windows require this for functions that abort + * (-Wmissing-noreturn) +*/ +#if defined(__GNUC__) || defined(__clang__) + #define NORETURN __attribute__((noreturn)) +#else + #define NORETURN +#endif + +NORETURN +static +void ecs_ctor_illegal( + void * dst, + int32_t count, + const ecs_type_info_t *ti) { + (void)dst; /* silence unused warning */ + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid constructor for %s", ti->name); +} + +NORETURN +static +void ecs_dtor_illegal( + void *dst, + int32_t count, + const ecs_type_info_t *ti) { + (void)dst; /* silence unused warning */ + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid destructor for %s", ti->name); +} + +NORETURN +static +void ecs_copy_illegal( + void *dst, + const void *src, + int32_t count, + const ecs_type_info_t *ti) +{ + (void)dst; /* silence unused warning */ + (void)src; + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid copy assignment for %s", ti->name); +} + +NORETURN +static +void ecs_move_illegal( + void * dst, + void * src, + int32_t count, + const ecs_type_info_t *ti) { + (void)dst; /* silence unused warning */ + (void)src; + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid move assignment for %s", ti->name); +} + +NORETURN +static +void ecs_copy_ctor_illegal( + void *dst, + const void *src, + int32_t count, + const ecs_type_info_t *ti) +{ + (void)dst; /* silence unused warning */ + (void)src; + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid copy construct for %s", ti->name); +} + +NORETURN +static +void ecs_move_ctor_illegal( + void *dst, + void *src, + int32_t count, + const ecs_type_info_t *ti) +{ + (void)dst; /* silence unused warning */ + (void)src; + (void)count; + ecs_abort(ECS_INVALID_OPERATION, "invalid move construct for %s", ti->name); +} + + void ecs_set_hooks_id( ecs_world_t *world, ecs_entity_t component, @@ -1230,6 +1318,7 @@ void ecs_set_hooks_id( ti->alignment = component_ptr->alignment; } + ti->hooks.flags = h->flags; if (h->ctor) ti->hooks.ctor = h->ctor; if (h->dtor) ti->hooks.dtor = h->dtor; if (h->copy) ti->hooks.copy = h->copy; @@ -1259,35 +1348,42 @@ void ecs_set_hooks_id( } /* Set default copy ctor, move ctor and merge */ + ecs_type_hooks_flags_t flags = h->flags; if (!h->copy_ctor) { - if(h->copy == ECS_COPY_ILLEGAL || h->ctor == ECS_CTOR_ILLEGAL) { - ti->hooks.copy_ctor = ECS_COPY_CTOR_ILLEGAL; + if(flags & ECS_COPY_ILLEGAL || flags & ECS_CTOR_ILLEGAL) { + flags |= ECS_COPY_CTOR_ILLEGAL; } else if(h->copy) { ti->hooks.copy_ctor = flecs_default_copy_ctor; } } if (!h->move_ctor) { - if(h->move == ECS_MOVE_ILLEGAL || h->ctor == ECS_CTOR_ILLEGAL) { - ti->hooks.move_ctor = ECS_MOVE_CTOR_ILLEGAL; + if(flags & ECS_MOVE_ILLEGAL || flags & ECS_CTOR_ILLEGAL) { + flags |= ECS_MOVE_CTOR_ILLEGAL; } else if (h->move) { ti->hooks.move_ctor = flecs_default_move_ctor; } } if (!h->ctor_move_dtor) { + ecs_type_hooks_flags_t illegal_check = 0; if (h->move) { + illegal_check |= ECS_MOVE_ILLEGAL; if (h->dtor) { + illegal_check |= ECS_DTOR_ILLEGAL; if (h->move_ctor) { + illegal_check |= ECS_MOVE_CTOR_ILLEGAL; /* If an explicit move ctor has been set, use callback * that uses the move ctor vs. using a ctor+move */ ti->hooks.ctor_move_dtor = flecs_default_move_ctor_w_dtor; } else { + illegal_check |= ECS_CTOR_ILLEGAL; /* If no explicit move_ctor has been set, use * combination of ctor + move + dtor */ ti->hooks.ctor_move_dtor = flecs_default_ctor_w_move_w_dtor; } } else { + illegal_check |= ECS_MOVE_CTOR_ILLEGAL; /* If no dtor has been set, this is just a move ctor */ ti->hooks.ctor_move_dtor = ti->hooks.move_ctor; } @@ -1295,29 +1391,75 @@ void ecs_set_hooks_id( /* If move is not set but move_ctor and dtor is, we can still set * ctor_move_dtor. */ if (h->move_ctor) { + illegal_check |= ECS_MOVE_CTOR_ILLEGAL; if (h->dtor) { + illegal_check |= ECS_DTOR_ILLEGAL; ti->hooks.ctor_move_dtor = flecs_default_move_ctor_w_dtor; } else { ti->hooks.ctor_move_dtor = ti->hooks.move_ctor; } } } + if(flags & illegal_check) { + flags |= ECS_CTOR_MOVE_DTOR_ILLEGAL; + } } if (!h->move_dtor) { + ecs_type_hooks_flags_t illegal_check = 0; if (h->move) { + illegal_check |= ECS_MOVE_ILLEGAL; if (h->dtor) { + illegal_check |= ECS_DTOR_ILLEGAL; ti->hooks.move_dtor = flecs_default_move_w_dtor; } else { ti->hooks.move_dtor = flecs_default_move; } } else { if (h->dtor) { + illegal_check |= ECS_DTOR_ILLEGAL; ti->hooks.move_dtor = flecs_default_dtor; } } + if(flags & illegal_check) { + flags |= ECS_MOVE_DTOR_ILLEGAL; + } + } + + if(flags & ECS_CTOR_ILLEGAL) { + ti->hooks.ctor = ecs_ctor_illegal; + } + + if(flags & ECS_DTOR_ILLEGAL) { + ti->hooks.dtor = ecs_dtor_illegal; + } + + if(flags & ECS_COPY_ILLEGAL) { + ti->hooks.copy = ecs_copy_illegal; } + if(flags & ECS_MOVE_ILLEGAL) { + ti->hooks.move = ecs_move_illegal; + } + + if(flags & ECS_COPY_CTOR_ILLEGAL) { + ti->hooks.copy_ctor = ecs_copy_ctor_illegal; + } + + if(ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL) { + ti->hooks.move_ctor = ecs_move_ctor_illegal; + } + + if(ti->hooks.flags & ECS_CTOR_MOVE_DTOR_ILLEGAL) { + ti->hooks.ctor_move_dtor = ecs_move_ctor_illegal; + } + + if(ti->hooks.flags & ECS_MOVE_DTOR_ILLEGAL) { + ti->hooks.ctor_move_dtor = ecs_move_ctor_illegal; + } + + ti->hooks.flags = flags; + error: return; } diff --git a/test/meta/src/RuntimeTypes.c b/test/meta/src/RuntimeTypes.c index c73945f41..0cea4f412 100644 --- a/test/meta/src/RuntimeTypes.c +++ b/test/meta/src/RuntimeTypes.c @@ -1,6 +1,5 @@ #include #include -#include "flecs.h" #define UINT32_PATTERN(x) \ (((uint32_t) (x)) + ((uint32_t) (x) << 8) + ((uint32_t) (x) << 16) + \ @@ -272,7 +271,7 @@ void RuntimeTypes_ctor_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.ctor = ECS_CTOR_ILLEGAL; /* mark constructor for "NestedStruct" as illegal */ + hooks.flags |= ECS_CTOR_ILLEGAL; /* mark constructor for "NestedStruct" as illegal */ ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -280,9 +279,9 @@ void RuntimeTypes_ctor_illegal(void) { const ecs_type_info_t *test_struct_ti = define_test_struct(world); /* TestStruct should have an illegal constructor too: */ - test_assert(test_struct_ti->hooks.ctor == ECS_CTOR_ILLEGAL); - test_assert(test_struct_ti->hooks.copy_ctor == ECS_COPY_CTOR_ILLEGAL); - test_assert(test_struct_ti->hooks.move_ctor == ECS_MOVE_CTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_CTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_COPY_CTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_struct_ti->hooks.dtor == NULL); @@ -347,7 +346,7 @@ void RuntimeTypes_dtor_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.dtor = ECS_DTOR_ILLEGAL; /* mark destructor for "NestedStruct" as illegal */ + hooks.flags |= ECS_DTOR_ILLEGAL; /* mark destructor for "NestedStruct" as illegal */ ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -355,11 +354,10 @@ void RuntimeTypes_dtor_illegal(void) { const ecs_type_info_t *test_struct_ti = define_test_struct(world); /* TestStruct should have an illegal constructor too: */ - test_assert(test_struct_ti->hooks.dtor == ECS_DTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_DTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_struct_ti->hooks.ctor != NULL); - test_assert(test_struct_ti->hooks.ctor != ECS_CTOR_ILLEGAL); test_assert(test_struct_ti->hooks.move == NULL); test_assert(test_struct_ti->hooks.copy == NULL); @@ -439,7 +437,7 @@ void RuntimeTypes_move_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.move = ECS_MOVE_ILLEGAL; /* mark move hook for "NestedStruct" as illegal */ + hooks.flags |= ECS_MOVE_ILLEGAL; /* mark move hook for "NestedStruct" as illegal */ ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -447,12 +445,11 @@ void RuntimeTypes_move_illegal(void) { const ecs_type_info_t *test_struct_ti = define_test_struct(world); /* TestStruct should have an illegal move hook too: */ - test_assert(test_struct_ti->hooks.move == ECS_MOVE_ILLEGAL); - test_assert(test_struct_ti->hooks.move_ctor == ECS_MOVE_CTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_MOVE_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_struct_ti->hooks.ctor != NULL); - test_assert(test_struct_ti->hooks.ctor != ECS_CTOR_ILLEGAL); test_assert(test_struct_ti->hooks.dtor == NULL); test_assert(test_struct_ti->hooks.copy == NULL); @@ -528,7 +525,7 @@ void RuntimeTypes_copy_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.copy = ECS_COPY_ILLEGAL; /* mark copy hook for "NestedStruct" as illegal */ + hooks.flags |= ECS_COPY_ILLEGAL; /* mark copy hook for "NestedStruct" as illegal */ ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -536,12 +533,11 @@ void RuntimeTypes_copy_illegal(void) { const ecs_type_info_t *test_struct_ti = define_test_struct(world); /* TestStruct should have an illegal move hook too: */ - test_assert(test_struct_ti->hooks.copy == ECS_COPY_ILLEGAL); - test_assert(test_struct_ti->hooks.copy_ctor == ECS_COPY_CTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_COPY_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_COPY_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_struct_ti->hooks.ctor != NULL); - test_assert(test_struct_ti->hooks.ctor != ECS_CTOR_ILLEGAL); test_assert(test_struct_ti->hooks.dtor == NULL); test_assert(test_struct_ti->hooks.move == NULL); @@ -698,20 +694,13 @@ void ResourceHandle_copy( * For different tests, it can set specific hooks or not. */ static ecs_entity_t resource_handle; -typedef enum hook_req_t { - HookDefault = 0, /* Hook is a default hook */ - HookForward = 1, /* Hook is set and valid */ - HookIllegal = 2 /* Hook is set and calling it is illegal */ -} hook_req_t; -#define GET_HOOK(req, forward, illegal) ((req) & HookIllegal ? (illegal) : (req & HookForward ? (forward) : NULL)) - static void define_resource_handle( ecs_world_t *world, - hook_req_t ctor_req, - hook_req_t dtor_req, - hook_req_t move_req, - hook_req_t copy_req) + bool ctor, + bool dtor, + bool move, + bool copy) { resource_handle = ecs_struct(world, { .entity = ecs_entity(world, {.name = "ResourceHandle"}), @@ -724,10 +713,14 @@ void define_resource_handle( const ecs_type_info_t *ti = ecs_get_type_info(world, resource_handle); ecs_type_hooks_t hooks = ti->hooks; - hooks.ctor = GET_HOOK(ctor_req, ResourceHandle_ctor, ECS_CTOR_ILLEGAL); - hooks.dtor = GET_HOOK(dtor_req, ResourceHandle_dtor, ECS_DTOR_ILLEGAL); - hooks.move = GET_HOOK(move_req, ResourceHandle_move, ECS_MOVE_ILLEGAL); - hooks.copy = GET_HOOK(copy_req,ResourceHandle_copy, ECS_COPY_ILLEGAL); + if (ctor) + hooks.ctor = ResourceHandle_ctor; + if (dtor) + hooks.dtor = ResourceHandle_dtor; + if (move) + hooks.move = ResourceHandle_move; + if (copy) + hooks.copy = ResourceHandle_copy; ecs_set_hooks_id(world, resource_handle, &hooks); } @@ -788,11 +781,7 @@ void RuntimeTypes_array_ctor(void) { test_int(10, resources_left()); /* Define the Resource with only a constructor hook. */ - define_resource_handle( - world, HookForward, - HookDefault, - HookDefault, - HookDefault); + define_resource_handle(world, true, false, false, false); /* create an array of 3 ResourceHandles */ ecs_array_desc_t desc = {.entity = 0, .type = resource_handle, .count = 3}; @@ -828,7 +817,7 @@ void RuntimeTypes_array_ctor_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.ctor = ECS_CTOR_ILLEGAL; /* mark constructor for "NestedStruct" as illegal */ + hooks.flags |= ECS_CTOR_ILLEGAL; /* mark constructor for "NestedStruct" as illegal */ ecs_set_hooks_id(world, nested_struct, &hooks); /* Define test_arr, as an array of "NestedStruct". @@ -839,9 +828,9 @@ void RuntimeTypes_array_ctor_illegal(void) { const ecs_type_info_t* test_arr_ti = ecs_get_type_info(world, test_arr); /* test_arr should have an illegal constructor too: */ - test_assert(test_arr_ti->hooks.ctor == ECS_CTOR_ILLEGAL); - test_assert(test_arr_ti->hooks.copy_ctor == ECS_COPY_CTOR_ILLEGAL); - test_assert(test_arr_ti->hooks.move_ctor == ECS_MOVE_CTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_CTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_COPY_CTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_arr_ti->hooks.dtor == NULL); @@ -861,11 +850,7 @@ void RuntimeTypes_array_dtor(void) { initialize_resource_ids(10); /* Define the Resource with only a destructor hook. */ - define_resource_handle(world, - HookDefault, - HookForward, - HookDefault, - HookDefault); + define_resource_handle(world, false, true, false, false); /* create an array of ResourceHandle */ ecs_array_desc_t desc = {.entity = 0, .type = resource_handle, .count = 3}; @@ -924,7 +909,7 @@ void RuntimeTypes_array_dtor_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.dtor = ECS_DTOR_ILLEGAL; /* mark destructor for "NestedStruct" as illegal */ + hooks.flags |= ECS_DTOR_ILLEGAL; /* mark destructor for "NestedStruct" as illegal */ ecs_set_hooks_id(world, nested_struct, &hooks); /* Define test_arr, as an array of "NestedStruct". @@ -935,11 +920,10 @@ void RuntimeTypes_array_dtor_illegal(void) { const ecs_type_info_t* test_arr_ti = ecs_get_type_info(world, test_arr); /* test_arr should have an illegal destructor too: */ - test_assert(test_arr_ti->hooks.dtor == ECS_DTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_DTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_arr_ti->hooks.ctor != NULL); - test_assert(test_arr_ti->hooks.ctor != ECS_CTOR_ILLEGAL); test_assert(test_arr_ti->hooks.move == NULL); test_assert(test_arr_ti->hooks.copy == NULL); @@ -977,11 +961,7 @@ void RuntimeTypes_array_move(void) { initialize_resource_ids(10); /* Define the Resource with only a move hook. */ - define_resource_handle(world, - HookDefault, - HookDefault, - HookForward, - HookDefault); + define_resource_handle(world, false, false, true, false); /* create an array of ResourceHandle */ ecs_array_desc_t desc = {.entity = 0, .type = resource_handle, .count = 3}; @@ -1059,7 +1039,7 @@ void RuntimeTypes_array_move_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.move = ECS_MOVE_ILLEGAL; /* mark move hook for "NestedStruct" as illegal */ + hooks.flags |= ECS_MOVE_ILLEGAL; /* mark move hook for "NestedStruct" as illegal */ ecs_set_hooks_id(world, nested_struct, &hooks); /* Define test_arr, as an array of "NestedStruct". @@ -1070,12 +1050,11 @@ void RuntimeTypes_array_move_illegal(void) { const ecs_type_info_t* test_arr_ti = ecs_get_type_info(world, test_arr); /* test_arr should have an illegal move hook too: */ - test_assert(test_arr_ti->hooks.move == ECS_MOVE_ILLEGAL); - test_assert(test_arr_ti->hooks.move_ctor == ECS_MOVE_CTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_MOVE_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_arr_ti->hooks.ctor != NULL); - test_assert(test_arr_ti->hooks.ctor != ECS_CTOR_ILLEGAL); test_assert(test_arr_ti->hooks.dtor == NULL); test_assert(test_arr_ti->hooks.copy == NULL); @@ -1093,11 +1072,7 @@ void RuntimeTypes_array_copy(void) { test_int(10, resources_left()); /* Define the Resource with only a copy hook. */ - define_resource_handle(world, - HookDefault, - HookDefault, - HookDefault, - HookForward); + define_resource_handle(world, false, false, false, true); /* create an array of ResourceHandle */ ecs_array_desc_t desc = {.entity = 0, .type = resource_handle, .count = 3}; @@ -1168,7 +1143,7 @@ void RuntimeTypes_array_copy_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.copy = ECS_COPY_ILLEGAL; /* mark copy hook for "NestedStruct" as illegal */ + hooks.flags |= ECS_COPY_ILLEGAL; /* mark copy hook for "NestedStruct" as illegal */ ecs_set_hooks_id(world, nested_struct, &hooks); /* Define test_arr, as an array of "NestedStruct". @@ -1179,12 +1154,11 @@ void RuntimeTypes_array_copy_illegal(void) { const ecs_type_info_t* test_arr_ti = ecs_get_type_info(world, test_arr); /* test_arr should have an illegal copy hook too: */ - test_assert(test_arr_ti->hooks.copy == ECS_COPY_ILLEGAL); - test_assert(test_arr_ti->hooks.copy_ctor == ECS_COPY_CTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_COPY_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_COPY_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_arr_ti->hooks.ctor != NULL); - test_assert(test_arr_ti->hooks.ctor != ECS_CTOR_ILLEGAL); test_assert(test_arr_ti->hooks.dtor == NULL); test_assert(test_arr_ti->hooks.move == NULL); @@ -1200,11 +1174,7 @@ void RuntimeTypes_vector_lifecycle(void) { initialize_resource_ids(initial_resources); test_int(10, resources_left()); - define_resource_handle(world, - HookForward, - HookForward, - HookForward, - HookForward); + define_resource_handle(world, true, true, true, true); /* create a vector of ResourceHandles */ ecs_vector_desc_t desc = {.entity = 0, .type = resource_handle};