pthread_clean_push与pthread_cleanup_pop函数:- #include <pthread.h>
-
- void pthread_cleanup_push(void (*routine)(void *), void *arg);
- void pthread_cleanup_pop(int execute);
这两个函数操作调用线程的“线程取消时的清理函数的栈”。(These functions manipulate the calling thread's stack of thread-cancellation clean-up handlers.)“线程取消函数”即线程被取消或者下面描述的情况发生时自动调用的函数。它一般用于释放一些资源,比如释放锁,以免其它的线程永远也不能获得锁,而造成死锁。
pthread_cleanup_push()函数执行压栈清理函数的操作,而pthread_cleanup_pop()函数执行从栈中删除清理函数的操作。
在下面三种情况下,pthread_cleanup_push()压栈的“清理函数”会被调用:
1, 线程调用pthread_exit()函数,而不是直接return.
2, 响应取消请求时,也就是有其它的线程对该线程调用pthread_cancel()函数。
3, 本线程调用pthread_cleanup_pop()函数,并且其参数非0.
所以:
1)当pthread_cleanup_pop()函数的参数为0时,仅仅在线程调用pthread_exit函数或者其它线程对本线程调用
pthread_cancel函数时,才在弹出“清理函数”的同时执行该“清理函数”。
2)注意pthread_exit终止线程与线程直接return终止线程的区别。
3)pthread_cleanup_push()函数与pthread_cleanup_pop()函数必须成对的出现在同一个函数中。
下面是man pthread_cleanup_push中的一个例子:
- #include <pthread.h>
-
#include <sys/types.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
#include <errno.h>
-
-
#define handle_error_en(en, msg) \
-
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
-
-
static int done = 0;
-
static int cleanup_pop_arg = 0;
-
static int cnt = 0;
-
-
static void cleanup_handler(void *arg)
-
{
-
printf("Called clean-up handler\n");
-
cnt = 0;
-
}
-
-
static void *thread_start(void *arg)
-
{
-
time_t start, curr;
-
-
printf("New thread started\n");
-
pthread_cleanup_push(cleanup_handler, NULL);
-
curr = start = time(NULL);
-
while(!done){
-
pthread_testcancel(); /* A cancellation point */
-
if(curr < time(NULL)){
-
curr = time(NULL);
-
printf("cnt = %d\n", cnt); /* A cancellation point */
-
cnt++;
-
}
-
}
-
-
pthread_cleanup_pop(cleanup_pop_arg);
-
return NULL;
-
}
-
-
int main(int argc, char *argv[])
-
{
-
pthread_t thr;
-
void *res;
-
-
pthread_create(&thr, NULL, thread_start, NULL);
-
sleep(2); /* Allow new thread to run a while */
-
-
if(argc > 1){
-
if(argc > 2)
-
cleanup_pop_arg = atoi(argv[2]);
-
done = 1;
-
-
}else{
-
printf("Canceling thread\n");
-
pthread_cancel(thr);
-
}
-
-
pthread_join(thr, &res);
-
if(res == PTHREAD_CANCELED)
-
printf("Thread was canceled; cnt = %d\n", cnt);
-
else
-
printf("Thread terminated normally; cnt = %d\n", cnt);
-
exit(EXIT_SUCCESS);
-
}
执行情况:
- digdeep@ubuntu:~/pthread/learnthread$ ./cleanup
-
New thread started
-
cnt = 0
-
cnt = 1
-
Canceling thread
-
Called clean-up handler
-
Thread was canceled; cnt = 0
-
digdeep@ubuntu:~/pthread/learnthread$ ./cleanup a
-
New thread started
-
cnt = 0
-
cnt = 1
-
Thread terminated normally; cnt = 2
-
digdeep@ubuntu:~/pthread/learnthread$ ./cleanup a 2
-
New thread started
-
cnt = 0
-
cnt = 1
-
Called clean-up handler
-
Thread terminated normally; cnt = 0
-
digdeep@ubuntu:~/pthread/learnthread$
执行./cleanup 时,因为 argc > 1不成立,所以调用了pthread_cancel(thr);所以线程是被“取消”的,所以pthread_cleanup_push压栈的函数一点会被调用。
执行./cleanup a 时,argc > 1,但是pthread_cleanup_push()的参数cleanup_pop_arg为0,也没有调用pthread_cancel(thr);所以线程是被pthread_join(thr, &res);正常完成的,没有pthread_exit。所以不会调用pthread_cleanup_push()压栈的清理函数。
执行./cleanup a 2 时,cleanup_pop_arg != 0,所以即使线程不是被“取消”的,但是因为pthread_cleanup_pop的参数不是0,所以pthread_cleanup_pop函数在弹出“清理函数”的同时也会执行该“清理函数”。
阅读(2064) | 评论(0) | 转发(0) |