标签:
#ifndef my_handle_h #define my_handle_h #include <stdint.h> #include "mydef.h" #include "mem.h" typedef struct tag_my_handle { int ref; int stack; intptr_t detached; void* ptr; free_t free; } my_handle; static inline my_handle* debug_handle_attach(void* ptr, free_t fp_free, const char* func, int line) { my_handle* handle = (my_handle *) debug_malloc(sizeof(my_handle), func, line); if (handle != NULL) { handle->ref = 1; handle->stack = 1; handle->ptr = ptr; handle->free = fp_free; handle->detached = 0; } return handle; } #define handle_attach(ptr, fptr) debug_handle_attach(ptr, fptr, __FUNCTION__, __LINE__) #define handle_put(handle) do { int n = __sync_sub_and_fetch(&(handle)->stack, 1); my_assert(n >= 0); if (n == 0) { void* handle_ptr = (void *) __sync_lock_test_and_set(&(handle)->ptr, NULL); if ((handle)->free && handle_ptr) { (handle)->free(handle_ptr); } } } while (0) static inline void* handle_get_with(my_handle* handle, int detach, const char* func, int line) { int n = __sync_add_and_fetch(&handle->stack, 1); int b = __sync_bool_compare_and_swap((void **) &handle->detached, (void *) 0, (void *) (intptr_t) detach); if (!b) { handle_put(handle); return NULL; } void* ptr = handle->ptr; my_assert2(n > 1 && ptr != NULL, "%d, %p, caller %d@%s", n, ptr, line, func); return ptr; } #define handle_get(handle) handle_get_with((handle), 0, __FUNCTION__, __LINE__) static inline int handle_clone(my_handle* handle) { int n = __sync_add_and_fetch(&handle->ref, 1); my_assert(n > 0); return n; } static inline int handle_release(my_handle* handle) { int n = __sync_sub_and_fetch(&handle->ref, 1); my_assert2(n >= 0, "%p %d:%d", handle, handle->ref, handle->stack); if (n > 0) { return n; } // it should be safe to simplely check whether detached equals 0. // we know __sync_xxx functions have mb() semantics, and // if some one set handle->detached = 1, it only can be called in // handle_dettach while still holds a reference of handle. // ok, now we have seen handle->ref = 0 above, meaning // we have observed the latter handle_release in handle_dettach. // then, the mb() assure that // we have observed the earlier handle_get_with(handle, 1). if (handle->detached == 0) { handle_put(handle); } my_assert(handle->stack == 0); my_free(handle); return n; } static inline int debug_handle_dettach(my_handle* handle, const char* func, int line) { void* ptr = handle_get_with(handle, 1, func, line); if (ptr != NULL) { __sync_sub_and_fetch(&handle->stack, 1); handle_put(handle); } return handle_release(handle); } #define handle_dettach(handle) debug_handle_dettach((handle), __FUNCTION__, __LINE__) #endif
标签:
原文地址:http://www.cnblogs.com/zylthinking/p/5975721.html