From b6179af210b0ed92224506dce0978c20d8d6fba7 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Fri, 24 Mar 2023 22:51:12 +0100 Subject: Custom alloc dispatch mode --- CMakeLists.txt | 12 ++++++++---- source/kit/allocator.c | 48 ++++++++++++++++++++++++++++++++++++---------- source/kit/allocator.h | 22 ++++++++++++++++----- source/kit/dynamic_array.c | 13 +++++++------ source/kit/dynamic_array.h | 10 +++++----- source/kit/input_buffer.c | 8 +++----- source/kit/input_stream.c | 7 ++++--- source/kit/thread.posix.c | 9 +++++---- 8 files changed, 87 insertions(+), 42 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 770e79d..6bd3356 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,10 +6,10 @@ if(NOT DEFINED CMAKE_BUILD_PARALLEL_LEVEL) set(CMAKE_BUILD_PARALLEL_LEVEL 4 CACHE STRING "" FORCE) endif() -option(KIT_ENABLE_TESTING "Enable testing" ON) - -option(KIT_DISABLE_SYSTEM_MALLOC "Disable system memory allocator" OFF) -option(KIT_DISABLE_SYSTEM_THREADS "Disable system threads" OFF) +option(KIT_DISABLE_SYSTEM_MALLOC "Disable system memory allocator" OFF) +option(KIT_DISABLE_SYSTEM_THREADS "Disable system threads" OFF) +option(KIT_ENABLE_CUSTOM_ALLOC_DISPATCH "Enable custom allocator dispatch" OFF) +option(KIT_ENABLE_TESTING "Enable testing" ON) project( kit @@ -114,6 +114,10 @@ if(KIT_DISABLE_SYSTEM_THREADS) target_compile_definitions(kit PUBLIC KIT_DISABLE_SYSTEM_THREADS) endif() +if(KIT_ENABLE_CUSTOM_ALLOC_DISPATCH) + target_compile_definitions(kit PUBLIC KIT_ENABLE_CUSTOM_ALLOC_DISPATCH) +endif() + if(NOT KIT_DISABLE_SYSTEM_THREADS) find_package(Threads REQUIRED) target_link_libraries(kit PUBLIC Threads::Threads) diff --git a/source/kit/allocator.c b/source/kit/allocator.c index 4a31d2f..b07cca8 100644 --- a/source/kit/allocator.c +++ b/source/kit/allocator.c @@ -1,26 +1,54 @@ #include "allocator.h" +#include + #ifndef KIT_DISABLE_SYSTEM_MALLOC # include #endif -static void *allocate(void *_, size_t size) { +static void *allocate(int request, void *state, ptrdiff_t size, + ptrdiff_t previous_size, void *pointer) { #ifndef KIT_DISABLE_SYSTEM_MALLOC - return malloc(size); + switch (request) { + case KIT_ALLOCATE: + assert(previous_size == 0); + assert(pointer == NULL); + return malloc(size); + + case KIT_DEALLOCATE: + assert(size == 0); + assert(pointer != NULL); + free(pointer); + return NULL; + + case KIT_REALLOCATE: + /* FIXME + * Not implemented. + */ + assert(0); + return NULL; + + default: assert(0); + } #else - return NULL; + assert(0); #endif + return NULL; } -static void deallocate(void *_, void *pointer) { -#ifndef KIT_DISABLE_SYSTEM_MALLOC - free(pointer); -#endif +#ifndef KIT_ENABLE_CUSTOM_ALLOC_DISPATCH +void *kit_alloc_dispatch(kit_allocator_t alloc, int request, + ptrdiff_t size, ptrdiff_t previous_size, + void *pointer) { + assert(alloc.allocate != NULL); + if (alloc.allocate == NULL) + return NULL; + return alloc.allocate(request, alloc.state, size, previous_size, + pointer); } +#endif kit_allocator_t kit_alloc_default(void) { - kit_allocator_t alloc = { .state = NULL, - .allocate = allocate, - .deallocate = deallocate }; + kit_allocator_t alloc = { .state = NULL, .allocate = allocate }; return alloc; } diff --git a/source/kit/allocator.h b/source/kit/allocator.h index 73eaa38..7126901 100644 --- a/source/kit/allocator.h +++ b/source/kit/allocator.h @@ -7,15 +7,27 @@ extern "C" { #endif -typedef void *(*kit_allocate_fn)(void *state, size_t size); -typedef void (*kit_deallocate_fn)(void *state, void *pointer); +enum { KIT_ALLOCATE, KIT_DEALLOCATE, KIT_REALLOCATE }; + +typedef void *(*kit_allocate_fn)(int request, void *state, + ptrdiff_t size, + ptrdiff_t previous_size, + void *pointer); typedef struct { - void *state; - kit_allocate_fn allocate; - kit_deallocate_fn deallocate; + void *state; + kit_allocate_fn allocate; } kit_allocator_t; +/* Application should implement this function if custom allocator + * dispatch is enabled. + * + * See KIT_ENABLE_CUSTOM_ALLOC_DISPATCH + */ +void *kit_alloc_dispatch(kit_allocator_t alloc, int request, + ptrdiff_t size, ptrdiff_t previous_size, + void *pointer); + kit_allocator_t kit_alloc_default(void); #ifdef __cplusplus diff --git a/source/kit/dynamic_array.c b/source/kit/dynamic_array.c index 1829c45..d3eaf29 100644 --- a/source/kit/dynamic_array.c +++ b/source/kit/dynamic_array.c @@ -9,12 +9,12 @@ void kit_da_init(kit_da_void_t *array, ptrdiff_t element_size, assert(element_size > 0); assert(size >= 0); assert(alloc.allocate != NULL); - assert(alloc.deallocate != NULL); memset(array, 0, sizeof(kit_da_void_t)); if (size > 0) - array->values = alloc.allocate(alloc.state, element_size * size); + array->values = kit_alloc_dispatch(alloc, KIT_ALLOCATE, + element_size * size, 0, NULL); if (array->values != NULL) { array->capacity = size; @@ -45,15 +45,16 @@ void kit_da_resize(kit_da_void_t *array, ptrdiff_t element_size, ptrdiff_t capacity = eval_capacity(array->capacity, size); assert(array->alloc.allocate != NULL); - assert(array->alloc.deallocate != NULL); - void *bytes = array->alloc.allocate(array->alloc.state, - element_size * capacity); + void *bytes = kit_alloc_dispatch( + array->alloc, KIT_ALLOCATE, element_size * capacity, 0, NULL); + if (bytes != NULL) { if (array->size > 0) memcpy(bytes, array->values, element_size * array->size); if (array->values != NULL) - array->alloc.deallocate(array->alloc.state, array->values); + kit_alloc_dispatch(array->alloc, KIT_DEALLOCATE, 0, 0, + array->values); array->capacity = capacity; array->size = size; array->values = bytes; diff --git a/source/kit/dynamic_array.h b/source/kit/dynamic_array.h index b571c75..35dddb3 100644 --- a/source/kit/dynamic_array.h +++ b/source/kit/dynamic_array.h @@ -44,11 +44,11 @@ void kit_da_resize(kit_da_void_t *array, ptrdiff_t element_size, /* Destroy dynamic array. */ -#define KIT_DA_DESTROY(array_) \ - do { \ - if ((array_).values != NULL) \ - (array_).alloc.deallocate((array_).alloc.state, \ - (array_).values); \ +#define KIT_DA_DESTROY(array_) \ + do { \ + if ((array_).values != NULL) \ + kit_alloc_dispatch((array_).alloc, KIT_DEALLOCATE, 0, 0, \ + (array_).values); \ } while (0) /* Resize dynamic array. diff --git a/source/kit/input_buffer.c b/source/kit/input_buffer.c index 8ac7755..1ea9e94 100644 --- a/source/kit/input_buffer.c +++ b/source/kit/input_buffer.c @@ -13,8 +13,8 @@ typedef struct { static internal_buffer_t *buf_init(kit_is_handle_t upstream, kit_allocator_t alloc) { assert(alloc.allocate != NULL); - internal_buffer_t *const buf = alloc.allocate(alloc.state, - sizeof *buf); + internal_buffer_t *const buf = kit_alloc_dispatch( + alloc, KIT_ALLOCATE, sizeof *buf, 0, NULL); if (buf != NULL) { memset(buf, 0, sizeof *buf); @@ -46,9 +46,7 @@ static void buf_release(void *p) { if (--buf->ref_count == 0) { DA_DESTROY(buf->data); - - assert(buf->alloc.deallocate != NULL); - buf->alloc.deallocate(buf->alloc.state, buf); + kit_alloc_dispatch(buf->alloc, KIT_DEALLOCATE, 0, 0, buf); } } diff --git a/source/kit/input_stream.c b/source/kit/input_stream.c index 89be44c..df31c1d 100644 --- a/source/kit/input_stream.c +++ b/source/kit/input_stream.c @@ -41,8 +41,9 @@ kit_is_handle_t kit_is_wrap_string(kit_str_t string, kit_allocator_t alloc) { kit_is_handle_t in; memset(&in, 0, sizeof in); - kit_is_state_str_t *state = (kit_is_state_str_t *) alloc.allocate( - alloc.state, sizeof(kit_is_state_str_t)); + kit_is_state_str_t *state = (kit_is_state_str_t *) + kit_alloc_dispatch(alloc, KIT_ALLOCATE, + sizeof(kit_is_state_str_t), 0, NULL); if (state != NULL) { memset(state, 0, sizeof *state); state->type = input_stream_str; @@ -57,5 +58,5 @@ kit_is_handle_t kit_is_wrap_string(kit_str_t string, void kit_is_destroy(kit_is_handle_t in) { kit_is_state_basic_t *basic = (kit_is_state_basic_t *) in.state; if (basic != NULL) - basic->alloc.deallocate(basic->alloc.state, in.state); + kit_alloc_dispatch(basic->alloc, KIT_DEALLOCATE, 0, 0, in.state); } diff --git a/source/kit/thread.posix.c b/source/kit/thread.posix.c index 192dca4..ee5d439 100644 --- a/source/kit/thread.posix.c +++ b/source/kit/thread.posix.c @@ -44,7 +44,7 @@ typedef struct { static void *impl_thrd_routine(void *p) { impl_thrd_param_t pack = *((impl_thrd_param_t *) p); - pack.alloc.deallocate(pack.alloc.state, p); + kit_alloc_dispatch(pack.alloc, KIT_DEALLOCATE, 0, 0, p); return (void *) (intptr_t) pack.func(pack.arg); } @@ -214,8 +214,9 @@ int thrd_create_with_stack(thrd_t *thr, thrd_start_t func, void *arg, attr_p = &attr; } kit_allocator_t alloc = kit_alloc_default(); - pack = (impl_thrd_param_t *) alloc.allocate( - alloc.state, sizeof(impl_thrd_param_t)); + + pack = (impl_thrd_param_t *) kit_alloc_dispatch( + alloc, KIT_ALLOCATE, sizeof(impl_thrd_param_t), 0, NULL); if (!pack) { if (attr_p) pthread_attr_destroy(attr_p); @@ -225,7 +226,7 @@ int thrd_create_with_stack(thrd_t *thr, thrd_start_t func, void *arg, pack->arg = arg; pack->alloc = alloc; if (pthread_create(thr, attr_p, impl_thrd_routine, pack) != 0) { - alloc.deallocate(alloc.state, pack); + kit_alloc_dispatch(alloc, KIT_DEALLOCATE, 0, 0, pack); if (attr_p) pthread_attr_destroy(attr_p); return thrd_error; -- cgit v1.2.3