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 线程详解 一种支持内存共享的简捷工具
线程是有趣的 了解如何正确运用线程是每一个优秀程序员必备的素质.线程类似于进程.如同进程,线程由内核按时间分片进行管理.在单处理器系统中,内核使用时间分片来模拟线程的并发执行,这种方式和进程的相同.而 ...
随机推荐
- 20165220实验二《Java面向对象程序设计》
实验封面: 实验二 面向对象程序设计-1 实验要求: 参考 http://www.cnblogs.com/rocedu/p/6371315.html#SECUNITTEST 参考http://www. ...
- Ajax技术使用之ajax与模态框结合的妙用
Ajax技术使用之ajax与模态框结合的妙用 要求: 使用ajax的方式提交数据:https://www.cnblogs.com/-wenli/p/10470063.html 使用模态框完成增加数据, ...
- redis+mysql
redis和mysql要根据具体业务场景去选型 mysql:数据放在磁盘 redis:数据放在内存 redis适合放一些频繁使用,比较热的数据,因为是放在内存中,读写速度都非常快,一般会应用在下面 ...
- Jmeter压测过程报错the target server failed to respond
失败事务报错信息如下, Socket closed Non HTTP response code: org.apache.http.NoHttpResponseException (the targe ...
- excel计算时间差值
excel计算时间差值 2018/10/1 10:59:00 减去 2018/9/21 1:05:13 获取 多少天. 如1.2天.这种. ==
- npm install报错Unhandled rejection RangeError: Maximum call stack size exceededill install
故障 在使用npm install下载依赖的时候报错Unhandled rejection RangeError: Maximum call stack size exceededill instal ...
- java加载类的顺序
一.什么时候会加载类?使用到类中的内容时加载:有三种情况1.创建对象:new StaticCode();2.使用类中的静态成员:StaticCode.num=9; StaticCode.show() ...
- shell脚本8--录制终端会话
准备: script -t 2> timing.log -a output.session type commands; ... . .. exit 回放: scriptreplay timin ...
- 2017.08.15【NOIP提高组】模拟赛B组
Summary 今天比赛很差很差,掉到谷底.第一题快排打错了,漏了递归,变成一个while循环.最后一题k忘记减一,答案一直是无穷大,所以没交.第三题没时间调DP就打了个递归,第二题状态想歪了.四道题 ...
- input中autocomplete属性
autocomplete="off":表示刷新页面时,input中的value值清空 <input type="text" id="q" ...