]> git.mdlowis.com Git - archive/carl.git/commitdiff
Added refcounting functionality
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 6 Jun 2015 01:59:38 +0000 (21:59 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 6 Jun 2015 01:59:38 +0000 (21:59 -0400)
source/libc.h
source/refcount.c [new file with mode: 0644]

index d24acdbbc87757cc150ef415b7282f3e8e168ebb..21947cddf0d89af14e0c1f7258b6da69fe09dc92 100644 (file)
 #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 (file)
index 0000000..d665600
--- /dev/null
@@ -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);
+}
+