Reference_Linking/rl.c
2023-03-16 12:28:35 +01:00

104 Zeilen
2.5 KiB
C

#include "rl.h"
#include <stdbool.h>
#include <malloc.h>
struct RlBox {
bool marked;
Rl* first;
Rl* last;
Destructor destructor;
};
#define RLBOX_SIZE sizeof(struct RlBox)
#define PTR_TO_RLBOX(ptr) ((struct RlBox*)((ptr) - RLBOX_SIZE))
inline void rl_alloc(Rl* reference, const void* owner, const size_t size, const Destructor destructor) {
struct RlBox* box = (struct RlBox*) malloc(RLBOX_SIZE + size);
box->marked = false;
box->first = NULL;
box->last = NULL;
box->destructor = destructor;
reference->prev = NULL;
reference->next = NULL;
reference->owner = PTR_TO_RLBOX(owner);
reference->ref = box + RLBOX_SIZE;
}
// reference may not point to a valid object
inline void rl_set(Rl* reference, const void* owner, const Rl* copy) {
reference->prev = PTR_TO_RLBOX(copy->ref)->last;
reference->next = NULL;
reference->owner = PTR_TO_RLBOX(owner);
reference->ref = copy->ref;
reference->prev->next = reference;
}
static void unmark(struct RlBox* obj) {
if(!obj->marked)
return;
obj->marked = false;
Rl* ref = obj->first;
while(ref) {
unmark(ref->owner);
ref = ref->next;
}
}
static bool search_root(struct RlBox* obj) {
if(obj->marked)
return false;
obj->marked = true;
Rl* ref = obj->first;
while(ref) {
if(!ref->owner || search_root(ref->owner)) {
// mark reversal
Rl* prev = ref->prev;
while(prev) {
unmark(prev->owner);
prev = ref->prev;
}
obj->marked = false;
// reordering
if(ref != obj->first) {
if(ref->next)
ref->next->prev = ref->prev;
else
obj->last = ref->prev;
ref->prev->next = ref->next;
obj->first->prev = ref;
obj->first = ref;
}
return true;
}
ref = ref->next;
}
return false;
}
inline void rl_free(Rl* reference) {
struct RlBox* obj = PTR_TO_RLBOX(reference->ref);
if(obj->first != reference) {
if(reference->next)
reference->next->prev = reference->prev;
else
obj->last = reference->prev;
reference->prev->next = reference->next;
return;
}
if(search_root(obj))
return;
obj->destructor(reference->ref);
free(obj);
}
//TODO foolproofed versions (with NULL, prev set, etc.)