/** * @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; } }