[ create a new paste ] login | about

Link: http://codepad.org/Ot7HL6Te    [ raw code | output | fork ]

C, pasted on Jun 15:
#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; 
};


#define REF_COUNT_STRUCT(mp_type)   \
    struct                          \
    {                               \
        struct ref_count rcount;    \
        mp_type type;               \
    }


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(REF_COUNT_STRUCT(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;
}


Output:
1
foo_ref_count_dtor::0x804a084 - -666.000000


Create a new paste based on this one


Comments: