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();
pthread_cleanup_pop();
pthread_cleanup_pop(); 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 ;
}
编译并运行:
This is thread []
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 ()
我们写个更简单的程序,把这两个宏展开后看一看是什么样结果:
代码如下:
# define pthread_cleanup_push(routine, arg) \
do { \
__pthread_cleanup_class __clframe (routine, arg) # define pthread_cleanup_pop(execute) \
__clframe.__setdoit (execute); \
} while ()
编译:
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, ); if (__builtin_expect((__not_first_call), )) { __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 (); } while (); __pthread_unregister_cancel (&__cancel_buf); if () __cancel_routine (__cancel_arg); } while ();
return ((void *));
}
int main() {
return ;
}
可以看到,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, );
if (__builtin_expect((__not_first_call), )) {
__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 ();
} while ();
__pthread_unregister_cancel (&__cancel_buf);
if () __cancel_routine (__cancel_arg);
} while ();
return ((void *));
}
可以看到,我们输出线程信息的 printf 语句,被一层层的 do{}while(0) 给包围了。 如果在 pthread_cleanup_push() 和 pthread_cleanup_pop() 之间加一个 return , 那么整个 do{}while(0) 就会被跳出,后面的代码肯定也就不会被执行了。
同步地址:https://www.fengbohello.top/archives/linux-pthread-cleanup
POSIX 线程清理函数的更多相关文章
- POSIX 线程取消点的 Linux 实现
http://blog.csdn.net/stevenliyong/article/details/4364039 原文链接:http://blog.solrex.cn/articles/linux- ...
- 三十七、Linux 线程——线程清理和控制函数、进程和线程启动方式比较、线程的状态转换
37.1 线程清理和控制函数 #include <pthread.h> void pthread_cleanup_push(void (* rtn)(void *), void *arg) ...
- Linux的POSIX线程属性
创建POSIX线程的函数为 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routin ...
- posix 线程(一):线程模型、pthread 系列函数 和 简单多线程服务器端程序
posix 线程(一):线程模型.pthread 系列函数 和 简单多线程服务器端程序 一.线程有3种模型,分别是N:1用户线程模型,1:1核心线程模型和N:M混合线程模型,posix thread属 ...
- POSIX多线程——基本线程管理函数介绍
POSIX基本的几个线程管理函数见下表: ------------------------------------------------------------------------------- ...
- POSIX多线程之创建线程pthread_create && 线程清理pthread_cleanup
多线程之pthread_create创建线程 pthreads定义了一套C程序语言类型.函数.与常量.以pthread.h和一个线程库实现. 数据类型: pthread_t:线程句柄 pthread_ ...
- Posix线程编程指南(4) 线程终止
线程终止方式 一般来说,Posix的线程终止有两种情况:正常终止和非正常终止.线程主动调用pthread_exit()或者从线程函数中return都将使线程正常退出,这是可预见的退出方式:非正常终止是 ...
- Posix线程编程指南(2) 线程私有数据
概念及作用 在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据.在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有.但有时应用程序设计中有必要提供 ...
- POSIX 线程详解 一种支持内存共享的简捷工具
线程是有趣的 了解如何正确运用线程是每一个优秀程序员必备的素质.线程类似于进程.如同进程,线程由内核按时间分片进行管理.在单处理器系统中,内核使用时间分片来模拟线程的并发执行,这种方式和进程的相同.而 ...
随机推荐
- Java中的不同遍历方式
已知一个Person类: public class Person implements Comparable<Person>{ String name; String id; public ...
- 比特币源码分析--C++11和boost库的应用
比特币源码分析--C++11和boost库的应用 我们先停下探索比特币源码的步伐,来分析一下C++11和boost库在比特币源码中的应用.比特币是一个纯C++编写的项目,用到了C++11和bo ...
- Best Cow Fences POJ - 2018 (二分)
Farmer John's farm consists of a long row of N (1 <= N <= 100,000)fields. Each field contains ...
- python 配置导入方式
许多连接,如 from setting import redis_config pool= redis.ConnectionPool(**redis_config) r=redis.Redis(con ...
- SpringMvc请求处理流程与源码探秘
流程梳理 dispatcherServlet作为前端控制器的主要作用就是接受请求与处理响应. 不过它不是传统意义上的servlet,它在接受到请求后采用转发的方式,将具体工作交给专业人士去做. 参与角 ...
- am335x uboot2016.05 (MLO u-boot.img)执行流程(转)
am335x的cpu上电后,执行流程:ROM->MLO(SPL)->u-boot.img 第一级bootloader:引导加载程序,板子上电后会自动执行这些代码,如启动方式(SDcard. ...
- Linux学习笔记8
其他常用命令 cd+回车=回车~ 进入当前用户主目录 查看指定进程信息 #ps -ef |grep 进程名 #ps ---查看属于自己的进程 #ps -aux 查看所有用户的执行进程 换成 p ...
- 【Excel】SUMIF 或用 筛选器 实现挑选含有某些字段的值,然后把这些值所对应的后面某列上的值相加
Background: 挑选含有某些字段的值,然后把这些值所对应的后面某列上的值相加.比如挑选下表中,所有带有“MX104”这个字段的值,然后把它的后面total那一列的值相加. Solution: ...
- elementUI的table组件实现setCurrentRow的滚动条定位效果
在github上咨询了,直接给了代码: https://jsfiddle.net/tk37c5cb/14/
- 【树形期望DP】BZOJ3566- [SHOI2014]概率充电器
[题目大意] 充电器由 n-1 条导线连通了 n 个充电元件.这n-1条导线均有一个通电概率p%,而每个充电元件本身有直接被充电的概率q[i]%.问期望有多少个充电元件处于充电状态? [思路] 第一次 ...