myhandle
#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的更多相关文章
- Java开发中的23种设计模式详解
[放弃了原文访问者模式的Demo,自己写了一个新使用场景的Demo,加上了自己的理解] [源码地址:https://github.com/leon66666/DesignPattern] 一.设计模式 ...
- Java开发中的23种设计模式详解(转)
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- java中的23中设计模式(转)
设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- Python 程序员经常犯的 10 个错误
关于PythonPython是一种解释性.面向对象并具有动态语义的高级程序语言.它内建了高级的数据结构,结合了动态类型和动态绑定的优点,这使得... 关于Python Python是一种解释性.面向对 ...
- xml文档解析
XML文档解主要分为四种解析方式,官方提供的两种分别是:DOM 和 SAX,第三方分别是:JDOM 和 DOM4j 测试用的xml文档: <?xml version="1.0" ...
- 转:python signal信号
转自:http://www.jb51.net/article/74844.htm 在liunx系统中要想每隔一分钟执行一个命令,最普遍的方法就是crontab了,如果不想使用crontab,经同事指点 ...
- java开发中的23中设计模式详解--大话设计模式
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- java基础语法要点<一>(基于1.8)
http://yishouce.com/java/run http://www.shucunwang.com/RunCode/java/ 数据类型 8种基本数据类型及对应的 类型封装器 byte, s ...
- Python开发最常犯错误总结10种
不管是在学习还是工作过程中,人都会犯错.虽然Python的语法简单.灵活,但也一样存在一些不小的坑,一不小心,初学者和资深Python程序员都有可能会栽跟头.本文是Toptal网站的程序员梳理的10大 ...
随机推荐
- 高通camera学习笔记
http://www.2cto.com/kf/201609/548725.html http://www.android100.org/html/201508/24/176303.html
- Oracle建表
1.oracle数据库中的多种数据结构: 1.表结构 存储数据 2.视图 一张表或多张表中数据的字节 3.sequence 主要用来生成主键值 4.index 提高检索性能 我们 ...
- CentOS 7 程序自启动的问题
Mysql具体的安装方法见http://www.cnblogs.com/yoyotl/p/5752437.html 但是关于自启动部分需要多一些说明. 一.问题现象: 系统重启后,发现mysqld服务 ...
- solrconfig.xml解析
solrconfig.xml配置文件主要定义了SOLR的一些处理规则,包括索引数据的存放位置,更新,删除,查询的一些规则配置.下面将对solrconfig进行详细描述:1 <luceneMatc ...
- sql语句错误
此错误一般有以下情况造成: 1.配置文件中SQL语句写的有问题 2.传参过程中没有找到sql对应的参数 解决方法: 1.检查sql语句 2.debug启动,查找与sql语句相对应的参数是否存在. 3. ...
- 28.zookeeper单机(Standalones模式)和集群搭建笔记
zookeeper单机(Standalones模式)和集群搭建: 前奏: (1).zookeeper也可以在windows下使用,和linux一样可以单机也可以集群,具体就是解压zookeeper-3 ...
- T-SQL编程 —— 用户自定义函数(内嵌表值函数)
内嵌表值函数 接上 <T-SQL编程 -- 用户自定义函数(标量函数)> http://www.cnblogs.com/viusuangio/p/6212072.html 内嵌表值函数可以 ...
- HTML 在安卓手机端软键盘弹出顶起页面布局的解决办法
$('body').height($('body')[0].clientHeight); 以上是背景即BODY被顶起的解决办法. 如果是footer被顶起,则可以用判断解决, $('input').f ...
- 如何离线创建Ionic/cordova项目
在创建ionic项目的时候,需要联网下载许多东西,由于墙的缘故,我们在创建.添加android平台.编译过程中,失败的可能性非常高,为解决这个问题,我创建了一个空的Ionic1 tab项目,并完成了上 ...
- JAVA 1.1
1. JASE : J2SE 这个就是我们现在在学的东西,他是一切Java的核心基础 JAME :J2ME : 他是Java的一个微型版,主要用来做移动开发 JAEE :J2EE Java企业版本,主 ...