跨平台线程库——pThread

来源:互联网 发布:天书世界坐骑进阶数据 编辑:程序博客网 时间:2024/05/18 03:26
基本接口介绍:
1.   pthread_create 

  #include <pthread.h>

   int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg);

   创建一个由调用线程控制的新的线程并发运行。新的线程使用start_routine作为实现体,并以arg作为第一个参数。
   新的线程可以通过调用pthread_exit显式结束,或者通过start_routine return来隐式结束。其中后者等价于调用pthread_exit并以start_routine 的返回值作为退出码。
      新线程的初始信号状态继承自他的创建线程,并且没有挂起的信号。pthread-win32暂时未实现信号量。
      attr参数指明新线程的属性,如果attr=NULL,则使用默认属性:新线程是joinable(not detached),和默认的调度策略(非实时)
     返回值:如果成功,新线程的指针会被存储到thread的参数中,并返回0。如果错误则一个非0的错误码返回。
      如果返回EAGAIN,没有足够的系统资源创建一个线程,或者已经存在大于PTHREAD_THREADS_MAX个活跃线程。

2. pthread_exit
   #include <pthread.h>
   void pthread_exit(void *retval);
   
pthread_exit结束调用线程的执行.所有通过pthread_cleanup_push设置的清除句柄将会被反序执行(后进先出)。
 所以key值非空的线程特定数据Finalization functions被调用(参见pthread_key_create)。
  最后调用线程被终止。
  retval是这个线程结束的返回值,可以通过在别的线程中调用pthread_join来获取这个值。
   没有返回值。

3. pthread_join 
   #include <pthread.h>
   int pthread_join(pthread_t th, void **thread_return);    

   挂载一个在执行的线程直到该线程通过调用pthread_exit或者cancelled结束。(阻塞的方式等待指定的现成结束,释放线程资源)
   如果thread_return不为空,则线程th的返回值会保存到thread_return所指的区域。
   th的返回值是它给pthread_exit的参数,或者是pthread_canceled 如果是被cancelled的。
   被依附的线程th必须是joinable状态。一定不能是detached通过使用pthread_detach或者pthread_create中使用pthread_create_detached属性。
   当一个joinable线程结束时,他的资源(线程描述符和堆栈)不会被释放直到另一个线程对它执行pthread_join操作。
   如果成功,返回值存储在thread_return中,并返回0,否则返回错误码:
   ESRCH:找不到指定线程
   EINVAL:线程th是detached或者已经存在另一个线程在等待线程th结束
   EDEADLK:th的参数引用它自己(即线程不能join自身)

4.pthread_cancel   

  #include <pthread.h>
  int pthread_cancel(pthread_t thread);
  int pthread_setcancelstate(int state, int *oldstate);
  int pthread_setcanceltype(int type, int *oldtype);
  void pthread_testcancel(void);

   Cancellation是一种一个线程可以结束另一个线程执行的机制。更确切的说,一个线程可以发生Cancellation请求给另一个线程。
   根据线程的设置,收到请求的线程可以忽视这个请求,立即执行这个请求或者延迟到一个cancellation点执行。
   当一个线程执行Cancellation请求,相当于在那个点执行pthread_exit操作退出:所有cleanup句柄被反向调用,所有析构函数被调用结束线程并返回pthread_canceled.


5.pthread_cond   
   #include <pthread.h>
   pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
   int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
   int pthread_cond_signal(pthread_cond_t *cond);
   int pthread_cond_broadcast(pthread_cond_t *cond);
   int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
   int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
   int pthread_cond_destroy(pthread_cond_t *cond);

   
pthread_cond_init初始化条件变量,通过cond_attr,如果cond_attr是null则使用默认属性。也可以通过常量PTHREAD_COND_INITIALIZER静态初始化。
   pthread_cond_signal激活一个正在等待条件变量cond的线程。如果没有线程在等待则什么也不会发生,如果有多个线程在等待,则只能激活一个线程,带未指定是哪个线程(根据操作系统自己的调度策略选择)。
   pthread_cond_broadcast激活所有在等待条件变量cond的线程。
   pthread_cond_wait自动解锁mutex(pthread_unlock_mutex)等待条件变量cond发送。线程的执行被挂起不消耗cpu时间直到cond发送。在wait的入口mutex必须被锁住。
   在重新回到线程前,pthread_cond_wait会重新获得mutex(pthread_lock_mutex).解锁mutex和挂起是自动进行的。因此,如果所有线程在发送cond前都申请mutex的话,
   这种wait的内部实现机制能够保证在线程锁住mutex和线程wait之间不会有cond发送操作发送。
   pthread_cond_timedwaitpthread_cond_wait,只是多了个超时设置,如果超时,则重新获取mutex并且返回ETIMEDOUT,时间为绝对时间。
   pthread_cond_destroy销毁一个条件变量。必须没有线程在wait该条件变量。
   condition函数是异步信号不安全的,容易产生死锁,必须自己控制调用流程避免死锁。

6.semaphore
 #include <semaphore.h>
 int sem_init(sem_t *sem, int pshared, unsigned int value);
 int sem_wait(sem_t * sem);
 int sem_timedwait(sem_t * semconst struct timespec *abstime);
 int sem_trywait(sem_t * sem);
 int sem_post(sem_t * sem);
 int sem_post_multiple(sem_t * sem, int number);
 int sem_getvalue(sem_t * sem, int * sval);
 int sem_destroy(sem_t * sem);

 sem_init:
初始化信号量,pshared表示该信号量是否只属于当前进程(pshared==0),如果pshared不为0则表示可以在进程间共享。value表示该信号量的初始值。
  sem_wait:如果信号量的值大于0,则自动减1并立即返回。否则线程挂起直到sem_post或sem_post_multiple增加信号量的值。
  sem_timedwait:同sem_wait,只是多了个超时设置,如果超时,首先将全局变量errno设为ETIMEDOUT,然后返回-1.
  sem_trywait:如果信号量的值大于0,将信号量减1并立即返回,否则将全局变量errno设为ETIMEDOUT,然后返回-1。sem_trywait不会阻塞。
  sem_post:释放一个正在等待该信号量的线程,或者将该信号量+1.
  sem_post_multiple:释放多个正在等待的线程。如果当前等待的线程数n小于number,则释放n个线程,并且该信号量的值增加(number - n).
  sem_get_value:返回信号量的值。在pthread-win32实现中,正值表示当前信号量的值,负值的绝对值表示当前正在等待该信号量的线程数。虽然在POSIX不需要这么表示,但是也是同样含义。


  信号量(sem)与条件变量(cond)的主要差别在于,条件变量等待必须在发送之前,否则容易出现死锁,而信号量等待可以在发送之后执行。一句话概括信号量对于操作的时序没有要求。


几个测试程序:
1.

#include <QCoreApplication>#include <iostream>#include "pthread.h"pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void *Func1(void *);void *Func2(void *);int i = 1;int main(int argc, char *argv[]){    QCoreApplication a(argc, argv);#ifdef WIN32#ifdef PTW32_STATIC_LIB    pthread_win32_process_attach_np();    pthread_win32_thread_attach_np();#endif#endif    pthread_t thread1;    pthread_t thread2;    pthread_create(&thread1,NULL,Func1,(void*)NULL);    pthread_create(&thread2,NULL,Func2,(void*)NULL);    pthread_join(thread2,NULL);    pthread_mutex_destroy(&mutex);    pthread_cond_destroy(&cond);#ifdef WIN32#ifdef PTW32_STATIC_LIB    pthread_win32_process_detach_np();    pthread_win32_thread_detach_np();#endif#endif    system("Pause");    return a.exec();}void *Func1(void *junk){    for(i = 1;i <= 9;i++)    {        if(i%3==0)        {            pthread_mutex_lock(&mutex);            pthread_cond_signal(&cond);            pthread_mutex_unlock(&mutex);        }        else        {            std::cout << "thread1: " << i << std::endl;        }    }    return NULL;}void *Func2(void *junk){    while(i<9)    {        if(i%3!=0)        {            pthread_mutex_lock(&mutex);            pthread_cond_wait(&cond,&mutex);            pthread_mutex_unlock(&mutex);        }        else        {            std::cout << "thread2: " << i << std::endl;        }    }    return NULL;}


2.
#include <stdio.h>#include <Windows.h>#include "pthread.h"#include <ctype.h>typedef struct arg_set{    char *fname;    int count;    int tid;}ARG_SET;bool bWait = false;ARG_SET *mailbox = NULL;pthread_mutex_t read_lock = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t write_lock = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t read_cond = PTHREAD_COND_INITIALIZER;pthread_cond_t write_cond = PTHREAD_COND_INITIALIZER;void main(int ac, char *av[]){    pthread_win32_process_attach_np();    pthread_win32_thread_attach_np();    pthread_t t1, t2, t3;    ARG_SET args1, args2, args3;    void *count_words(void *);    int reports_in = 0;    int total_words = 0;    if (4 != ac)    {        printf("usage: %s file1 file2 file3\n", av[0]);        return;    }        args1.fname = av[1];    args1.count = 0;    args1.tid = 1;    pthread_create(&t1, NULL, count_words, (void *)&args1);    args2.fname = av[2];    args2.count = 0;    args2.tid = 2;    pthread_create(&t2, NULL, count_words, (void *)&args2);    args3.fname = av[3];    args3.count = 0;    args3.tid = 3;    pthread_create(&t3, NULL, count_words, (void *)&args3);    while(reports_in < 3)    {        printf("MAIN: waiting for flag to go up\n");        pthread_mutex_lock(&read_lock);        bWait = true;        pthread_cond_wait(&read_cond, &read_lock);        bWait = false;        pthread_mutex_unlock(&read_lock);        printf("MAIN: wow! flag was raised, I have the lock\n");        printf("MAIN: %7d: %s\n", mailbox->count, mailbox->fname);        total_words += mailbox->count;        Sleep(10);        printf("MAIN: Ok, I've read the thread %d mail\n", mailbox->tid);                pthread_mutex_lock(&write_lock);        pthread_cond_signal(&write_cond);        pthread_mutex_unlock(&write_lock);        printf("MAIN: raising write flag\n");        reports_in++;    }    printf("%7d: total words\n", total_words);    pthread_mutex_destroy(&read_lock);    pthread_mutex_destroy(&write_lock);    pthread_cond_destroy(&read_cond);    pthread_cond_destroy(&write_cond);    pthread_win32_thread_detach_np();    pthread_win32_process_detach_np();    system("pause");}void *count_words(void *a){    ARG_SET *args = (ARG_SET*)a;    FILE *fp;    int c, prevc = '\0';    if (NULL != (fp = fopen(args->fname, "r")))    {        while((c = getc(fp)) != EOF)        {            if (!isalnum(c) && isalnum(prevc))            {                args->count++;            }            prevc = c;        }        fclose(fp);    }    else    {        perror(args->fname);    }    printf("COUNT %d: waiting to get lock\n", args->tid);                pthread_mutex_lock(&write_lock);      if (NULL != mailbox)    {        printf("COUNT %d: oops..mailbox not empty. wait for signal\n", args->tid);        pthread_cond_wait(&write_cond, &write_lock);    }    printf("COUNT %d: OK, I can write mail\n", args->tid);    mailbox = args;          while (!bWait)    {        Sleep(1);            }    pthread_mutex_lock(&read_lock);     pthread_cond_signal(&read_cond);    /* raise the flag */    pthread_mutex_unlock(&read_lock);     printf("COUNT %d: raising read flag\n", args->tid);    pthread_mutex_unlock(&write_lock);    /* release the mailbox */    printf("COUNT %d: unlocking box\n", args->tid);        return NULL;}

3.

#include <stdio.h>#include <Windows.h>#include "pthread.h"#include "semaphore.h"#include <ctype.h>typedef struct arg_set{    char *fname;    int count;    int tid;}ARG_SET;ARG_SET *mailbox = NULL;static sem_t sem_write;static sem_t sem_read;void main(int ac, char *av[]){    pthread_win32_process_attach_np();    pthread_win32_thread_attach_np();    pthread_t t1, t2, t3;    ARG_SET args1, args2, args3;    void *count_words(void *);    int reports_in = 0;    int total_words = 0;    if (4 != ac)    {        printf("usage: %s file1 file2 file3\n", av[0]);        return;    }    if (-1 == sem_init(&sem_read, 0 , 1)        || -1 == sem_init(&sem_write, 0, 0))    {        return;    }    args1.fname = av[1];    args1.count = 0;    args1.tid = 1;    pthread_create(&t1, NULL, count_words, (void *) &args1);        args2.fname = av[2];    args2.count = 0;    args2.tid = 2;    pthread_create(&t2, NULL, count_words, (void *) &args2);        args3.fname = av[3];    args3.count = 0;    args3.tid = 3;    pthread_create(&t3, NULL, count_words, (void *) &args3);    while(reports_in < 3)    {        printf("MAIN: waiting for sub thread write\n");        sem_wait(&sem_write);        printf("MAIN: %7d: %s\n", mailbox->count, mailbox->fname);        total_words += mailbox->count;        if ( mailbox == &args1)             pthread_join(t1,NULL);        if ( mailbox == &args2)             pthread_join(t2,NULL);        if ( mailbox == &args3)             pthread_join(t3,NULL);                mailbox = NULL;        printf("MAIN: Ok,I have read the mail\n");        sem_post(&sem_read);          reports_in++;    }       printf("%7d: total words\n", total_words);    sem_destroy(&sem_read);    sem_destroy(&sem_write);    pthread_win32_thread_detach_np();    pthread_win32_process_detach_np();    system("pause");}void *count_words(void *a){    struct arg_set *args = (arg_set *)a;    /* cast arg back to correct type */    FILE *fp;    int  c, prevc = '\0';         if ( (fp = fopen(args->fname, "r")) != NULL )    {         while( ( c = getc(fp)) != EOF )         {               if ( !isalnum(c) && isalnum(prevc) )               {                    args->count++;               }               prevc = c;         }         fclose(fp);     } else           perror(args->fname);     printf("COUNT %d: waiting for main thread read the mail\n", args->tid);     sem_wait(&sem_read);     printf("COUNT %d:OK,I can write mail\n", args->tid);     mailbox = args;            /* put ptr to our args there */     printf("COUNT %d: Finished writting\n", args->tid);     sem_post(&sem_write);     return NULL;}

http://www.cppblog.com/saha/articles/189802.html
1 0
原创粉丝点击