From: Michael D. Lowis Date: Sat, 6 Jun 2015 01:59:38 +0000 (-0400) Subject: Added refcounting functionality X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=4d3b1067234e6ada466e6bd5588b50f02d947b55;p=archive%2Fcarl.git Added refcounting functionality --- 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); +} +