feat: add data-kind to TracingObject to enable quasi-polymorphism
This commit is contained in:
parent
7120f59951
commit
3d6f7a2957
2 changed files with 49 additions and 16 deletions
|
@ -28,8 +28,16 @@ int TracingHeap_Create(TracingHeap* self, allocator_t* allocator)
|
||||||
|
|
||||||
static void _TracingHeap_ForceDestroyObject(TracingHeap* self, TracingObject* object)
|
static void _TracingHeap_ForceDestroyObject(TracingHeap* self, TracingObject* object)
|
||||||
{
|
{
|
||||||
size_t allocated_size = self->config.size_query(self->config.size_query_context, object->data);
|
TracingHeapSizeQuery query_function = self->config.size_query[object->data_kind];
|
||||||
self->config.destructor(self->config.destructor_context, object->data);
|
void* query_function_context = self->config.size_query_context[object->data_kind];
|
||||||
|
size_t allocated_size = query_function(query_function_context, object->data);
|
||||||
|
|
||||||
|
TracingHeapDataDestructor destructor_function = self->config.destructor[object->data_kind];
|
||||||
|
void* destructor_function_context = self->config.destructor_context[object->data_kind];
|
||||||
|
|
||||||
|
int destructor_code = destructor_function(destructor_function_context, object->data);
|
||||||
|
(void) destructor_code;
|
||||||
|
|
||||||
Allocator_Free(self->allocator, object, allocated_size);
|
Allocator_Free(self->allocator, object, allocated_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,8 +159,10 @@ int TracingHeap_TraceNext(TracingHeap* self)
|
||||||
|
|
||||||
TracingObject* trace_object = _TracingHeap_PopColorList(self, TRACINGCOLOR_GREY);
|
TracingObject* trace_object = _TracingHeap_PopColorList(self, TRACINGCOLOR_GREY);
|
||||||
|
|
||||||
int tracing_code = self->config.trace_data(
|
TracingHeapTraceData trace_function = self->config.trace_data[trace_object->data_kind];
|
||||||
self->config.trace_context,
|
void* trace_context = self->config.trace_context[trace_object->data_kind];
|
||||||
|
int tracing_code = trace_function(
|
||||||
|
trace_context,
|
||||||
trace_object->data,
|
trace_object->data,
|
||||||
_TracingHeap_TraceReferenceCallback,
|
_TracingHeap_TraceReferenceCallback,
|
||||||
self
|
self
|
||||||
|
@ -181,9 +191,13 @@ size_t TracingHeap_TraceNextN(TracingHeap* self, size_t n, int* error_code)
|
||||||
|
|
||||||
static int _TracingHeap_DestroyObject(TracingHeap* self, TracingObject* unreachable_object)
|
static int _TracingHeap_DestroyObject(TracingHeap* self, TracingObject* unreachable_object)
|
||||||
{
|
{
|
||||||
size_t allocated_size = self->config.size_query(self->config.size_query_context, unreachable_object->data);
|
TracingHeapSizeQuery query_function = self->config.size_query[unreachable_object->data_kind];
|
||||||
|
void* query_function_context = self->config.size_query_context[unreachable_object->data_kind];
|
||||||
|
size_t allocated_size = query_function(query_function_context, unreachable_object->data);
|
||||||
|
|
||||||
int destructor_code = self->config.destructor(self->config.destructor_context, unreachable_object->data);
|
TracingHeapDataDestructor destructor_function = self->config.destructor[unreachable_object->data_kind];
|
||||||
|
void* destructor_function_context = self->config.destructor_context[unreachable_object->data_kind];
|
||||||
|
int destructor_code = destructor_function(destructor_function_context, unreachable_object->data);
|
||||||
if (destructor_code) {
|
if (destructor_code) {
|
||||||
return destructor_code;
|
return destructor_code;
|
||||||
}
|
}
|
||||||
|
@ -248,11 +262,14 @@ int TracingHeap_EndTrace(TracingHeap* self)
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* TracingHeap_Allocate(TracingHeap* self, size_t bytes)
|
void* TracingHeap_Allocate(TracingHeap* self, size_t bytes, uint64_t data_kind)
|
||||||
{
|
{
|
||||||
if (self == NULL) {
|
if (self == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data_kind > TRACINGHEAPDATAKIND_MAX) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
TracingObject* object = Allocator_Allocate(self->allocator, sizeof(TracingObject) + bytes);
|
TracingObject* object = Allocator_Allocate(self->allocator, sizeof(TracingObject) + bytes);
|
||||||
if (object == NULL) {
|
if (object == NULL) {
|
||||||
|
@ -260,6 +277,7 @@ void* TracingHeap_Allocate(TracingHeap* self, size_t bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
object->color = self->reachable_color;
|
object->color = self->reachable_color;
|
||||||
|
object->data_kind = data_kind;
|
||||||
|
|
||||||
TracingObject** reachable_list_start = _TracingHeap_ColorListStart(self, self->reachable_color);
|
TracingObject** reachable_list_start = _TracingHeap_ColorListStart(self, self->reachable_color);
|
||||||
object->color_next = *reachable_list_start;
|
object->color_next = *reachable_list_start;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <stdalign.h>
|
#include <stdalign.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
enum TracingColor {
|
enum TracingColor {
|
||||||
TRACINGCOLOR_BLACK,
|
TRACINGCOLOR_BLACK,
|
||||||
|
@ -12,29 +13,43 @@ enum TracingColor {
|
||||||
TRACINGCOLOR_WHITE,
|
TRACINGCOLOR_WHITE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union TracingObjectDataAlignment {
|
||||||
|
double d;
|
||||||
|
void* p;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct TracingObject {
|
typedef struct TracingObject {
|
||||||
|
// color linked list members
|
||||||
struct TracingObject* color_next;
|
struct TracingObject* color_next;
|
||||||
struct TracingObject* color_prev;
|
struct TracingObject* color_prev;
|
||||||
enum TracingColor color;
|
|
||||||
|
// Selector for the callback function
|
||||||
|
// TODO: Think about something for 16-bit systems
|
||||||
|
#define TRACINGHEAPDATAKIND_MAX (((uint64_t) 1 << 62) - 1)
|
||||||
|
uint64_t data_kind: 62;
|
||||||
|
|
||||||
|
// color of this object
|
||||||
|
enum TracingColor color: 2;
|
||||||
|
|
||||||
// data member of the requested size
|
// data member of the requested size
|
||||||
alignas(void*) char data[];
|
alignas(union TracingObjectDataAlignment) char data[];
|
||||||
} TracingObject;
|
} TracingObject;
|
||||||
|
|
||||||
|
|
||||||
typedef int (*TracingHeapVisit) (void* context, void* reference);
|
typedef int (*TracingHeapVisit) (void* context, void* reference);
|
||||||
typedef int (*TracingHeapTraceData) (void* context, void* data, TracingHeapVisit 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 int (*TracingHeapDataDestructor) (void* context, void* data);
|
||||||
typedef size_t (*TracingHeapSizeQuery) (void* context, void* data);
|
typedef size_t (*TracingHeapSizeQuery) (void* context, void* data);
|
||||||
|
|
||||||
typedef struct TracingHeapConfig_s {
|
typedef struct TracingHeapConfig_s {
|
||||||
TracingHeapTraceData trace_data;
|
TracingHeapTraceData* trace_data;
|
||||||
void* trace_context;
|
void** trace_context;
|
||||||
|
|
||||||
TracingHeapDataDestructor destructor;
|
TracingHeapDataDestructor* destructor;
|
||||||
void* destructor_context;
|
void** destructor_context;
|
||||||
|
|
||||||
TracingHeapSizeQuery size_query;
|
TracingHeapSizeQuery* size_query;
|
||||||
void* size_query_context;
|
void** size_query_context;
|
||||||
} TracingHeapConfig;
|
} TracingHeapConfig;
|
||||||
|
|
||||||
typedef struct TracingHeap_s {
|
typedef struct TracingHeap_s {
|
||||||
|
@ -52,7 +67,7 @@ typedef struct TracingHeap_s {
|
||||||
int TracingHeap_Create(TracingHeap* self, 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, uint64_t object_kind);
|
||||||
|
|
||||||
int TracingHeap_BeginTrace(TracingHeap* self);
|
int TracingHeap_BeginTrace(TracingHeap* self);
|
||||||
bool TracingHeap_IsTraceFinished(TracingHeap* self);
|
bool TracingHeap_IsTraceFinished(TracingHeap* self);
|
||||||
|
|
Loading…
Reference in a new issue