Skip to content
This repository has been archived by the owner on Jun 30, 2021. It is now read-only.

Commit

Permalink
transparent reference counting API
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanFrench committed Sep 20, 2017
1 parent f50cbd0 commit 6f4dc08
Showing 1 changed file with 85 additions and 0 deletions.
85 changes: 85 additions & 0 deletions refcount.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#pragma once

#include <pthread.h>

static void (* REF_free)(void *) = free;
static void * (* REF_realloc)(void *, size_t) = realloc;
static void * (* REF_malloc)(size_t) = malloc;

struct refcount_ {
pthread_mutex_t mux;
unsigned int count;
char data[];
};

#define ref_upcast(DAT) \
(struct refcount_ *)((char *)(DAT - offsetof(struct refcount_, data)))

#define ref_barrier(CODE) \
pthread_mutex_lock(&refc->mux); \
CODE \
pthread_mutex_unlock(&refc->mux)


static inline void
ref_init_functions(void *(*mallocf)(size_t),
void * (*callocf)(size_t, size_t),
void *(*reallocf)(void *, size_t),
void (* freef)(void *))
{
REF_malloc = mallocf;
REF_realloc = reallocf;
REF_free = freef;
}

static unsigned int
ref_inc(void * buf)
{
struct refcount_ * refc = ref_upcast(buf);
unsigned int refs;

ref_barrier({ refs = ++refc->count; });

return refs;
}

static unsigned int
ref_dec(void * buf)
{
struct refcount_ * refc = ref_upcast(buf);
unsigned int refs;

ref_barrier({ refc->count -= 1; refs = refc->count; });

return refs;
}

static inline void *
ref_malloc(size_t size)
{
struct refcount_ * refc;
pthread_mutexattr_t attr;

refc = REF_malloc(sizeof(*refc) + size);
refc->count = 1;

pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&refc->mux, &attr);

return refc->data;
}

static void
ref_free(void * buf)
{
struct refcount_ * refc = ref_upcast(buf);

ref_barrier({
if (--refc->count == 0)
{
pthread_mutex_unlock(&refc->mux);
return REF_free(refc);
}
});
}

0 comments on commit 6f4dc08

Please sign in to comment.