Linux组件封装(三)使用面向对象编程封装Thread
C++11提供了thread,但是过于复杂,我们还是倾向于在项目中编写自己的Thread。
Posix Thread的使用这里不再赘述。
重点是这个函数:
#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
第三个参数是一个回调函数,该函数必须返回值为void*,而且只有一个参数,类型也是void*。
POSIX的thread默认是joinable,需要手工调用pthread_join函数来回收,也可以调用pthread_detach将其变为detachable,此时不需要手工回收线程。
下面介绍Thread的封装。
我们把Thread的声明先放在这里:
#ifndef THREAD_H_ #define THREAD_H_ #include "NonCopyable.h" #include <pthread.h> class Thread : NonCopyable { public: Thread(); virtual ~Thread(); void start(); void join(); virtual void run() = 0; pthread_t getThreadId() const { return threadId_; } private:
//提供给pthread_create的第三个参数使用 static void *runInThread(void *arg); pthread_t threadId_; //pid_t tid_; //进程标示 bool isRunning_; }; #endif //THREAD_H_
这里需要说明的是:
首先,为了获得最干净的语义,Thread应该是不可复制的,所以需要继承NonCopyable。
其次,为了调用pthread_create创建线程,我们往里面注册的不能是一个成员函数,因为成员函数含有一个隐式参数,导致函数的指针类型并不是void *(*start_routine) (void *),所以我们采用了static函数。
static函数无法访问某一对象的成员,所以我们在调用pthread_create时,将this指针作为回调函数的参数。
这里相关代码如下:
//static void *Thread::runInThread(void *arg) { Thread *pt = static_cast<Thread*>(arg); //pt->tid_ = syscall(SYS_gettid); pt->run(); return NULL; }
这个Thread不提供detach函数,因为我们在析构函数中做了如下的处理,如果Thread对象析构,线程还在运行,那么需要将Thread设置为detach状态。
Thread::~Thread() { if(isRunning_) { pthread_detach(threadId_); } }
大部分逻辑都是固定的,用户只需要改变run里面的代码即可,于是我们将run设置为纯虚函数,让用户继承Thread类。
所以析构函数为virtual。
完整的CPP实现如下:
#include "Thread.h" #include <assert.h> #include <unistd.h> #include "MutexLock.h" //TINY_CHECK Thread::Thread() :threadId_(0), isRunning_(false) { } Thread::~Thread() { if(isRunning_) { TINY_CHECK(!pthread_detach(threadId_)); } } //static void *Thread::runInThread(void *arg) { Thread *pt = static_cast<Thread*>(arg); //pt->tid_ = syscall(SYS_gettid); pt->run(); return NULL; } void Thread::start() { TINY_CHECK(!pthread_create(&threadId_, NULL, Thread::runInThread, this)); isRunning_ = true; } void Thread::join() { assert(isRunning_); TINY_CHECK(!pthread_join(threadId_, NULL)); isRunning_ = false; }
测试代码如下:采用继承的方式使用这个类。
#include "Thread.h" #include <iostream> #include <unistd.h> using namespace std; class MyThread : public Thread { public: void run() { cout << "foo" << endl; } }; int main(int argc, char const *argv[]) { MyThread t; t.start(); t.join(); return 0; }
NonCopyable类的定义如下:
#ifndef NONCOPYABLE_H #define NONCOPYABLE_H class NonCopyable //禁用值语义 { public: NonCopyable() { } ~NonCopyable() { } private: NonCopyable(const NonCopyable &); void operator=(const NonCopyable &); }; #endif //NONCOPYABLE_H