线程封装

Linux下原始的API使用起来不方便,为了便于使用,尝试封装线程相关API。

看了《Linux多线程服务端编程》,陈硕是基于对象来封装的,使用了boost::bind来创建函数对象,把函数对象作为线程运行的函数。我这次尝试面向对象的封装,创建一个线程基类,子类继承这个基类,实现线程运行的主体函数即可。基类如下:

class BaseThread
{
public:
    BaseThread(const std::string& name);
    virtual ~BaseThread();
     void Run();
    void Join();
    static void* ThreadProxy(void* argument);
protected:
    virtual void DoTask() = 0;

private:
    void Initilization();
    bool initilized_;
    bool started_;
    bool joined_;
    pthread_t pthreadId_;
    pid_t tid_;
    std::string name_;

};

变量中包含了线程的名字、id(整数)、线程标识符、是否启动、初始化等。纯虚函数DoTask即为线程运行的主体函数,在子类实现这个函数即可。

静态函数ThreadProxy是线程创建后执行的入口。因为线程创建API

int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,
(void*)(*start_rtn)(void*),void *arg);

start_rtn是线程创建后执行的函数,因为静态函数有this指针,不能作为线程的入口函数。解决办法1、使用全局函数。这样就难以访问类的private和protected成员。2、友元函数。3、静态函数。
我使用了静态函数的方法。

来看一下实现

BaseThread::BaseThread(const std::string& name)
    :initilized_(false),
    started_(false),
    joined_(false),
    pthreadId_(0),
    tid_(pid_t(0)),
    name_(name)
{}
BaseThread::~BaseThread()
{
    if(initilized_ && started_ && !joined_)
        pthread_detach(pthreadId_);
}
void BaseThread::Run()
{
    assert(!started_);
    started_=true;
    //create the thread
    pthread_create(&pthreadId_,
        NULL,
        BaseThread::ThreadProxy,
        this);

}
void BaseThread::Join()
{
    assert(started_);
    assert(!joined_);
    pthread_join(pthreadId_, NULL);
}

/*staitc function used to call the real Task */
void* BaseThread::ThreadProxy(void* argument) 
{
    BaseThread* thread=static_cast<BaseThread*>(argument);
    thread->Initilization();
    thread->started_=true;
    thread->DoTask();
    return static_cast<void*> (0);

}

void BaseThread::Initilization() //must be called by the new thread
{
    tid_=static_cast<pid_t>(::syscall(SYS_gettid));
    initilized_=true;
}

在实现时,在Run中创建线程并执行线程函数,这里把this指针作为参数是为了方便在ThreadEntry中可以调用BaseThread类的其他成员。

在析构函数中,如果类析构时,线程已经运行且没有join,就分离它。

这样一个基本的封装就算完成了。关于线程的同步,参考muduo网络库做了封装。

下面写了几个测试:都是关于生产者消费者模型的,可以参考这里
1、生产者和消费者作为独立的类存在,在main函数中调度生产者类和消费者类。
这样实现,要求生产者和消费者同步的话,需要全局同步变量。实现参考这里:
https://github.com/KangRoger/ThreadLib/blob/master/test/ConsumerAndProductor/ConsumerAndProductor.cpp

2、生产者、消费者作为成员变量而存在,包含在类ConsumerAndProductor中。这时同步变量都作为生产者/消费者的私有变量,他们使用的互斥量和条件变量应该为同一个,可以使用指针或引用。
实现参考这里:
https://github.com/KangRoger/ThreadLib/blob/master/test/ConsumerAndProductor/ConsumerAndProductor2.cpp

线程生命周期管理还存在问题,后续完善。

你可能感兴趣的:(thread,linux)