優雅的cancel一個pthread線程

這是一個基本的問題。仔細看看man pages,應該就可以理解其中的道理。不過我看到的幾個man pages的詳略程度有所不同。關鍵的函數是pthread_cleanup_push()和pthread_cleanup_pop()以及由此衍生出來的xxx_np(不可移植版本)。

更詳細的信息可以參考NPTL的代碼:http://code.metager.de/source/xref/gnu/glibc/nptl/pthread_cond_wait.c

$ cat pthread.cc

/*
* See man page for the details.
* See the following link, too.
* https://computing.llnl.gov/tutorials/pthreads/man/pthread_cleanup_push.txt
*
* $ g++ -Wall -pthread pthread.cc
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int condition = 1;
int count = 0;
int unlock = 1;

void
cleanup_handler(void *arg)
{
  printf("Called clean-up handler\n");
  if (unlock)
  {
    int rc = pthread_mutex_unlock(&mutex);
    printf("cleanup_handler.rc=%d\n", rc);
  }
}

void *
produce(void *arg)
{
  pthread_cleanup_push(cleanup_handler, NULL);

  while(1)
  {
    pthread_mutex_lock( &mutex );
    while( condition == 1)
      pthread_cond_wait( &cond, &mutex );
    printf("Produced %d\n", count++);
    pthread_mutex_unlock( &mutex );
  }

  pthread_cleanup_pop(0);
  return( 0 );
}

void usage(void)
{
  printf("Usage: ./a.out <unlock_or_not>\n");
  printf("       unlock_or_not is 1 or 0.\n");
  exit(1);
}

int main(int argc, char *argv[])
{
   if (argc != 2)
     usage();

   if (strcmp(argv[1], "1") == 0)
     unlock = 1;
   else if (strcmp(argv[1], "0") == 0)
     unlock = 0;
   else
     usage();

   pthread_t thd_produce;
   pthread_create(&thd_produce, NULL, &produce, NULL );
   sleep(1);
   pthread_cancel(thd_produce);
   pthread_join(thd_produce, NULL);
   int rc = pthread_mutex_destroy(&mutex);
   printf("rc=%d\n", rc);
   return 0;
}
發佈了94 篇原創文章 · 獲贊 9 · 訪問量 309萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章