Skip to content

Commit

Permalink
Implement stack allocator for deferred ops
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Jul 3, 2022
1 parent c8b642d commit 1b3473c
Show file tree
Hide file tree
Showing 14 changed files with 396 additions and 104 deletions.
205 changes: 170 additions & 35 deletions flecs.c

Large diffs are not rendered by default.

49 changes: 17 additions & 32 deletions flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -15292,7 +15292,7 @@ template <typename T, if_t< is_flecs_constructible<T>::value > = 0>
inline void set(world_t *world, entity_t entity, T&& value, ecs_id_t id) {
ecs_assert(_::cpp_type<T>::size() != 0, ECS_INVALID_PARAMETER, NULL);

T& dst = *static_cast<T*>(ecs_get_mut_id(world, entity, id, NULL));
T& dst = *static_cast<T*>(ecs_get_mut_id(world, entity, id));
dst = FLECS_MOV(value);

ecs_modified_id(world, entity, id);
Expand All @@ -15303,7 +15303,7 @@ template <typename T, if_t< is_flecs_constructible<T>::value > = 0>
inline void set(world_t *world, entity_t entity, const T& value, ecs_id_t id) {
ecs_assert(_::cpp_type<T>::size() != 0, ECS_INVALID_PARAMETER, NULL);

T& dst = *static_cast<T*>(ecs_get_mut_id(world, entity, id, NULL));
T& dst = *static_cast<T*>(ecs_get_mut_id(world, entity, id));
dst = value;

ecs_modified_id(world, entity, id);
Expand All @@ -15314,11 +15314,7 @@ template <typename T, if_not_t< is_flecs_constructible<T>::value > = 0>
inline void set(world_t *world, entity_t entity, T&& value, ecs_id_t id) {
ecs_assert(_::cpp_type<T>::size() != 0, ECS_INVALID_PARAMETER, NULL);

bool is_new = false;
T& dst = *static_cast<T*>(ecs_get_mut_id(world, entity, id, &is_new));

/* If type is not constructible get_mut should assert on new values */
ecs_assert(!is_new, ECS_INTERNAL_ERROR, NULL);
T& dst = *static_cast<T*>(ecs_get_mut_id(world, entity, id));

dst = FLECS_MOV(value);

Expand All @@ -15330,11 +15326,7 @@ template <typename T, if_not_t< is_flecs_constructible<T>::value > = 0>
inline void set(world_t *world, id_t entity, const T& value, id_t id) {
ecs_assert(_::cpp_type<T>::size() != 0, ECS_INVALID_PARAMETER, NULL);

bool is_new = false;
T& dst = *static_cast<T*>(ecs_get_mut_id(world, entity, id, &is_new));

/* If type is not constructible get_mut should assert on new values */
ecs_assert(!is_new, ECS_INTERNAL_ERROR, NULL);
T& dst = *static_cast<T*>(ecs_get_mut_id(world, entity, id));
dst = value;

ecs_modified_id(world, entity, id);
Expand Down Expand Up @@ -18598,15 +18590,13 @@ struct entity : entity_builder<entity>
* will be copied to the entity before this function returns.
*
* @tparam T The component to get.
* @param is_added If provided, this parameter will be set to true if the component was added.
* @return Pointer to the component value.
*/
template <typename T>
T* get_mut(bool *is_added = nullptr) const {
T* get_mut() const {
auto comp_id = _::cpp_type<T>::id(m_world);
ecs_assert(_::cpp_type<T>::size() != 0, ECS_INVALID_PARAMETER, NULL);
return static_cast<T*>(
ecs_get_mut_id(m_world, m_id, comp_id, is_added));
return static_cast<T*>(ecs_get_mut_id(m_world, m_id, comp_id));
}

/** Get mutable component value (untyped).
Expand All @@ -18616,11 +18606,10 @@ struct entity : entity_builder<entity>
* will be copied to the entity before this function returns.
*
* @param comp The component to get.
* @param is_added If provided, this parameter will be set to true if the component was added.
* @return Pointer to the component value.
*/
void* get_mut(entity_t comp, bool *is_added = nullptr) const {
return ecs_get_mut_id(m_world, m_id, comp, is_added);
void* get_mut(entity_t comp) const {
return ecs_get_mut_id(m_world, m_id, comp);
}

/** Get mutable pointer for a pair.
Expand All @@ -18630,9 +18619,8 @@ struct entity : entity_builder<entity>
* @tparam Object the object type.
*/
template <typename Relation, typename Object>
Relation* get_mut(bool *is_added = nullptr) const {
return this->get_mut<Relation>(
_::cpp_type<Object>::id(m_world), is_added);
Relation* get_mut() const {
return this->get_mut<Relation>(_::cpp_type<Object>::id(m_world));
}

/** Get mutable pointer for a pair.
Expand All @@ -18642,12 +18630,11 @@ struct entity : entity_builder<entity>
* @param object the object.
*/
template <typename Relation>
Relation* get_mut(entity_t object, bool *is_added = nullptr) const {
Relation* get_mut(entity_t object) const {
auto comp_id = _::cpp_type<Relation>::id(m_world);
ecs_assert(_::cpp_type<Relation>::size() != 0, ECS_INVALID_PARAMETER, NULL);
return static_cast<Relation*>(
ecs_get_mut_id(m_world, m_id,
ecs_pair(comp_id, object), is_added));
ecs_get_mut_id(m_world, m_id, ecs_pair(comp_id, object)));
}

/** Get mutable pointer for a pair (untyped).
Expand All @@ -18657,9 +18644,8 @@ struct entity : entity_builder<entity>
* @param relation the relation.
* @param object the object.
*/
void* get_mut(entity_t relation, entity_t object, bool *is_added = nullptr) const {
return ecs_get_mut_id(m_world, m_id,
ecs_pair(relation, object), is_added);
void* get_mut(entity_t relation, entity_t object) const {
return ecs_get_mut_id(m_world, m_id, ecs_pair(relation, object));
}

/** Get mutable pointer for the object from a pair.
Expand All @@ -18669,12 +18655,11 @@ struct entity : entity_builder<entity>
* @param relation the relation.
*/
template <typename Object>
Object* get_mut_w_object(entity_t relation, bool *is_added = nullptr) const {
Object* get_mut_w_object(entity_t relation) const {
auto comp_id = _::cpp_type<Object>::id(m_world);
ecs_assert(_::cpp_type<Object>::size() != 0, ECS_INVALID_PARAMETER, NULL);
return static_cast<Object*>(
ecs_get_mut_id(m_world, m_id,
ecs_pair(relation, comp_id), is_added));
ecs_get_mut_id(m_world, m_id, ecs_pair(relation, comp_id)));
}

/** Signal that component was modified.
Expand Down Expand Up @@ -19250,7 +19235,7 @@ struct entity_with_invoker_impl<arg_list<Args ...>> {
size_t i = 0;
DummyArray dummy ({
(ptrs[i ++] = ecs_get_mut_id(world, e,
_::cpp_type<Args>().id(world), NULL), 0)...
_::cpp_type<Args>().id(world)), 0)...
});

return true;
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ flecs_src = files(
'src/datastructures/hash.c',
'src/datastructures/hashmap.c',
'src/datastructures/map.c',
'src/datastructures/stack_allocator.c',
'src/datastructures/name_index.c',
'src/datastructures/qsort.c',
'src/datastructures/sparse.c',
Expand Down
82 changes: 82 additions & 0 deletions src/datastructures/stack_allocator.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "../private_api.h"

#define FLECS_STACK_PAGE_OFFSET ECS_ALIGN(ECS_SIZEOF(ecs_stack_page_t), 16)

static
ecs_stack_page_t* flecs_stack_page_new(void) {
ecs_stack_page_t *result = ecs_os_malloc(
FLECS_STACK_PAGE_OFFSET + ECS_STACK_PAGE_SIZE);
result->data = ECS_OFFSET(result, FLECS_STACK_PAGE_OFFSET);
result->next = NULL;
return result;
}

void* flecs_stack_alloc(
ecs_stack_t *stack,
ecs_size_t size,
ecs_size_t align)
{
ecs_stack_page_t *page = stack->cur;
if (page == &stack->first && !page->data) {
page->data = ecs_os_malloc(ECS_STACK_PAGE_SIZE);
}

ecs_size_t sp = ECS_ALIGN(page->sp, align);
ecs_size_t next_sp = sp + size;

if (next_sp > ECS_STACK_PAGE_SIZE) {
if (size > ECS_STACK_PAGE_SIZE) {
return ecs_os_malloc(size); /* Too large for page */
}

if (page->next) {
page = page->next;
} else {
page = page->next = flecs_stack_page_new();
}
sp = 0;
next_sp = size;
stack->cur = page;
}

page->sp = next_sp;

return ECS_OFFSET(page->data, sp);
}

void flecs_stack_free(
void *ptr,
ecs_size_t size)
{
if (size > ECS_STACK_PAGE_SIZE) {
ecs_os_free(ptr);
}
}

void flecs_stack_reset(
ecs_stack_t *stack)
{
stack->cur = &stack->first;
}

void flecs_stack_init(
ecs_stack_t *stack)
{
ecs_os_zeromem(stack);
stack->cur = &stack->first;
stack->first.data = NULL;
}

void flecs_stack_fini(
ecs_stack_t *stack)
{
ecs_stack_page_t *next, *cur = &stack->first;
do {
next = cur->next;
if (cur == &stack->first) {
ecs_os_free(cur->data);
} else {
ecs_os_free(cur);
}
} while ((cur = next));
}
27 changes: 27 additions & 0 deletions src/datastructures/stack_allocator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @file stack_allocator.h
* @brief Data structure used for temporary small allocations.
*/

#ifndef FLECS_STACK_ALLOCATOR_H
#define FLECS_STACK_ALLOCATOR_H

void flecs_stack_init(
ecs_stack_t *stack);

void flecs_stack_fini(
ecs_stack_t *stack);

void* flecs_stack_alloc(
ecs_stack_t *stack,
ecs_size_t size,
ecs_size_t align);

void flecs_stack_free(
void *ptr,
ecs_size_t size);

void flecs_stack_reset(
ecs_stack_t *stack);

#endif
Loading

0 comments on commit 1b3473c

Please sign in to comment.