Implemented TracingHeap_Destroy and TraceNextN
This commit is contained in:
parent
4f2a816128
commit
ccbe41c269
3 changed files with 127 additions and 23 deletions
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_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
|
#endif // header
|
||||||
|
|
Loading…
Reference in a new issue