libzmq源码阅读 之 thread_t
最近阅读了ZeroMQ源码的poll的实现,看到类 thread_t 挺有意思,记录一下。
我认为,这个thread_t
是对pthead的一层封装,弄成C++的模样。
thread.hpp
#include <pthread.h>
namespace zmq {
typedef void (thread_fn) (void*); // 定义个类型‘线程函数’,function
class thread_t{
public:
inline thread_t(): // 没搞懂为什么要显示的使用inline
tfn(NULL),
args(NULL) {
}
void start(thread_fn *tfn, void *args); //启动线程
void stop(); // 终止线程
thread_fn *tfn; // 函数指针, void (*)(void *)
void *args; // 函数参数
private:
pthread_t descriptor; // 线程描述符
};
}
thread.cpp
#include "thread.h"
extern "C" { // pthread.h是 C 接口,这里拓展了C特性。
// 由于是用pthread,所以要用static void *xxx(void *args)
static void *thread_routine(void *args_) {
// args_ is "this" argument, point to the thread itself.
zmq::thread_t *self = (zmq::thread_t*)args_;
// 函数调用在此!
self->tfn(self->args);
return NULL;
}
}
void zmq::thread_t::start(thread_fn *tfn_, void *args_) {
tfn = tfn_;
args = args_;
int rc = pthread_create(&descriptor, NULL, thread_routine, this);
}
void zmq::thread_t::stop() {
int rc = pthread_join(descriptor, NULL);
}
那么怎么用呢?举个例子,我们现在想启动一个线程运行kqueue_t
中的loop()
循环。很有意思,loop()
是成员函数,为了把他暴露出来传递给thread_t,这里用了一个worker_routine()
。
kqueue.cpp
void zmq::kqueue_t::start ()
{
// worker 是 kqueue_t 的成员,类型是 thread_t。
worker.start(worker_routine, this);
}
void zmq::kqueue_t::loop() {
...
}
// 头文件原型是这样子的:static void worker_routine (void *arg_);
void zmq::kqueue_t::worker_routine (void *arg_)
{
// 这里传入的 arg_ 是this指针,指向kqueue自己。
((kqueue_t*) arg_)->loop ();
return;
}