POSIX 线程清理函数
POSIX 多线程的 cleanup 函数
控制清理函数的函数有两个,一个是 pthread_cleanup_push(), 用来把清理函数压入栈中,另一个是 pthread_cleanup_pop(), 用来把栈中的函数弹出来。
用这两个函数组合,可以达到在线程退出时,清理线程数据的作用, 例如对 mutex 进行解锁等。
下面是这两个函数的函数原型:
#include <pthread.h>void pthread_cleanup_push(void (*routine)(void *), void *arg); void pthread_cleanup_pop(int execute);//Compile and link with -pthread.
我们先写个简单的例子,感性认识一下这两个函数的作用:
#include <stdio.h> #include <pthread.h>void handlers(void *arg) {if(NULL != arg) {printf("%s() : [%s]\n", __func__, (char*)arg);} else {printf("%s()\n", __func__);} }void * thread_start(void *arg) {pthread_cleanup_push(handlers, "one");pthread_cleanup_push(handlers, "two");pthread_cleanup_push(handlers, "thr");printf("This is thread [%u]\n", (unsigned int)pthread_self());pthread_exit("he~he~");//do something pthread_cleanup_pop(1);pthread_cleanup_pop(1);pthread_cleanup_pop(1);return NULL; }int main() {pthread_t pt;pthread_create(&pt, NULL, thread_start, NULL);void *r = NULL;pthread_join(pt, &r);if(NULL != r) {printf("thread return : [%s]\n", (const char*)r);}return 0; }
编译并运行:
This is thread [3290769152] handlers() : [thr] handlers() : [two] handlers() : [one] thread return : [he~he~]
我们在代码里面是按照 one、two、thr 的顺序调用的 pthread_cleanup_push() 函数, 结果在运行后得到的结果中,却看到它们输出的顺序正好倒过来了。 这正是这对函数的性质。
并且这对函数还有一个性质,那就是使用 pthread_cleanup_push() 和 pthread_cleanup_pop() 之间使用 return 的话,会导致之后的 pthread_cleanup_pop() 不起作用。 这是为什么呢?原因是,其实 pthread_cleanup_push() 和 pthread_cleanup_pop() 不是函数, 而是一对宏。
其宏定义在头文件 pthread.h 中可以看到,宏定义如下:
# define pthread_cleanup_push(routine, arg) \do { \__pthread_cleanup_class __clframe (routine, arg)# define pthread_cleanup_pop(execute) \__clframe.__setdoit (execute); \} while (0)
我们写个更简单的程序,把这两个宏展开后看一看是什么样结果:
代码如下:
# define pthread_cleanup_push(routine, arg) \do { \__pthread_cleanup_class __clframe (routine, arg)# define pthread_cleanup_pop(execute) \__clframe.__setdoit (execute); \} while (0)
编译:
gcc -g -E -o pthread_cleanup_macro.i pthread_cleanup_macro.c
查看 pthread_cleanup_macro.i 的代码:
void hand(void* arg) {printf("do nothing"); }void *thread_start(void* arg) {do { __pthread_unwind_buf_t __cancel_buf; void (*__cancel_routine) (void *) = (hand); void *__cancel_arg = ("a"); int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) __cancel_buf.__cancel_jmp_buf, 0); if (__builtin_expect((__not_first_call), 0)) { __cancel_routine (__cancel_arg); __pthread_unwind_next (&__cancel_buf); } __pthread_register_cancel (&__cancel_buf); do {;printf("This is thread [%u]\n", (unsigned int)pthread_self());do { } while (0); } while (0); __pthread_unregister_cancel (&__cancel_buf); if (1) __cancel_routine (__cancel_arg); } while (0);return ((void *)0); }int main() {return 0; }
可以看到,thread_start 函数里面的 pthread_cleanup_push() 和 pthread_cleanup_pop() 已经被展开了。我们把 thread_start 函数里面的代码再修饰一下格式,结果如下:
void *thread_start(void* arg) {do { __pthread_unwind_buf_t __cancel_buf; void (*__cancel_routine) (void *) = (hand); void *__cancel_arg = ("a"); int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) __cancel_buf.__cancel_jmp_buf, 0); if (__builtin_expect((__not_first_call), 0)) { __cancel_routine (__cancel_arg); __pthread_unwind_next (&__cancel_buf); }__pthread_register_cancel (&__cancel_buf);do {;printf("This is thread [%u]\n", (unsigned int)pthread_self());do { } while (0); } while (0); __pthread_unregister_cancel (&__cancel_buf); if (1) __cancel_routine (__cancel_arg); } while (0);return ((void *)0); }
可以看到,我们输出线程信息的 printf 语句,被一层层的 do{}while(0) 给包围了。 如果在 pthread_cleanup_push() 和 pthread_cleanup_pop() 之间加一个 return , 那么整个 do{}while(0) 就会被跳出,后面的代码肯定也就不会被执行了。
本文转自郝峰波博客园博客,原文链接:http://www.cnblogs.com/fengbohello/p/7571730.html,如需转载请自行联系原作者
POSIX 线程清理函数相关推荐
- APUE2勘误-11.5节 线程终止(关于线程清理处理程序)
平台:Linux 2.6.28-19-generic 书中讲解所用的linux版本为Linux 2.4.22,我没有在此版本上做实验的机会,只是在当前用的版本上做了测试,问题原因可能是Linux内核版 ...
- Posix线程编程指南(4) 线程终止
线程终止方式 一般来说,Posix的线程终止有两种情况:正常终止和非正常终止.线程主动调用pthread_exit()或者从线程函数中return都将使线程正常退出,这是可预见的退出方式:非正常终止是 ...
- POSIX线程专有数据的空间释放问题,pthread_key_create
下面说一下线程中特有的线程存储, Thread Specific Data .线程存储有什么用了?他是什么意思了?大家都知道,在多线程程序中,所有线程共享程序中的变量.现在有一全局变量,所有线程都可以 ...
- POSIX 线程详解
一种支持内存共享的简捷工具 简介: POSIX(可移植操作系统接口)线程是提高代码响应和性能的有力手段.在本系列中,Daniel Robbins 向您精确地展示在编程中如何使用线程.其中还涉及大量幕后 ...
- posix线程使用详解
原文:http://blog.csdn.net/liuhongxiangm/article/details/8308697 Posix多线程编程学习笔记(一)-线程基础(1) 一.什么是线程 ...
- POSIX线程的同步
当线程运行在同样的线程空间,线程们共享同样的内存和资源.这使它变得很容易对于线程来通信和共享数据,尽管它会发生两种问题:线程阻塞和内存不一致由于线程的同步对共享资源的修改.在这些情况下,线程同步变得很 ...
- 通用线程:POSIX 线程详解,第 2部分——称作互斥对象的小玩意
通用线程:POSIX 线程详解,第 2部分--称作互斥对象的小玩意 Daniel Robbins (drobbins@gentoo.org), 总裁/CEO, Gentoo Technologies, ...
- posix 线程(一)
1.POSIX线程库 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以"pthread_"开头,要使用这些函数库,要通过引入头文<pthread.h>,而 ...
- linux网络编程之posix线程(二)
继续接着上次的posix线程来学习: 回顾一下创建线程的函数: pthread_att_t属性变量是需要进行初始化才能够用的,一定初始化了属性变量,它就包含了线程的多种属性的值,那到底有哪些属性了,下 ...
最新文章
- 027_自己实现一个ArrayList
- 解决ansible报错“msg“: “Failed to import docker-py - cannot import name __version__.
- linux脚本ls输出到变量中,bash – 将命令输出的错误消息存储到shell变量中
- 《自然》年度十大人物:天才曹原居首 贺建奎来去匆匆
- SQLAlchemy orm.query.Query
- bootstrap pagewrapper_BootStrap table服务端分页
- Python自学笔记-map和reduce函数(来自廖雪峰的官网Python3)
- import tool for Scripter Studio
- CentOS下常用配置文件和命令以及目录结构备注
- python语言程序设计实践教程陈东_20193323实验三《Python程序设计》实验报告
- 组合逻辑电路的分析与设计
- E+H电磁流量计你知道多少?
- 聚沙成塔的分布式云存储
- 46、建筑防烟排烟系统的维护保养要求
- HTML5自学笔记上
- 58同城2014校园招聘软件测试笔试题
- x264源码分析与应用示例(一)——视频编码基本流程
- 力天创见热区统计方案
- MATLAB聚类分析--------2019/8/22
- 《2021爱智先行者—精灵1号边缘计算机》
热门文章
- CSS中Position定位属性的使用
- java8 interface_Java8新特性:函数式接口@FunctionalInterface使用说明
- mysql 表名是变量_MySQL深层次的总结
- mysql int 判断_PHP通过PDO查MySQL查询int字段返回string类型,解决方案
- opencv ubuntu 汉字_OpenCV在ubuntu下的编译
- mysql缺失值处理方法,插值MySQL表中的缺失值
- Maven和Eclipse整合
- VB获取windows各常用目录的函数(模块)
- 选课中应用Redis一些思考
- Jupyter Notebook的三大短板,都被这个新工具补齐了