From 4d3b1067234e6ada466e6bd5588b50f02d947b55 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Fri, 5 Jun 2015 21:59:38 -0400 Subject: [PATCH] Added refcounting functionality --- source/libc.h | 18 ++++++++-------- source/refcount.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 source/refcount.c diff --git a/source/libc.h b/source/libc.h index d24acdb..21947cd 100644 --- a/source/libc.h +++ b/source/libc.h @@ -23,6 +23,11 @@ #define nelem(x) (sizeof(x)/sizeof((x)[0])) #endif +#ifndef container_of +#define container_of(obj, type, member) \ + (type*)((uintptr_t)obj - offsetof(type, member)) +#endif + /* * Assertions */ @@ -58,17 +63,12 @@ int cistrcmp(char*, char*); char* cistrstr(char*, char*); int tokenize(char*, char**, int); +void* refallocate(size_t); +void* refobject(size_t,void (*)(void*)); void* refretain(void*); void refrelease(void*); -void refcount(void*); -static inline void __refreplace(void** var, void* val) -{ - void* doomed = *var; - *var = val; - refrelease(doomed); -} -#define refreplace(var, val) \ - __refreplace((void**)var, val); +size_t refcount(void*); +void refreplace(void** var, void* val); /* * Rune Definitions and Routines diff --git a/source/refcount.c b/source/refcount.c new file mode 100644 index 0000000..d665600 --- /dev/null +++ b/source/refcount.c @@ -0,0 +1,52 @@ +#include "libc.h" + +typedef struct obj_t { + uintptr_t refcount; + void (*destruct)(void*); + uint8_t data[]; +} obj_t; + +void* refallocate(size_t sz) +{ + return refobject(sz, nil); +} + +void* refobject(size_t sz, void (*destruct)(void*)) +{ + obj_t* object = (obj_t*)malloc(sizeof(obj_t) + sz); + object->refcount = 1; + object->destruct = destruct; + return &(object->data[0]); +} + +void* refretain(void* obj) +{ + obj_t* object = container_of(obj, obj_t, data); + object->refcount++; + return obj; +} + +void refrelease(void* obj) +{ + obj_t* object = container_of(obj, obj_t, data); + object->refcount--; + if (object->refcount == 0) { + if (nil != object->destruct) + object->destruct(obj); + free(object); + } +} + +size_t refcount(void* obj) +{ + obj_t* object = container_of(obj, obj_t, data); + return object->refcount; +} + +void refreplace(void** var, void* val) +{ + void* deadite = *var; + *var = val; + refrelease(deadite); +} + -- 2.54.0