104 lines
2.4 KiB
C
104 lines
2.4 KiB
C
/**
|
|
* @file datastructures/allocator.c
|
|
* @brief Allocator for any size.
|
|
*
|
|
* Allocators create a block allocator for each requested size.
|
|
*/
|
|
|
|
#include "../private_api.h"
|
|
|
|
static
|
|
ecs_size_t flecs_allocator_size(
|
|
ecs_size_t size)
|
|
{
|
|
return ECS_ALIGN(size, 16);
|
|
}
|
|
|
|
static
|
|
ecs_size_t flecs_allocator_size_hash(
|
|
ecs_size_t size)
|
|
{
|
|
return size >> 4;
|
|
}
|
|
|
|
void flecs_allocator_init(
|
|
ecs_allocator_t *a)
|
|
{
|
|
flecs_ballocator_init_n(&a->chunks, ecs_block_allocator_t,
|
|
FLECS_SPARSE_PAGE_SIZE);
|
|
flecs_sparse_init_t(&a->sizes, NULL, &a->chunks, ecs_block_allocator_t);
|
|
}
|
|
|
|
void flecs_allocator_fini(
|
|
ecs_allocator_t *a)
|
|
{
|
|
int32_t i = 0, count = flecs_sparse_count(&a->sizes);
|
|
for (i = 0; i < count; i ++) {
|
|
ecs_block_allocator_t *ba = flecs_sparse_get_dense_t(
|
|
&a->sizes, ecs_block_allocator_t, i);
|
|
flecs_ballocator_fini(ba);
|
|
}
|
|
flecs_sparse_fini(&a->sizes);
|
|
flecs_ballocator_fini(&a->chunks);
|
|
}
|
|
|
|
ecs_block_allocator_t* flecs_allocator_get(
|
|
ecs_allocator_t *a,
|
|
ecs_size_t size)
|
|
{
|
|
ecs_assert(size >= 0, ECS_INTERNAL_ERROR, NULL);
|
|
if (!size) {
|
|
return NULL;
|
|
}
|
|
|
|
ecs_assert(a != NULL, ECS_INTERNAL_ERROR, NULL);
|
|
ecs_assert(size <= flecs_allocator_size(size), ECS_INTERNAL_ERROR, NULL);
|
|
size = flecs_allocator_size(size);
|
|
ecs_size_t hash = flecs_allocator_size_hash(size);
|
|
ecs_block_allocator_t *result = flecs_sparse_get_any_t(&a->sizes,
|
|
ecs_block_allocator_t, (uint32_t)hash);
|
|
|
|
if (!result) {
|
|
result = flecs_sparse_ensure_fast_t(&a->sizes,
|
|
ecs_block_allocator_t, (uint32_t)hash);
|
|
flecs_ballocator_init(result, size);
|
|
}
|
|
|
|
ecs_assert(result->data_size == size, ECS_INTERNAL_ERROR, NULL);
|
|
|
|
return result;
|
|
}
|
|
|
|
char* flecs_strdup(
|
|
ecs_allocator_t *a,
|
|
const char* str)
|
|
{
|
|
ecs_size_t len = ecs_os_strlen(str);
|
|
char *result = flecs_alloc_n(a, char, len + 1);
|
|
ecs_os_memcpy(result, str, len + 1);
|
|
return result;
|
|
}
|
|
|
|
void flecs_strfree(
|
|
ecs_allocator_t *a,
|
|
char* str)
|
|
{
|
|
ecs_size_t len = ecs_os_strlen(str);
|
|
flecs_free_n(a, char, len + 1, str);
|
|
}
|
|
|
|
void* flecs_dup(
|
|
ecs_allocator_t *a,
|
|
ecs_size_t size,
|
|
const void *src)
|
|
{
|
|
ecs_block_allocator_t *ba = flecs_allocator_get(a, size);
|
|
if (ba) {
|
|
void *dst = flecs_balloc(ba);
|
|
ecs_os_memcpy(dst, src, size);
|
|
return dst;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|