Thread系列的RAII封装

采用c++封装了Thread,线程私有数据TSD,线程池:

#include<iostream>
#include<pthread.h>
#include<unistd.h>
#include<boost/shared_ptr.hpp>
#include<boost/weak_ptr.hpp>
#include<boost/noncopyable.hpp>
#include<boost/function.hpp>
#include<boost/bind.hpp>
#include<boost/ptr_container/ptr_vector.hpp>
#include<string>
#include<deque>
#include<algorithm>
#include<sys/syscall.h>
#include<stdio.h>
#include<assert.h>
#include"Mutex.hpp"
using namespace std;
using namespace boost;
/*
 *线程类Thread
 */
__thread pid_t t_cacheTid=0;//线程私有数据线程ID避免通过系统调用获得ID
class Thread:noncopyable{
    public:
        typedef function<void()> ThreadFunc;//线程需要执行工作函数
        explicit Thread(const ThreadFunc& a,const string& name=string()):started_(false),
            joinded_(false),pthreadID_(0),tid_(new pid_t(0)),func_(a),name_(name){
            }
        ~Thread(){
            if(started_&&!joinded_){
                pthread_detach(pthreadID_);//分离线程
            }
        }
        void start();
        /*
        {
            assert(!started_);
            started_=true;
            if(pthread_create(&pthreadID_,NULL,&startThread,NULL)){
                started_=false;
                abort();//终止进程刷新缓冲区
            }
        }
        *///###1###使用此处会出错详见http://cboard.cprogramming.com/cplusplus-programming/113981-passing-class-member-function-pthread_create.html
        void join(){//等待线程执行完工作函数
            assert(started_);
            assert(!joinded_);
            joinded_=true;
            pthread_join(pthreadID_,NULL);
        }
        pid_t tid() const{
            if(t_cacheTid==0){//如果没有缓存t_cacheTid则获取线程ID否则直接通过线程私有数据返回ID减少系统调用
                t_cacheTid=syscall(SYS_gettid);
            }
            return t_cacheTid;
        }
        const string& name() const{
            return name_;
        }
        //void* startThread(void* arg){//###1###
        void startThread(){
            func_();
        }
    private:
        bool started_;
        bool joinded_;
        pthread_t pthreadID_;
        shared_ptr<pid_t> tid_;
        ThreadFunc func_;
        string name_;
};
void* threadFun(void* arg){//采用间接层执行工作函数
    Thread* thread=static_cast<Thread*>(arg);
    thread->startThread();
}
void Thread::start(){
    assert(!started_);
    started_=true;
    if(pthread_create(&pthreadID_,NULL,threadFun,this)){
        started_=false;
        abort();//终止进程刷新缓冲区
    }
}

/*
 * 线程局部数据TSD
 */
template<typename T>
class ThreadLocal:noncopyable{
    public:
        ThreadLocal(){
            pthread_key_create(&pkey_,&destructor);//每个线程会设定自己的pkey_并在pthread_key_delete执行destructor操作
        }
        ~ThreadLocal(){
            pthread_key_delete(pkey_);//执行destructor操作
        }
        T& value(){//采用单件模式,此处不会跨线程使用故不存在非线程安全的singleton问题
            T* perThreadValue=static_cast<T*>(pthread_getspecific(pkey_));
            if(!perThreadValue){
                T* newObj=new T();
                pthread_setspecific(pkey_,newObj);
                perThreadValue=newObj;
            }
            return *perThreadValue;
        }
    private:
        static void destructor(void* x){//清除私有数据
            T* obj=static_cast<T*>(x);
            delete obj;
        }
    private:
        pthread_key_t pkey_;
};
/*
 * 线程池
 */
class ThreadPool:noncopyable{
    public:
        typedef function<void()> Task;//线程工作函数
        explicit ThreadPool(const string& name=string()):mutex_(),cond_(mutex_),name_(name),running_(false){
        }
        ~ThreadPool(){
            if(running_){
                stop();//等待所有线程池中的线程完成工作
            }
        }
        void start(int numThreads){
            assert(threads_.empty());
            running_=true;
            threads_.reserve(numThreads);
            for(int i=0;i<numThreads;i++){
                threads_.push_back(new Thread(bind(&ThreadPool::runInThread,this)));//池中线程运行runInThread工作函数
                threads_[i].start();
            }
        }
        void stop(){
            running_=false;//可以提醒使用者不要在此后添加任务了,因为停止池但是池还要等待池中线程完成任务
            cond_.notifyALL();//唤醒池中所有睡眠的线程
            for_each(threads_.begin(),threads_.end(),bind(&Thread::join,_1));//等待池中线程完成
        }
        void run(const Task& task){
            if(running_){//###4###防止停止池运行后还有任务加进来
                if(threads_.empty()){//池中没有线程
                    task();
                }
                else{
                    MutexLockGuard guard(mutex_);//使用RAII mutex保证线程安全
                    queue_.push_back(task);
                    cond_.notify();
                }
            }
            else{
                printf("线程池已停止运行\n");
            }
        }
        bool running(){//使用者可以获取线程池的运行状态
            return running_;
        }
    private:
        void runInThread(){//线程工作函数
            while(running_){//###2###
                Task task(take());
                if(task){//task可能意外的为NULL
                    task();
                }
            }
        }
        Task take(){
            MutexLockGuard guard(mutex_);
            while(queue_.empty()&&running_){//###3###和###2###不能保证在池停止运行但是线程还没有完成操作期间安全。假设此期间有任务添加到池中,且某个线程A执行到###2###后马上被切换了,池running_=false停止运行,A被切换后运行执行###3###处无意义啊,因为池已经停止运行了。所以###4###是有必要提醒使用者池停止这一情景
                cond_.wait();//池中没有任务等待
            }
            Task task;
            if(!queue_.empty()){
                task=queue_.front();
                queue_.pop_front();
            }
            return task;
        }
        Mutex mutex_;
        Condition cond_;
        string name_;
        ptr_vector<Thread> threads_;//智能指针容器
        deque<Task> queue_;
        bool running_;
};
/*
 *测试代码
 */
class test{
    public:
        test(){
            printf("test::constructor\n");
        }
        ~test(){
            printf("test::deconsturctor\n");
        }
};
void worker1(){
    ThreadLocal<test> one;
    test two=one.value();//线程局部数据会在线程结束时释放
    printf("worker1\n");
}
void worke2(){
    printf("worker2\n");
}
void worker3(){
    printf("worker3\n");
    sleep(1);
}
int main(){
    Thread one(worker1);
    one.start();
    one.join();
    ThreadPool two;
    two.start(2);
    two.run(worke2);
    two.run(worker3);
    two.stop();
    return 0;
}

运行结果:

test::constructor
worker1                     //单个线程的输出
test::deconsturctor  //以上是线程私有数据在线程结束时释放
worker2        //线程池的输出
worker3


头文件Mutex.hpp

#include<iostream>
#include<string>
#include<unistd.h>
#include<pthread.h>
#include<assert.h>
#include<boost/utility.hpp>
using namespace std;
using namespace boost;
/*
*互斥量
*/
class Mutex:noncopyable{
    public:
        Mutex(){
            pthread_mutex_init(&mutex,NULL);
        }
        void lock(){
            pthread_mutex_lock(&mutex);
        }
        void unlock(){
            pthread_mutex_unlock(&mutex);
        }
        pthread_mutex_t& get(){
            return mutex;
        }
    private:
        pthread_mutex_t mutex;
};
/*
*互斥量RAII
*/
class MutexLockGuard:noncopyable{
    public:
        explicit MutexLockGuard(Mutex& mutex):mutex_(mutex){
            mutex_.lock();
        }
        ~MutexLockGuard(){
            mutex_.unlock();
        }
    private:
        Mutex& mutex_;
};
/*
*条件变量
*/
class Condition:noncopyable{
    public:
        explicit Condition(Mutex& mutex):mutex_(mutex){
            pthread_cond_init(&pcond_,NULL);
        }
        ~Condition(){
            pthread_cond_destroy(&pcond_);
        }
        void wait(){
            pthread_cond_wait(&pcond_,&mutex_.get());
        }
        void notify(){
            pthread_cond_signal(&pcond_);
        }
        void notifyALL(){
            pthread_cond_broadcast(&pcond_);
        }
    private:
        Mutex& mutex_;
        pthread_cond_t pcond_;
};
/*
*倒计时闩
*/
class CountDownLatch{
    public:
        CountDownLatch(int count):mutex_(),condition_(mutex_),count_(count){}
        void wait(){
            MutexLockGuard lock(mutex_);
            while(count_>0)
                condition_.wait();
        }
        void countDown(){
            MutexLockGuard lock(mutex_);
            --count_;
            if(count_==0)
                condition_.notifyALL();
        }
    private:
        mutable Mutex mutex_;
        Condition condition_;
        int count_;
};


你可能感兴趣的:(Thread系列的RAII封装)