#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

myhandle的更多相关文章

  1. Java开发中的23种设计模式详解

    [放弃了原文访问者模式的Demo,自己写了一个新使用场景的Demo,加上了自己的理解] [源码地址:https://github.com/leon66666/DesignPattern] 一.设计模式 ...

  2. Java开发中的23种设计模式详解(转)

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  3. java中的23中设计模式(转)

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  4. Python 程序员经常犯的 10 个错误

    关于PythonPython是一种解释性.面向对象并具有动态语义的高级程序语言.它内建了高级的数据结构,结合了动态类型和动态绑定的优点,这使得... 关于Python Python是一种解释性.面向对 ...

  5. xml文档解析

    XML文档解主要分为四种解析方式,官方提供的两种分别是:DOM 和 SAX,第三方分别是:JDOM 和 DOM4j 测试用的xml文档: <?xml version="1.0" ...

  6. 转:python signal信号

    转自:http://www.jb51.net/article/74844.htm 在liunx系统中要想每隔一分钟执行一个命令,最普遍的方法就是crontab了,如果不想使用crontab,经同事指点 ...

  7. java开发中的23中设计模式详解--大话设计模式

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  8. java基础语法要点<一>(基于1.8)

    http://yishouce.com/java/run http://www.shucunwang.com/RunCode/java/ 数据类型 8种基本数据类型及对应的 类型封装器 byte, s ...

  9. Python开发最常犯错误总结10种

    不管是在学习还是工作过程中,人都会犯错.虽然Python的语法简单.灵活,但也一样存在一些不小的坑,一不小心,初学者和资深Python程序员都有可能会栽跟头.本文是Toptal网站的程序员梳理的10大 ...

随机推荐

  1. 英雄联盟网络测速 v1.3 全服全区取延时+取服务器维护状态+机房地理位置

    全服全区取延时+取服务器维护状态+机房地理位置 v1.2修复了服务器状态获取不准确的bug 下载链接: https://pan.baidu.com/s/1c1LHIY8 

  2. 构建ceph deb 安装包

    前言:本文基于ubuntu 14.04.5 LTS 和ceph v0.94.3 之上做的实验 一.编译ceph包1.1.克隆ceph代码,切换分支 git clone --recursive http ...

  3. 描述性统计分析-用脚本将统计量函数批量化&分步骤逐一写出

    计算各种描述性统计量函数脚本(myDescriptStat.R)如下: myDescriptStat <- function(x){ n <- length(x) #样本数据个数 m &l ...

  4. 手机响应式js轮播基础

    onmousedown --->ontuchstart onmousemove --->ontouchmove onmouseup --->ontouchend ontuchstar ...

  5. iOS利用通知逆传值

    直接创建两个控制器,点击跳转第二个界面,然后点击按钮进行传值 #import "ViewController.h" #import "TWOOViewController ...

  6. Redis3.20阅读-SDS实现

    声明:这是本人参考黄建宏的<redis设计与实现>(源码版本是redis3.0)来学习redis3.20源码的笔记,如果有什么不对的地方,欢迎大家指正,大家一起学习.一起进步,QQ:499 ...

  7. 欧拉回路(hdu3018)

    刚学图论不久,看着别人的博客慢慢学了一点基础的,感觉还是有点力不从心,感觉图论的题好多长得都很像,什么太监算法(Tarjan),Kosaraju,当然最基础的还是并查集...好了继续介绍这道题.... ...

  8. centos6.5 安装linux 环境

    准备工作 安装make yum -y install gcc automake autoconf libtool make 安装g++ yum install gcc gcc-c++下面正式开始--- ...

  9. 基于ubuntu 14搭建nginx+php+mysql环境

    基于最新的Ubuntu 14.04(2014年9月)搭建nginx.php.mysql环境, 以下全部命令行操作: 1 由于需要大量的权限操作,方便起见临时提升权限,使用root账号 sudo su ...

  10. Javascript 字符串常用操作方法

    1.字符串转换 /* 你可以将一个数字,布尔值,或一个字符串对象转换为字符串 */ var num= 18; var str1 = num.toString(); //'18' var str2 = ...