From ccbe41c269e2324616e28ad467af23ae4822b0c3 Mon Sep 17 00:00:00 2001 From: VegOwOtenks Date: Mon, 14 Oct 2024 12:31:58 +0200 Subject: [PATCH] Implemented TracingHeap_Destroy and TraceNextN --- src/CMakeLists.txt | 1 + src/TracingHeap/TracingHeap.c | 119 +++++++++++++++++++++++++++++----- src/TracingHeap/TracingHeap.h | 30 +++++++-- 3 files changed, 127 insertions(+), 23 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c6e0ec..1d37fc2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,3 +18,4 @@ add_subdirectory(./regex) add_subdirectory(./QuadTree) add_subdirectory(./BinaryTree) add_subdirectory(./Subprocess) +add_subdirectory(./TracingHeap) diff --git a/src/TracingHeap/TracingHeap.c b/src/TracingHeap/TracingHeap.c index 3eeb20a..bab34e4 100644 --- a/src/TracingHeap/TracingHeap.c +++ b/src/TracingHeap/TracingHeap.c @@ -2,14 +2,19 @@ #include "../pointers/pointers.h" -int TracingHeap_Create(TracingHeap* self, ReferenceTracingFunction tracing_function, allocator_t* allocator) +int TracingHeap_Create(TracingHeap* self, allocator_t* allocator) { if (self == NULL) { return EDESTADDRREQ; } + if (1==0 + || self->config.trace_data == NULL + || self->config.destructor == NULL + || self->config.size_query == NULL) { + return EBADSTATE; + } self->allocator = allocator; - self->tracing_function = tracing_function; self->objects = NULL; self->black_objects = NULL; @@ -22,13 +27,23 @@ int TracingHeap_Create(TracingHeap* self, ReferenceTracingFunction tracing_funct return EXIT_SUCCESS; } +static void _TracingHeap_ForceDestroyObject(TracingHeap* self, TracingObject* object) +{ + self->config.destructor(self->config.destructor_context, object->data); + size_t allocated_size = self->config.size_query(self->config.size_query_context, object->data); + Allocator_Free(self->allocator, object, allocated_size); +} + void TracingHeap_Destroy(TracingHeap* self) { if (self == NULL) { return; } - // TODO: Deallocate all objects + for (TracingObject* object = self->objects; object != NULL; object = object->global_next) { + _TracingHeap_ForceDestroyObject(self, object); + } + memset(self, 0, sizeof(*self)); } @@ -111,7 +126,7 @@ int TracingHeap_AddTracingRoot(TracingHeap* self, void* data) return EXIT_SUCCESS; } -int TracingHeap_TraceOnce(TracingHeap* self) +int TracingHeap_TraceNext(TracingHeap* self) { if (self == NULL) { return EDESTADDRREQ; @@ -123,8 +138,8 @@ int TracingHeap_TraceOnce(TracingHeap* self) TracingObject* trace_object = _TracingHeap_PopColorList(self, TRACINGCOLOR_GREY); - int tracing_code = self->tracing_function( - self->tracing_function_context, + int tracing_code = self->config.trace_data( + self->config.trace_context, trace_object->data, _TracingHeap_TraceReferenceCallback, self @@ -138,6 +153,81 @@ int TracingHeap_TraceOnce(TracingHeap* self) return EXIT_SUCCESS; } +size_t TracingHeap_TraceNextN(TracingHeap* self, size_t n) +{ + for (size_t i = 0; i < n; i++) { + if (TracingHeap_TraceNext(self)) { + return i; + } + } + + return n; +} + +static int _TracingHeap_DestroyObject(TracingHeap* self, TracingObject* unreachable_object) +{ + int destructor_code = self->config.destructor(self->config.destructor_context, unreachable_object->data); + if (destructor_code) { + return destructor_code; + } + + size_t allocated_size = self->config.size_query(self->config.size_query_context, unreachable_object->data); + + Allocator_Free(self->allocator, unreachable_object, allocated_size); + + return EXIT_SUCCESS; +} + +int TracingHeap_BeginTrace(TracingHeap* self) +{ + if (self == NULL) { + return EDESTADDRREQ; + } + if (self->grey_objects != NULL) { + return EBADSTATE; + } + if (*_TracingHeap_ColorListStart(self, self->unreachable_color) == NULL) { + return EBADSTATE; + } + + // swap reachable and unreachable color + // xor swap algorithm!! + self->reachable_color = self->reachable_color ^ self->unreachable_color; + self->unreachable_color = self->unreachable_color ^ self->reachable_color; + self->reachable_color = self->reachable_color ^ self->unreachable_color; + + return EXIT_SUCCESS; +} + +int TracingHeap_EndTrace(TracingHeap* self) +{ + if (self == NULL) { + return EDESTADDRREQ; + } + if (self->grey_objects != NULL) { + return EBADSTATE; + } + + TracingObject** unreachable_list = _TracingHeap_ColorListStart(self, self->unreachable_color); + TracingObject* unreachable_object = *unreachable_list; + + while (unreachable_object != NULL) { + TracingObject* next_unreachable = unreachable_object->global_next; + + if (_TracingHeap_DestroyObject(self, unreachable_object)) { + *unreachable_list = unreachable_object; + unreachable_object->global_prev = NULL; + return ECANCELED; + } + + unreachable_object = next_unreachable; + } + + *unreachable_list = NULL; + + return EXIT_SUCCESS; +} + void* TracingHeap_Allocate(TracingHeap* self, size_t bytes) { if (self == NULL) { @@ -151,19 +241,16 @@ void* TracingHeap_Allocate(TracingHeap* self, size_t bytes) object->color = self->reachable_color; - if (self->reachable_color == TRACINGCOLOR_WHITE) { - object->color_next = self->white_objects; - self->white_objects = object; - } else { - // black - object->color_next = self->black_objects; - self->black_objects = object; - } + TracingObject** reachable_list_start = _TracingHeap_ColorListStart(self, self->reachable_color); + object->color_next = *reachable_list_start; + *reachable_list_start = object; object->color_prev = NULL; - object->global_next = self->objects; - self->objects = object; + object->global_next = self->objects; // link before global object list + object->global_prev = NULL; // no previous object + self->objects->global_prev = object; // link first object via previous link + self->objects = object; // insert into linked list return object->data; } diff --git a/src/TracingHeap/TracingHeap.h b/src/TracingHeap/TracingHeap.h index 0ea6d00..fbc1c92 100644 --- a/src/TracingHeap/TracingHeap.h +++ b/src/TracingHeap/TracingHeap.h @@ -13,6 +13,7 @@ enum TracingColor { typedef struct TracingObject { struct TracingObject* global_next; + struct TracingObject* global_prev; struct TracingObject* color_next; struct TracingObject* color_prev; enum TracingColor color; @@ -21,8 +22,21 @@ typedef struct TracingObject { alignas(void*) char data[]; } TracingObject; -typedef int (*TraceReferenceCallback) (void* context, void* reference); -typedef int (*ReferenceTracingFunction) (void* context, void* object, TraceReferenceCallback trace_callback, void* callback_context); +typedef int (*TracingHeapVisit) (void* context, void* reference); +typedef int (*TracingHeapTraceData) (void* context, void* data, TracingHeapVisit trace_callback, void* callback_context); +typedef int (*TracingHeapDataDestructor) (void* context, void* data); +typedef size_t (*TracingHeapSizeQuery) (void* context, void* data); + +typedef struct TracingHeapConfig_s { + TracingHeapTraceData trace_data; + void* trace_context; + + TracingHeapDataDestructor destructor; + void* destructor_context; + + TracingHeapSizeQuery size_query; + void* size_query_context; +} TracingHeapConfig; typedef struct TracingHeap_s { TracingObject* objects; @@ -30,20 +44,22 @@ typedef struct TracingHeap_s { TracingObject* grey_objects; TracingObject* black_objects; - ReferenceTracingFunction tracing_function; - void* tracing_function_context; - enum TracingColor reachable_color; enum TracingColor unreachable_color; + TracingHeapConfig config; allocator_t* allocator; } TracingHeap; -int TracingHeap_Create(TracingHeap* self, ReferenceTracingFunction tracing_function, allocator_t* allocator); +int TracingHeap_Create(TracingHeap* self, allocator_t* allocator); void TracingHeap_Destroy(TracingHeap* self); void* TracingHeap_Allocate(TracingHeap* self, size_t bytes); -int TracingHeap_AddTracingRoot(TracingHeap* self, void* data); +int TracingHeap_BeginTrace(TracingHeap* self); +int TracingHeap_EndTrace(TracingHeap* self); +int TracingHeap_TraceNext(TracingHeap* self); +size_t TracingHeap_TraceNextN(TracingHeap* self, size_t n); +int TracingHeap_AddTracingRoot(TracingHeap* self, void* data); #endif // header