Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1786247
  • 博文数量: 413
  • 博客积分: 8399
  • 博客等级: 中将
  • 技术积分: 4325
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-09 10:44
文章分类

全部博文(413)

文章存档

2015年(1)

2014年(18)

2013年(39)

2012年(163)

2011年(192)

分类: C/C++

2011-11-21 10:44:31

pthread_clean_push与pthread_cleanup_pop函数:
  1. #include <pthread.h>

  2. void pthread_cleanup_push(void (*routine)(void *), void *arg);
  3. 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中的一个例子:
  1. #include <pthread.h>
  2. #include <sys/types.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <errno.h>

  7. #define handle_error_en(en, msg) \
  8. do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

  9. static int done = 0;
  10. static int cleanup_pop_arg = 0;
  11. static int cnt = 0;

  12. static void cleanup_handler(void *arg)
  13. {
  14.         printf("Called clean-up handler\n");
  15.         cnt = 0;
  16. }

  17. static void *thread_start(void *arg)
  18. {
  19.         time_t start, curr;

  20.         printf("New thread started\n");
  21.         pthread_cleanup_push(cleanup_handler, NULL);
  22.         curr = start = time(NULL);
  23.         while(!done){
  24.                 pthread_testcancel(); /* A cancellation point */
  25.                 if(curr < time(NULL)){
  26.                         curr = time(NULL);
  27.                         printf("cnt = %d\n", cnt); /* A cancellation point */
  28.                         cnt++;
  29.                 }
  30.         }

  31.         pthread_cleanup_pop(cleanup_pop_arg);
  32.         return NULL;
  33. }

  34. int main(int argc, char *argv[])
  35. {
  36.         pthread_t thr;
  37.         void *res;

  38.         pthread_create(&thr, NULL, thread_start, NULL);
  39.         sleep(2); /* Allow new thread to run a while */

  40.         if(argc > 1){
  41.                 if(argc > 2)
  42.                         cleanup_pop_arg = atoi(argv[2]);
  43.                 done = 1;

  44.         }else{
  45.                 printf("Canceling thread\n");
  46.                 pthread_cancel(thr);
  47.         }

  48.         pthread_join(thr, &res);
  49.         if(res == PTHREAD_CANCELED)
  50.                 printf("Thread was canceled; cnt = %d\n", cnt);
  51.         else
  52.                 printf("Thread terminated normally; cnt = %d\n", cnt);
  53.         exit(EXIT_SUCCESS);
  54. }
执行情况:
  1. digdeep@ubuntu:~/pthread/learnthread$ ./cleanup
  2. New thread started
  3. cnt = 0
  4. cnt = 1
  5. Canceling thread
  6. Called clean-up handler
  7. Thread was canceled; cnt = 0
  8. digdeep@ubuntu:~/pthread/learnthread$ ./cleanup a
  9. New thread started
  10. cnt = 0
  11. cnt = 1
  12. Thread terminated normally; cnt = 2
  13. digdeep@ubuntu:~/pthread/learnthread$ ./cleanup a 2
  14. New thread started
  15. cnt = 0
  16. cnt = 1
  17. Called clean-up handler
  18. Thread terminated normally; cnt = 0
  19. 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) |
0

上一篇:service命令解析

下一篇:C语言中的sizeof

给主人留下些什么吧!~~