1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 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);
}
});
}
|