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 线程详解 一种支持内存共享的简捷工具
线程是有趣的 了解如何正确运用线程是每一个优秀程序员必备的素质.线程类似于进程.如同进程,线程由内核按时间分片进行管理.在单处理器系统中,内核使用时间分片来模拟线程的并发执行,这种方式和进程的相同.而 ...
随机推荐
- 实现手写数字识别(数据集50000张图片)比较3种算法神经网络、灰度平均值、SVM各自的准确率—Jason niu
对手写数据集50000张图片实现阿拉伯数字0~9识别,并且对结果进行分析准确率, 手写数字数据集下载:http://yann.lecun.com/exdb/mnist/ 首先,利用图片本身的属性,图片 ...
- 浅析Linux服务器集群系统技术
浅析Linux服务器集群系统技术 目录 前言 常用的服务器集群 集群系统的优势 LVS集群的通用体系结构 为什么使用层次的体系结构 为什么是共享存储 可伸缩Web服务 前言 总结两篇技术文章,努力学习 ...
- 移动端滑屏全应用【三】requestAnimationFrame的兼容与使用
首先,传统做动画的方式有以下几种: 1. css的transition过度动画 2. css的animation动画 3. 使用setTimeout或setInterval模拟动画贞(js执行机制决定 ...
- Linux 查看文件被那个进程写数据
目录 背景 步骤 获取写文件的进程号 文件被那个进程使用,写数据不是用lsof可以找出来吗,但现实情况是lsof没找出来T_T 背景 centos7 在某一段时间监控报警磁盘使用率达99%,由于监控属 ...
- mongoose update操作属性中的变量
最近在学习mongoose操作数据库,利用schema模型.记录一下通过使用update()操作实现数据库更新: 可在属性中添加变量,'属性名.0',可以修改该属性的第一条属性,依次类推,但是如果想实 ...
- Beautifulsoup关于find的测试
from bs4 import BeautifulSoup import requests url='https://book.douban.com/subject_search?search_tex ...
- LOJ.2718.[NOI2018]归程(Kruskal重构树 倍增)
LOJ2718 BZOJ5415 洛谷P4768 Rank3+Rank1无压力 BZOJ最初还不是一道权限题... Update 2019.1.5 UOJ上被hack了....好像是纯一条链的数据过不 ...
- 常用的Lambda表达式
Java 8 引入Lambda表达式,对于Java开发人员来说是一大福利,简化了代码,提高了开发效率. 本文主要讲解日常开发中使用频率比较高的几类Lambda表达式. 集合 Lambda表达式的引入 ...
- Vue发送请求
可以试试玩ajax请求,个人觉得axios用Promise包装了下,代码美观 axios请求使用方法 https://github.com/axios/axios#using-applica ...
- js 倒计时10s
<button id="send">允许点击</button> var wait = 10; function time(o){ if(wait==0){ ...