#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <assert.h>
#if ! defined (ALIGN_UINTPTR_TYPE)
# define ALIGN_UINTPTR_TYPE size_t
#endif
typedef char ALIGN_STATIC_ASSERT
[
sizeof(ALIGN_UINTPTR_TYPE) == sizeof(void*)
? 1 : -1
];
#define ALIGN_OF(mp_type) \
offsetof( \
struct \
{ \
char pad; \
mp_type type; \
}, \
type \
)
#define ALIGN_UP(mp_ptr, mp_align) \
((void*)( \
(((ALIGN_UINTPTR_TYPE)(mp_ptr)) + \
((mp_align) - 1)) & ~(((mp_align) - 1)) \
))
void*
xmalloc_aligned(
size_t header_size,
size_t object_size,
size_t align_size
){
size_t total_size;
unsigned char* tmp;
unsigned char* header;
unsigned char* header_ptr;
unsigned char* object;
align_size = align_size
? (size_t)ALIGN_UP(align_size, ALIGN_OF(void*))
: ALIGN_OF(void*);
total_size = (size_t)
ALIGN_UP(
header_size + sizeof(void*) +
object_size + ALIGN_OF(void*) + align_size,
ALIGN_OF(void*)
);
if (! (header = malloc(total_size))) return NULL;
tmp = ALIGN_UP(header + header_size, ALIGN_OF(void*));
object = ALIGN_UP(tmp + sizeof(void*), align_size);
header_ptr = object - sizeof(void*);
*((void**)header_ptr) = header;
return object;
}
#define xmalloc_aligned_get(mp_object) \
((mp_object) \
? (*((void**)(((unsigned char*)mp_object) \
- sizeof(void*)))) \
: NULL)
#define XMALLOC_ALIGNED(mp_header, mp_object) \
xmalloc_aligned( \
sizeof(mp_header), \
sizeof(mp_object), \
ALIGN_OF(mp_object) \
)
void
xfree_aligned(
void* object
){
if (! object) return;
free(xmalloc_aligned_get(object));
}
typedef void (ref_count_func_dtor) (void*);
struct ref_count
{
unsigned count;
ref_count_func_dtor* fp_dtor;
};
void* ref_count_sys_create(
size_t object_size,
size_t align_size,
ref_count_func_dtor* fp_dtor
){
struct ref_count* self;
void* const object =
xmalloc_aligned(sizeof(*self), object_size, align_size);
if (! object) return NULL;
self = xmalloc_aligned_get(object);
self->count = 1;
self->fp_dtor = fp_dtor;
return object;
}
#define REF_COUNT_CREATE(mp_type, mp_fp_dtor) \
ref_count_sys_create( \
sizeof(mp_type), \
ALIGN_OF(mp_type), \
(mp_fp_dtor) \
)
#define ref_count_get(mp_object) \
xmalloc_aligned_get(mp_object)
void*
ref_count_acquire(
void* state
){
struct ref_count* const self = ref_count_get(state);
if (! self) return NULL;
++self->count;
return state;
}
void
ref_count_release(
void* state
){
struct ref_count* const self = ref_count_get(state);
if (! self) return;
if (--self->count) return;
if (self->fp_dtor) self->fp_dtor(state);
free(self);
}
struct foo
{
/*__declspec(align(128))*/ double state;
};
void
foo_ref_count_dtor(
void* state
){
struct foo* const self = state;
printf("foo_ref_count_dtor::%p - %f\n",
(void*)self, self->state);
}
int main(void)
{
struct foo* foo1 =
REF_COUNT_CREATE(struct foo, foo_ref_count_dtor);
struct foo* foo2;
if (! foo1) return EXIT_FAILURE;
foo1->state = -665;
foo2 = ref_count_acquire(foo1);
foo2->state -= 1;
ref_count_release(foo1);
ref_count_release(foo2);
return EXIT_SUCCESS;
}