Skip to content

Commit 4d93604

Browse files
committed
on_replace: always set both fields, expose other_table for prior-presence check
Updated: set_fields is now always (1 << 2) - 1, ecs_table_has_id call removed. other_table is still set to the pre-operation table so callers that need to know whether the component existed can check it on demand.
1 parent 2ac7322 commit 4d93604

8 files changed

Lines changed: 57 additions & 28 deletions

File tree

distr/flecs.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7031,7 +7031,7 @@ void flecs_invoke_replace_hook(
70317031
it.offset = 0; /* Don't set row because we don't want to offset ptrs */
70327032
it.flags = EcsIterIsValid;
70337033
it.other_table = prev_table;
7034-
it.set_fields = (prev_table != NULL && ecs_table_has_id(world, prev_table, id)) ? 3 : 2;
7034+
it.set_fields = (1 << 2) - 1;
70357035

70367036
ti->hooks.on_replace(&it);
70377037

@@ -18987,6 +18987,8 @@ void ecs_remove_all(
1898718987
flecs_journal_end();
1898818988
}
1898918989

18990+
#include <time.h>
18991+
1899018992
void ecs_os_api_impl(ecs_os_api_t *api);
1899118993

1899218994
static bool ecs_os_api_initialized = false;
@@ -41123,6 +41125,8 @@ void flecs_component_update_childof_depth(
4112341125
flecs_component_update_childof_w_depth(world, cr, new_depth);
4112441126
}
4112541127

41128+
#include <inttypes.h>
41129+
4112641130
ecs_entity_index_page_t* flecs_entity_index_ensure_page(
4112741131
ecs_entity_index_t *index,
4112841132
uint32_t id)
@@ -47839,6 +47843,8 @@ ecs_table_t* ecs_table_find(
4783947843
return flecs_table_ensure(world, &type, false, NULL);
4784047844
}
4784147845

47846+
#include <errno.h>
47847+
4784247848
#ifdef FLECS_HTTP
4784347849

4784447850
#ifndef FLECS_HTTP_IMPL_H
@@ -56789,6 +56795,7 @@ int ecs_meta_from_desc(
5678956795
#endif
5679056796

5679156797
#include <ctype.h>
56798+
#include <inttypes.h>
5679256799

5679356800
#ifdef FLECS_META
5679456801
#ifdef FLECS_QUERY_DSL
@@ -69670,6 +69677,8 @@ void FlecsScriptImport(
6967069677

6967169678
#endif
6967269679

69680+
#include <inttypes.h>
69681+
6967369682
#ifdef FLECS_SCRIPT
6967469683

6967569684
static

distr/flecs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4659,7 +4659,10 @@ struct ecs_type_hooks_t {
46594659
/** Callback that is invoked with the existing and new value before the
46604660
* value is assigned. Invoked after on_add and before on_set. Registering
46614661
* an on_replace hook prevents using operations that return a mutable
4662-
* pointer to the component, like get_mut(), ensure(), and emplace(). */
4662+
* pointer to the component, like get_mut(), ensure(), and emplace().
4663+
* The iterator's other_table field is set to the table of the entity
4664+
* before the operation. To find out whether the component existed before
4665+
* the operation, call ecs_table_has_id() on other_table. */
46634666
ecs_iter_action_t on_replace;
46644667

46654668
/** Callback that is invoked before the on_set/OnSet hooks and observers are

distr/flecs_no_addons.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6966,7 +6966,7 @@ void flecs_invoke_replace_hook(
69666966
it.offset = 0; /* Don't set row because we don't want to offset ptrs */
69676967
it.flags = EcsIterIsValid;
69686968
it.other_table = prev_table;
6969-
it.set_fields = (prev_table != NULL && ecs_table_has_id(world, prev_table, id)) ? 3 : 2;
6969+
it.set_fields = (1 << 2) - 1;
69706970

69716971
ti->hooks.on_replace(&it);
69726972

@@ -18835,6 +18835,8 @@ void ecs_remove_all(
1883518835
flecs_journal_end();
1883618836
}
1883718837

18838+
#include <time.h>
18839+
1883818840
void ecs_os_api_impl(ecs_os_api_t *api);
1883918841

1884018842
static bool ecs_os_api_initialized = false;
@@ -32926,6 +32928,8 @@ void flecs_component_update_childof_depth(
3292632928
flecs_component_update_childof_w_depth(world, cr, new_depth);
3292732929
}
3292832930

32931+
#include <inttypes.h>
32932+
3292932933
ecs_entity_index_page_t* flecs_entity_index_ensure_page(
3293032934
ecs_entity_index_t *index,
3293132935
uint32_t id)
@@ -39642,6 +39646,8 @@ ecs_table_t* ecs_table_find(
3964239646
return flecs_table_ensure(world, &type, false, NULL);
3964339647
}
3964439648

39649+
#include <errno.h>
39650+
3964539651
#ifndef FLECS_SCRIPT_PRIVATE_H
3964639652
#define FLECS_SCRIPT_PRIVATE_H
3964739653

@@ -39807,6 +39813,7 @@ int64_t flecs_parser_errpos(
3980739813
#endif
3980839814

3980939815
#include <ctype.h>
39816+
#include <inttypes.h>
3981039817

3981139818
#ifndef FLECS_META_TYPE_SUPPORT_H
3981239819
#define FLECS_META_TYPE_SUPPORT_H
@@ -40766,6 +40773,8 @@ void ecs_set_os_api_impl(void) {
4076640773

4076740774
#endif
4076840775

40776+
#include <inttypes.h>
40777+
4076940778
#ifndef FLECS_STATS_PRIVATE_H
4077040779
#define FLECS_STATS_PRIVATE_H
4077140780

distr/flecs_no_addons.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4632,7 +4632,10 @@ struct ecs_type_hooks_t {
46324632
/** Callback that is invoked with the existing and new value before the
46334633
* value is assigned. Invoked after on_add and before on_set. Registering
46344634
* an on_replace hook prevents using operations that return a mutable
4635-
* pointer to the component, like get_mut(), ensure(), and emplace(). */
4635+
* pointer to the component, like get_mut(), ensure(), and emplace().
4636+
* The iterator's other_table field is set to the table of the entity
4637+
* before the operation. To find out whether the component existed before
4638+
* the operation, call ecs_table_has_id() on other_table. */
46364639
ecs_iter_action_t on_replace;
46374640

46384641
/** Callback that is invoked before the on_set/OnSet hooks and observers are

include/flecs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,10 @@ struct ecs_type_hooks_t {
10131013
/** Callback that is invoked with the existing and new value before the
10141014
* value is assigned. Invoked after on_add and before on_set. Registering
10151015
* an on_replace hook prevents using operations that return a mutable
1016-
* pointer to the component, like get_mut(), ensure(), and emplace(). */
1016+
* pointer to the component, like get_mut(), ensure(), and emplace().
1017+
* The iterator's other_table field is set to the table of the entity
1018+
* before the operation. To find out whether the component existed before
1019+
* the operation, call ecs_table_has_id() on other_table. */
10171020
ecs_iter_action_t on_replace;
10181021

10191022
/** Callback that is invoked before the on_set/OnSet hooks and observers are

src/component_actions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ void flecs_invoke_replace_hook(
107107
it.offset = 0; /* Don't set row because we don't want to offset ptrs */
108108
it.flags = EcsIterIsValid;
109109
it.other_table = prev_table;
110-
it.set_fields = (prev_table != NULL && ecs_table_has_id(world, prev_table, id)) ? 3 : 2;
110+
it.set_fields = (1 << 2) - 1;
111111

112112
ti->hooks.on_replace(&it);
113113

test/core/src/ComponentLifecycle.c

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4581,11 +4581,10 @@ void ComponentLifecycle_on_replace_other_table_new_entity(void) {
45814581
ecs_set(world, e, Position, {10, 20});
45824582
test_int(ctx.invoked, 1);
45834583

4584-
/* prev_table captured before flecs_ensure: root table, no Position.
4585-
* set_fields=2: bit 0 unset (no old value), bit 1 set (new value). */
4584+
/* prev_table captured before flecs_ensure: root table, no Position. */
45864585
test_assert(ctx.other_table == prev);
4587-
test_assert(!(ctx.set_fields & 1));
4588-
test_assert(ctx.set_fields & 2);
4586+
test_assert(ctx.set_fields == 3);
4587+
test_assert(!ecs_table_has_id(world, ctx.other_table, ecs_id(Position)));
45894588

45904589
ecs_fini(world);
45914590
}
@@ -4612,10 +4611,10 @@ void ComponentLifecycle_on_replace_other_table_existing_entity(void) {
46124611
ecs_set(world, e, Position, {10, 20});
46134612
test_int(ctx.invoked, 1);
46144613

4615-
/* prev_table = {Velocity} before ensure; set_fields=2: Position not yet in prev. */
4614+
/* prev_table = {Velocity} before ensure: Position not yet in prev. */
46164615
test_assert(ctx.other_table == prev);
4617-
test_assert(!(ctx.set_fields & 1));
4618-
test_assert(ctx.set_fields & 2);
4616+
test_assert(ctx.set_fields == 3);
4617+
test_assert(!ecs_table_has_id(world, ctx.other_table, ecs_id(Position)));
46194618

46204619
ecs_fini(world);
46214620
}
@@ -4643,9 +4642,10 @@ void ComponentLifecycle_on_replace_other_table_set_existing(void) {
46434642
ecs_set(world, e, Position, {11, 21});
46444643
test_int(ctx.invoked, 1);
46454644

4646-
/* prev_table = {Position} (unchanged by ensure); set_fields=3: Position in prev. */
4645+
/* prev_table = {Position} (unchanged by ensure): Position in prev. */
46474646
test_assert(ctx.other_table == table_with_pos);
46484647
test_assert(ctx.set_fields == 3);
4648+
test_assert(ecs_table_has_id(world, ctx.other_table, ecs_id(Position)));
46494649

46504650
ecs_fini(world);
46514651
}
@@ -4675,11 +4675,10 @@ void ComponentLifecycle_on_replace_other_table_batched_new_entity(void) {
46754675
ecs_defer_end(world);
46764676
test_int(ctx.invoked, 1);
46774677

4678-
/* Batch flush second-pass: uses start_table (root, no Position).
4679-
* set_fields=2: bit 0 unset because start_table lacks Position. */
4678+
/* Batch flush second-pass: uses start_table (root, no Position). */
46804679
test_assert(ctx.other_table == start_table);
4681-
test_assert(!(ctx.set_fields & 1));
4682-
test_assert(ctx.set_fields & 2);
4680+
test_assert(ctx.set_fields == 3);
4681+
test_assert(!ecs_table_has_id(world, ctx.other_table, ecs_id(Position)));
46834682

46844683
ecs_fini(world);
46854684
}
@@ -4712,6 +4711,7 @@ void ComponentLifecycle_on_replace_other_table_batched_existing(void) {
47124711
test_int(ctx.invoked, 1);
47134712
test_assert(ctx.other_table == table_with_pos);
47144713
test_assert(ctx.set_fields == 3);
4714+
test_assert(ecs_table_has_id(world, ctx.other_table, ecs_id(Position)));
47154715
ecs_defer_end(world);
47164716

47174717
ecs_fini(world);
@@ -4730,16 +4730,15 @@ void ComponentLifecycle_on_replace_other_table_entity_init(void) {
47304730
.ctx = &ctx,
47314731
});
47324732

4733-
/* init_table = r->table before any components added (root, no Position).
4734-
* set_fields=2: bit 0 unset, new add. */
4733+
/* init_table = r->table before any components added (root, no Position). */
47354734
ecs_entity_t e = ecs_entity(world, {
47364735
.set = ecs_values(ecs_value(Position, {10, 20}))
47374736
});
47384737
test_int(ctx.invoked, 1);
47394738

47404739
test_assert(ctx.other_table != ecs_get_table(world, e));
4741-
test_assert(!(ctx.set_fields & 1));
4742-
test_assert(ctx.set_fields & 2);
4740+
test_assert(ctx.set_fields == 3);
4741+
test_assert(!ecs_table_has_id(world, ctx.other_table, ecs_id(Position)));
47434742

47444743
ecs_fini(world);
47454744
}

test/cpp/src/Entity.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6697,10 +6697,10 @@ void Entity_on_replace_other_table_set_new(void) {
66976697
e.set(Position{10, 20});
66986698
test_int(ctx.invoked, 1);
66996699

6700-
/* prev captured before ensure: root table, no Position -> bit 0 unset */
6700+
/* prev captured before ensure: root table, no Position */
67016701
test_assert(ctx.other_table == prev);
6702-
test_assert(!(ctx.set_fields & 1));
6703-
test_assert(ctx.set_fields & 2);
6702+
test_assert(ctx.set_fields == 3);
6703+
test_assert(!ecs_table_has_id(world, ctx.other_table, pos_id));
67046704
}
67056705

67066706
void Entity_on_replace_other_table_set_existing(void) {
@@ -6724,9 +6724,10 @@ void Entity_on_replace_other_table_set_existing(void) {
67246724
e.set(Position{11, 21});
67256725
test_int(ctx.invoked, 1);
67266726

6727-
/* Entity already had Position -> other_table == {Position} table, both bits set */
6727+
/* Entity already had Position -> other_table == {Position} table */
67286728
test_assert(ctx.other_table == table_with_pos);
67296729
test_assert(ctx.set_fields == 3);
6730+
test_assert(ecs_table_has_id(world, ctx.other_table, pos_id));
67306731
}
67316732

67326733
void Entity_on_replace_other_table_assign_new(void) {
@@ -6749,9 +6750,10 @@ void Entity_on_replace_other_table_assign_new(void) {
67496750
e.assign(Position{10, 20});
67506751
test_int(ctx.invoked, 1);
67516752

6752-
/* assign requires component to already exist; other_table == {Position}, both bits set */
6753+
/* assign requires component to already exist; other_table == {Position} */
67536754
test_assert(ctx.other_table == table_with_pos);
67546755
test_assert(ctx.set_fields == 3);
6756+
test_assert(ecs_table_has_id(world, ctx.other_table, pos_id));
67556757
}
67566758

67576759
void Entity_on_replace_other_table_assign_existing(void) {
@@ -6775,9 +6777,10 @@ void Entity_on_replace_other_table_assign_existing(void) {
67756777
e.assign(Position{11, 21});
67766778
test_int(ctx.invoked, 1);
67776779

6778-
/* Replacing existing via assign: other_table == {Position}, both bits set */
6780+
/* Replacing existing via assign: other_table == {Position} */
67796781
test_assert(ctx.other_table == table_with_pos);
67806782
test_assert(ctx.set_fields == 3);
6783+
test_assert(ecs_table_has_id(world, ctx.other_table, pos_id));
67816784
}
67826785

67836786
void Entity_set_lvalue_to_mutable(void) {

0 commit comments

Comments
 (0)