Implemented TracingHeap_Destroy and TraceNextN

This commit is contained in:
VegOwOtenks 2024-10-14 12:31:58 +02:00
parent 4f2a816128
commit ccbe41c269
3 changed files with 127 additions and 23 deletions

View file

@ -18,3 +18,4 @@ add_subdirectory(./regex)
add_subdirectory(./QuadTree) add_subdirectory(./QuadTree)
add_subdirectory(./BinaryTree) add_subdirectory(./BinaryTree)
add_subdirectory(./Subprocess) add_subdirectory(./Subprocess)
add_subdirectory(./TracingHeap)

View file

@ -2,14 +2,19 @@
#include "../pointers/pointers.h" #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) { if (self == NULL) {
return EDESTADDRREQ; 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->allocator = allocator;
self->tracing_function = tracing_function;
self->objects = NULL; self->objects = NULL;
self->black_objects = NULL; self->black_objects = NULL;
@ -22,13 +27,23 @@ int TracingHeap_Create(TracingHeap* self, ReferenceTracingFunction tracing_funct
return EXIT_SUCCESS; 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) void TracingHeap_Destroy(TracingHeap* self)
{ {
if (self == NULL) { if (self == NULL) {
return; 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)); memset(self, 0, sizeof(*self));
} }
@ -111,7 +126,7 @@ int TracingHeap_AddTracingRoot(TracingHeap* self, void* data)
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
int TracingHeap_TraceOnce(TracingHeap* self) int TracingHeap_TraceNext(TracingHeap* self)
{ {
if (self == NULL) { if (self == NULL) {
return EDESTADDRREQ; return EDESTADDRREQ;
@ -123,8 +138,8 @@ int TracingHeap_TraceOnce(TracingHeap* self)
TracingObject* trace_object = _TracingHeap_PopColorList(self, TRACINGCOLOR_GREY); TracingObject* trace_object = _TracingHeap_PopColorList(self, TRACINGCOLOR_GREY);
int tracing_code = self->tracing_function( int tracing_code = self->config.trace_data(
self->tracing_function_context, self->config.trace_context,
trace_object->data, trace_object->data,
_TracingHeap_TraceReferenceCallback, _TracingHeap_TraceReferenceCallback,
self self
@ -138,6 +153,81 @@ int TracingHeap_TraceOnce(TracingHeap* self)
return EXIT_SUCCESS; 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) void* TracingHeap_Allocate(TracingHeap* self, size_t bytes)
{ {
if (self == NULL) { if (self == NULL) {
@ -151,19 +241,16 @@ void* TracingHeap_Allocate(TracingHeap* self, size_t bytes)
object->color = self->reachable_color; object->color = self->reachable_color;
if (self->reachable_color == TRACINGCOLOR_WHITE) { TracingObject** reachable_list_start = _TracingHeap_ColorListStart(self, self->reachable_color);
object->color_next = self->white_objects; object->color_next = *reachable_list_start;
self->white_objects = object; *reachable_list_start = object;
} else {
// black
object->color_next = self->black_objects;
self->black_objects = object;
}
object->color_prev = NULL; object->color_prev = NULL;
object->global_next = self->objects; object->global_next = self->objects; // link before global object list
self->objects = object; 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; return object->data;
} }

View file

@ -13,6 +13,7 @@ enum TracingColor {
typedef struct TracingObject { typedef struct TracingObject {
struct TracingObject* global_next; struct TracingObject* global_next;
struct TracingObject* global_prev;
struct TracingObject* color_next; struct TracingObject* color_next;
struct TracingObject* color_prev; struct TracingObject* color_prev;
enum TracingColor color; enum TracingColor color;
@ -21,8 +22,21 @@ typedef struct TracingObject {
alignas(void*) char data[]; alignas(void*) char data[];
} TracingObject; } TracingObject;
typedef int (*TraceReferenceCallback) (void* context, void* reference); typedef int (*TracingHeapVisit) (void* context, void* reference);
typedef int (*ReferenceTracingFunction) (void* context, void* object, TraceReferenceCallback trace_callback, void* callback_context); 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 { typedef struct TracingHeap_s {
TracingObject* objects; TracingObject* objects;
@ -30,20 +44,22 @@ typedef struct TracingHeap_s {
TracingObject* grey_objects; TracingObject* grey_objects;
TracingObject* black_objects; TracingObject* black_objects;
ReferenceTracingFunction tracing_function;
void* tracing_function_context;
enum TracingColor reachable_color; enum TracingColor reachable_color;
enum TracingColor unreachable_color; enum TracingColor unreachable_color;
TracingHeapConfig config;
allocator_t* allocator; allocator_t* allocator;
} TracingHeap; } 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_Destroy(TracingHeap* self);
void* TracingHeap_Allocate(TracingHeap* self, size_t bytes); void* TracingHeap_Allocate(TracingHeap* self, size_t bytes);
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); int TracingHeap_AddTracingRoot(TracingHeap* self, void* data);
#endif // header #endif // header