天天看點

對Pthread線程進行簡單的類封裝       1.封裝遇到的問題 2.使用靜态函數

       将Pthreads線程封裝為抽象類,這樣使用者在使用線程時,隻需要繼承一下這個抽象類,并實作相應的接口就可以了。這樣做的好處是使用者可以将注意力集中線上程所要執行的邏輯上,而不需要關注建立線程、銷毀線程等細節問題上。這裡給出兩種簡單的封裝方法,以供參考。

       我們抽象類的名稱為Thread,其中有一個成員函數run,該函數為的聲明形式為:

       void run() = 0;

       即将該成員函數聲明為純虛函數,使用者繼承此類必須要實作此成員函數。Thread中還有另外一個成員函數start,該函數的聲明形式為:

       void start();

       使用者在子類中調用start方法,将啟動線程,并線上程中執行run函數。

       最常想到的方法就是在start方法中使用pthread_create建立一個線程,并調用run函數。如下面這樣的實作:

void start() 

    { 

           int status; 

           status = pthread_create(_pThread,NULL,Thread::run,NULL); 

           if(status != 0) 

                  err_abort(“creating thread failure”,status); 

    } 

       這樣編譯肯定是不能通過的,這是因為pthread_create要求的線程例程的接口形式為:

       void *(*thread_routin)(void *args);

       而上面代碼中提供的線程例程的接口形式為:

       void Thread::run()

       顯然不符合要求的接口。

       為了能夠在start中調用run函數,我們不得不采用一種迂回的方式。下面提供兩種方法:一種是使用靜态成員函數,另外一種是使用友元函數。

       靜态成員函數的作用域是全局的,而不僅僅局限于某個函數中。靜态成員函數的實作方法和C語言中的普通函數類似,是以靜态函數沒有this指針,靜态函數隻能操作靜态成員變量。之是以将靜态函數封裝到類中,在很大程度上也隻是為了滿足面向對象的特性之一-----封裝性。

       下面是一個簡單的使用靜态成員函數調用類中某個函數的例子,這個例子僅僅作為一個引子:

/* 

 * main.cpp 

 * 

 *  Created on: Jul 24, 2012 

 *      Author: lichao 

 */ 

#include <iostream> 

#include <pthread.h> 

#include <time.h> 

#include "lc_error.h" 

using namespace std; 

class MyThread 

public: 

       void run() 

       { 

              fprintf(stdout,"I'm a little tired.Sleep for a while.\n"); 

              fflush(stdout); 

              sleep(5); 

       } 

       static void * thread_proxy_func(void * args) 

              MyThread * pMyThread = static_cast<MyThread *>(args); 

              pMyThread->run(); 

              return NULL; 

       virtual ~MyThread(){} 

}; 

int main(int argc,char *argv[]) 

       MyThread t; 

       pthread_t thread; 

       int status; 

       status = pthread_create(&thread,NULL,MyThread::thread_proxy_func,(void *)&t); 

       if(status != 0) 

              err_abort("creating thread error...\n",status); 

       status = pthread_join(thread,NULL); 

              err_abort("joining thread...\n",status); 

       return 0; 

       需要特别注意的是mian函數中使用pthread_create的執行例程為MyThread類中的線程代理函數thread_proxy_func,在此函數中在調用run函數,這樣就順利的迂回到了run函數。基于這種方法,我們可以用靜态函數來封裝一個簡單的抽象類,以下為封裝的代碼,由三個檔案構成:Thread.h(類的聲明檔案),Thread.cpp(類的實作檔案),main.cpp(測試檔案):

      /* 

 * Thread.h 

#ifndef THREAD_H_ 

#define THREAD_H_ 

class Thread 

       Thread(); 

       ~Thread(); 

       virtual void run() = 0; 

       void start(); 

       void wait();       

private: 

    static void * thread_proxy_func(void *args); 

       pthread_t * _pThread; 

#endif /* THREAD_H_ */ 

 * Thread.cpp 

#include "Thread.h" 

Thread::Thread() 

       _pThread = (pthread_t *)malloc(sizeof(pthread_t)); 

       if(NULL == _pThread) 

              error_abort("malloc error...\n"); 

Thread::~Thread() 

       if(NULL != _pThread) 

              delete _pThread; 

void Thread::start() 

       status = pthread_create(_pThread,NULL,thread_proxy_func,this); 

              err_abort("creating thread...\n",status); 

void * Thread::thread_proxy_func(void *args) 

       Thread * pThread = static_cast<Thread *>(args); 

       pThread->run(); 

       return NULL; 

void Thread::wait() 

       status = pthread_join(*_pThread,NULL); 

              err_abort("joining thread error...\n",status); 

3.使用友元函數

       友元函數的作用和靜态函數相同,都起到一個代理的作用。需要将對象的指針作為參數傳遞給這個友元函數,然後在友元函數中調用run函數。代碼如下,

由三個檔案構成:Thread.h(類的聲明檔案),Thread.cpp(類的實作檔案),main.cpp(測試檔案):

       friend void * proxy_thread_func(void * args); 

       virtual ~Thread(); 

       virtual void run(void) = 0; 

       void wait(); 

       pthread_t * _thread; 

void * proxy_thread_func(void * args); 

void * proxy_thread_func(void * args) 

       Thread * _thread = static_cast<Thread *>(args); 

       _thread->run(); 

       _thread = (pthread_t * )malloc(sizeof(pthread_t)); 

       if(NULL == _thread) 

              error_abort("malloc failure...\n"); 

       if(_thread != NULL) 

              delete _thread; 

       status = pthread_create(_thread,NULL,proxy_thread_func,this); 

       status = pthread_join(*_thread,NULL); 

              err_abort("joing thread...\n",status); 

 * main.c 

class MyThread:public Thread 

              cout<<"I'm a littile tired. Sleep for a while..."<<endl; 

       t.start(); 

       t.wait(); 

 本文轉自hipercomer 51CTO部落格,原文連結:http://blog.51cto.com/hipercomer/941682

繼續閱讀