Generated CMakeLists.txt, implemented some of TracingHeap
This commit is contained in:
parent
7c74b68d75
commit
4f2a816128
3 changed files with 219 additions and 0 deletions
1
src/TracingHeap/CMakeLists.txt
Normal file
1
src/TracingHeap/CMakeLists.txt
Normal file
|
@ -0,0 +1 @@
|
|||
add_library(TracingHeap STATIC TracingHeap.c)
|
169
src/TracingHeap/TracingHeap.c
Normal file
169
src/TracingHeap/TracingHeap.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
#include "TracingHeap.h"
|
||||
|
||||
#include "../pointers/pointers.h"
|
||||
|
||||
int TracingHeap_Create(TracingHeap* self, ReferenceTracingFunction tracing_function, allocator_t* allocator)
|
||||
{
|
||||
if (self == NULL) {
|
||||
return EDESTADDRREQ;
|
||||
}
|
||||
|
||||
self->allocator = allocator;
|
||||
self->tracing_function = tracing_function;
|
||||
|
||||
self->objects = NULL;
|
||||
self->black_objects = NULL;
|
||||
self->white_objects = NULL;
|
||||
self->grey_objects = NULL;
|
||||
|
||||
self->reachable_color = TRACINGCOLOR_WHITE;
|
||||
self->unreachable_color = TRACINGCOLOR_BLACK;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void TracingHeap_Destroy(TracingHeap* self)
|
||||
{
|
||||
if (self == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Deallocate all objects
|
||||
memset(self, 0, sizeof(*self));
|
||||
}
|
||||
|
||||
static TracingObject* _TracingObject_FromDataPointer(void* datap)
|
||||
{
|
||||
return rewindp(datap, sizeof(TracingObject));
|
||||
}
|
||||
|
||||
static void _TracingObject_ChangeObjectColor(TracingObject* object, enum TracingColor new_color, TracingObject** list_start)
|
||||
{
|
||||
if (object->color != new_color) {
|
||||
object->color_prev->color_next = object->color_next;
|
||||
object->color_next->color_prev = object->color_prev;
|
||||
|
||||
object->color = new_color;
|
||||
object->color_prev = NULL;
|
||||
object->color_next = *list_start;
|
||||
(*list_start)->color_prev = object;
|
||||
*list_start = object;
|
||||
}
|
||||
}
|
||||
|
||||
static TracingObject** _TracingHeap_ColorListStart(TracingHeap* self, enum TracingColor color)
|
||||
{
|
||||
TracingObject** list_start;
|
||||
switch (color) {
|
||||
case TRACINGCOLOR_BLACK:
|
||||
list_start = &self->black_objects;
|
||||
break;
|
||||
case TRACINGCOLOR_GREY:
|
||||
list_start = &self->grey_objects;
|
||||
break;
|
||||
case TRACINGCOLOR_WHITE:
|
||||
list_start = &self->white_objects;
|
||||
break;
|
||||
}
|
||||
|
||||
return list_start;
|
||||
}
|
||||
|
||||
static void _TracingHeap_MakeReachable(TracingHeap* self, TracingObject* object)
|
||||
{
|
||||
TracingObject** reachable_list_start = _TracingHeap_ColorListStart(self, self->reachable_color);
|
||||
_TracingObject_ChangeObjectColor(object, self->reachable_color, reachable_list_start);
|
||||
}
|
||||
|
||||
static TracingObject* _TracingHeap_PopColorList(TracingHeap* self, enum TracingColor color)
|
||||
{
|
||||
TracingObject** list_start = _TracingHeap_ColorListStart(self, color);
|
||||
|
||||
TracingObject* popped = *list_start;
|
||||
popped->color_next->color_prev = NULL; // unlink next element from popped
|
||||
*list_start = popped->color_next; // link list to next element
|
||||
popped->color_next = NULL; // unlink popped from next element
|
||||
|
||||
return popped;
|
||||
}
|
||||
|
||||
static int _TracingHeap_TraceReferenceCallback(void* context, void* reference)
|
||||
{
|
||||
TracingHeap* self = context;
|
||||
TracingObject* object = _TracingObject_FromDataPointer(reference);
|
||||
|
||||
if (object->color == self->unreachable_color) {
|
||||
_TracingObject_ChangeObjectColor(object, TRACINGCOLOR_GREY, &self->grey_objects);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int TracingHeap_AddTracingRoot(TracingHeap* self, void* data)
|
||||
{
|
||||
if (self == NULL) {
|
||||
return EDESTADDRREQ;
|
||||
}
|
||||
|
||||
TracingObject* root_object = _TracingObject_FromDataPointer(data);
|
||||
_TracingObject_ChangeObjectColor(root_object, TRACINGCOLOR_GREY, &self->grey_objects);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int TracingHeap_TraceOnce(TracingHeap* self)
|
||||
{
|
||||
if (self == NULL) {
|
||||
return EDESTADDRREQ;
|
||||
}
|
||||
|
||||
if (self->grey_objects == NULL) {
|
||||
return EBADSTATE;
|
||||
}
|
||||
|
||||
TracingObject* trace_object = _TracingHeap_PopColorList(self, TRACINGCOLOR_GREY);
|
||||
|
||||
int tracing_code = self->tracing_function(
|
||||
self->tracing_function_context,
|
||||
trace_object->data,
|
||||
_TracingHeap_TraceReferenceCallback,
|
||||
self
|
||||
);
|
||||
if (tracing_code) {
|
||||
return tracing_code;
|
||||
}
|
||||
|
||||
_TracingHeap_MakeReachable(self, trace_object);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void* TracingHeap_Allocate(TracingHeap* self, size_t bytes)
|
||||
{
|
||||
if (self == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TracingObject* object = Allocator_Allocate(self->allocator, sizeof(TracingObject) + bytes);
|
||||
if (object == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
object->color_prev = NULL;
|
||||
|
||||
|
||||
object->global_next = self->objects;
|
||||
self->objects = object;
|
||||
|
||||
return object->data;
|
||||
}
|
49
src/TracingHeap/TracingHeap.h
Normal file
49
src/TracingHeap/TracingHeap.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef UTILITIEC_TRACINGHEAP_H
|
||||
#define UTILITIEC_TRACINGHEAP_H
|
||||
|
||||
#include "../allocator-interface/allocator-interface.h"
|
||||
|
||||
#include <stdalign.h>
|
||||
|
||||
enum TracingColor {
|
||||
TRACINGCOLOR_BLACK,
|
||||
TRACINGCOLOR_GREY,
|
||||
TRACINGCOLOR_WHITE,
|
||||
};
|
||||
|
||||
typedef struct TracingObject {
|
||||
struct TracingObject* global_next;
|
||||
struct TracingObject* color_next;
|
||||
struct TracingObject* color_prev;
|
||||
enum TracingColor color;
|
||||
|
||||
// data member of the requested size
|
||||
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 struct TracingHeap_s {
|
||||
TracingObject* objects;
|
||||
TracingObject* white_objects;
|
||||
TracingObject* grey_objects;
|
||||
TracingObject* black_objects;
|
||||
|
||||
ReferenceTracingFunction tracing_function;
|
||||
void* tracing_function_context;
|
||||
|
||||
enum TracingColor reachable_color;
|
||||
enum TracingColor unreachable_color;
|
||||
|
||||
allocator_t* allocator;
|
||||
} TracingHeap;
|
||||
|
||||
int TracingHeap_Create(TracingHeap* self, ReferenceTracingFunction tracing_function, allocator_t* allocator);
|
||||
void TracingHeap_Destroy(TracingHeap* self);
|
||||
|
||||
void* TracingHeap_Allocate(TracingHeap* self, size_t bytes);
|
||||
|
||||
int TracingHeap_AddTracingRoot(TracingHeap* self, void* data);
|
||||
|
||||
#endif // header
|
Loading…
Reference in a new issue