Skip to content

Commit

Permalink
#784 don't require default constructor for deferred emplace
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Aug 22, 2022
1 parent b9b4977 commit f461b4f
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 16 deletions.
23 changes: 17 additions & 6 deletions flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ typedef enum ecs_defer_op_kind_t {
EcsOpAdd,
EcsOpRemove,
EcsOpSet,
EcsOpEmplace,
EcsOpMut,
EcsOpModified,
EcsOpDelete,
Expand Down Expand Up @@ -1618,7 +1619,8 @@ bool flecs_defer_set(
ecs_entity_t component,
ecs_size_t size,
const void *value,
void **value_out);
void **value_out,
bool emplace);

bool flecs_defer_end(
ecs_world_t *world,
Expand Down Expand Up @@ -8138,7 +8140,7 @@ void* ecs_get_mut_id(
void *result;

if (flecs_defer_set(
world, stage, EcsOpMut, entity, id, 0, NULL, &result))
world, stage, EcsOpMut, entity, id, 0, NULL, &result, false))
{
return result;
}
Expand Down Expand Up @@ -8324,7 +8326,9 @@ void* ecs_emplace_id(
ecs_stage_t *stage = flecs_stage_from_world(&world);
void *result;

if (flecs_defer_set(world, stage, EcsOpMut, entity, id, 0, NULL, &result)) {
if (flecs_defer_set(world, stage, EcsOpEmplace, entity, id, 0, NULL,
&result, true))
{
return result;
}

Expand Down Expand Up @@ -8394,7 +8398,7 @@ ecs_entity_t set_ptr_w_id(
}

if (flecs_defer_set(world, stage, EcsOpSet, entity, id,
flecs_utosize(size), ptr, NULL))
flecs_utosize(size), ptr, NULL, false))
{
return entity;
}
Expand Down Expand Up @@ -9510,6 +9514,12 @@ bool flecs_defer_end(
op->id, flecs_itosize(op->is._1.size),
op->is._1.value, true, true);
break;
case EcsOpEmplace:
ecs_emplace_id(world, e, op->id);
set_ptr_w_id(world, e,
op->id, flecs_itosize(op->is._1.size),
op->is._1.value, true, false);
break;
case EcsOpMut:
set_ptr_w_id(world, e,
op->id, flecs_itosize(op->is._1.size),
Expand Down Expand Up @@ -9903,7 +9913,8 @@ bool flecs_defer_set(
ecs_id_t id,
ecs_size_t size,
const void *value,
void **value_out)
void **value_out,
bool emplace)
{
if (flecs_defer_op(world, stage)) {
world->info.set_count ++;
Expand Down Expand Up @@ -9960,7 +9971,7 @@ bool flecs_defer_set(
} else {
ecs_os_memcpy(op->is._1.value, value, size);
}
} else {
} else if (!emplace) {
ecs_xtor_t ctor;
if ((ctor = ti->hooks.ctor)) {
ctor(op->is._1.value, 1, ti);
Expand Down
2 changes: 1 addition & 1 deletion flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

/* Customizable precision for floating point operations (such as time ops) */
#ifndef ecs_float_t
#define ecs_float_t int
#define ecs_float_t float
#endif

/* Customizable precision for time scalar values */
Expand Down
14 changes: 11 additions & 3 deletions src/entity.c
Original file line number Diff line number Diff line change
Expand Up @@ -2911,7 +2911,7 @@ void* ecs_get_mut_id(
void *result;

if (flecs_defer_set(
world, stage, EcsOpMut, entity, id, 0, NULL, &result))
world, stage, EcsOpMut, entity, id, 0, NULL, &result, false))
{
return result;
}
Expand Down Expand Up @@ -3097,7 +3097,9 @@ void* ecs_emplace_id(
ecs_stage_t *stage = flecs_stage_from_world(&world);
void *result;

if (flecs_defer_set(world, stage, EcsOpMut, entity, id, 0, NULL, &result)) {
if (flecs_defer_set(world, stage, EcsOpEmplace, entity, id, 0, NULL,
&result, true))
{
return result;
}

Expand Down Expand Up @@ -3167,7 +3169,7 @@ ecs_entity_t set_ptr_w_id(
}

if (flecs_defer_set(world, stage, EcsOpSet, entity, id,
flecs_utosize(size), ptr, NULL))
flecs_utosize(size), ptr, NULL, false))
{
return entity;
}
Expand Down Expand Up @@ -4283,6 +4285,12 @@ bool flecs_defer_end(
op->id, flecs_itosize(op->is._1.size),
op->is._1.value, true, true);
break;
case EcsOpEmplace:
ecs_emplace_id(world, e, op->id);
set_ptr_w_id(world, e,
op->id, flecs_itosize(op->is._1.size),
op->is._1.value, true, false);
break;
case EcsOpMut:
set_ptr_w_id(world, e,
op->id, flecs_itosize(op->is._1.size),
Expand Down
1 change: 1 addition & 0 deletions src/private_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ typedef enum ecs_defer_op_kind_t {
EcsOpAdd,
EcsOpRemove,
EcsOpSet,
EcsOpEmplace,
EcsOpMut,
EcsOpModified,
EcsOpDelete,
Expand Down
5 changes: 3 additions & 2 deletions src/stage.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,8 @@ bool flecs_defer_set(
ecs_id_t id,
ecs_size_t size,
const void *value,
void **value_out)
void **value_out,
bool emplace)
{
if (flecs_defer_op(world, stage)) {
world->info.set_count ++;
Expand Down Expand Up @@ -356,7 +357,7 @@ bool flecs_defer_set(
} else {
ecs_os_memcpy(op->is._1.value, value, size);
}
} else {
} else if (!emplace) {
ecs_xtor_t ctor;
if ((ctor = ti->hooks.ctor)) {
ctor(op->is._1.value, 1, ti);
Expand Down
3 changes: 2 additions & 1 deletion src/stage.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ bool flecs_defer_set(
ecs_entity_t component,
ecs_size_t size,
const void *value,
void **value_out);
void **value_out,
bool emplace);

bool flecs_defer_end(
ecs_world_t *world,
Expand Down
1 change: 1 addition & 0 deletions test/api/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,7 @@
"set_lifecycle_after_trigger",
"valid_entity_in_dtor_after_delete",
"ctor_w_emplace",
"ctor_w_emplace_defer",
"dtor_on_fini",
"valid_type_in_dtor_on_fini",
"valid_other_type_of_entity_in_dtor_on_fini",
Expand Down
34 changes: 34 additions & 0 deletions test/api/src/ComponentLifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -1293,6 +1293,40 @@ void ComponentLifecycle_ctor_w_emplace() {
ecs_fini(world);
}

void ComponentLifecycle_ctor_w_emplace_defer() {
ecs_world_t* world = ecs_mini();

ECS_COMPONENT(world, Position);

ecs_set_hooks(world, Position, {
.ctor = ecs_ctor(Position)
});

test_int(ctor_position, 0);

ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);

ecs_defer_begin(world);
Position *ptr = ecs_emplace(world, e, Position);
test_assert(ptr != NULL);
test_int(ctor_position, 0);
ptr->x = 10;
ptr->y = 20;
test_assert(!ecs_has(world, e, Position));
test_int(ctor_position, 0);
ecs_defer_end(world);

test_assert(ecs_has(world, e, Position));
test_int(ctor_position, 0);
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);

ecs_fini(world);
}

void ComponentLifecycle_dtor_on_fini() {
ecs_world_t *world = ecs_mini();

Expand Down
7 changes: 6 additions & 1 deletion test/api/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,7 @@ void ComponentLifecycle_allow_lifecycle_overwrite_equal_callbacks(void);
void ComponentLifecycle_set_lifecycle_after_trigger(void);
void ComponentLifecycle_valid_entity_in_dtor_after_delete(void);
void ComponentLifecycle_ctor_w_emplace(void);
void ComponentLifecycle_ctor_w_emplace_defer(void);
void ComponentLifecycle_dtor_on_fini(void);
void ComponentLifecycle_valid_type_in_dtor_on_fini(void);
void ComponentLifecycle_valid_other_type_of_entity_in_dtor_on_fini(void);
Expand Down Expand Up @@ -5040,6 +5041,10 @@ bake_test_case ComponentLifecycle_testcases[] = {
"ctor_w_emplace",
ComponentLifecycle_ctor_w_emplace
},
{
"ctor_w_emplace_defer",
ComponentLifecycle_ctor_w_emplace_defer
},
{
"dtor_on_fini",
ComponentLifecycle_dtor_on_fini
Expand Down Expand Up @@ -10644,7 +10649,7 @@ static bake_test_suite suites[] = {
"ComponentLifecycle",
ComponentLifecycle_setup,
NULL,
68,
69,
ComponentLifecycle_testcases
},
{
Expand Down
3 changes: 2 additions & 1 deletion test/cpp_api/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,8 @@
"on_set_hook_w_entity",
"chained_hooks",
"ctor_w_2_worlds",
"ctor_w_2_worlds_explicit_registration"
"ctor_w_2_worlds_explicit_registration",
"defer_emplace"
]
}, {
"id": "Refs",
Expand Down
26 changes: 26 additions & 0 deletions test/cpp_api/src/ComponentLifecycle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1273,3 +1273,29 @@ void ComponentLifecycle_ctor_w_2_worlds_explicit_registration() {
test_int(Pod::ctor_invoked, 1);
}
}

struct DeferEmplaceTest {
double x, y;

DeferEmplaceTest(double x_, double y_) {
x = x_;
y = y_;
}
};

void ComponentLifecycle_defer_emplace() {
flecs::world ecs;

flecs::entity e = ecs.entity();

ecs.defer_begin();
e.emplace<DeferEmplaceTest>(10.0, 20.0);
test_assert(!e.has<DeferEmplaceTest>());
ecs.defer_end();
test_assert(e.has<DeferEmplaceTest>());

const DeferEmplaceTest *p = e.get<DeferEmplaceTest>();
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
}
7 changes: 6 additions & 1 deletion test/cpp_api/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,7 @@ void ComponentLifecycle_on_set_hook_w_entity(void);
void ComponentLifecycle_chained_hooks(void);
void ComponentLifecycle_ctor_w_2_worlds(void);
void ComponentLifecycle_ctor_w_2_worlds_explicit_registration(void);
void ComponentLifecycle_defer_emplace(void);

// Testsuite 'Refs'
void Refs_get_ref_by_ptr(void);
Expand Down Expand Up @@ -4004,6 +4005,10 @@ bake_test_case ComponentLifecycle_testcases[] = {
{
"ctor_w_2_worlds_explicit_registration",
ComponentLifecycle_ctor_w_2_worlds_explicit_registration
},
{
"defer_emplace",
ComponentLifecycle_defer_emplace
}
};

Expand Down Expand Up @@ -4914,7 +4919,7 @@ static bake_test_suite suites[] = {
"ComponentLifecycle",
NULL,
NULL,
49,
50,
ComponentLifecycle_testcases
},
{
Expand Down

0 comments on commit f461b4f

Please sign in to comment.