下面实现了一个通用的线程封装类Thread<T>
提供start()(创建线程)、join()(等待线程结束)、detach()(分离线程)、stop()(标记线程停止状态)等接口,覆盖了线程的基本操作需求。
#ifndef __THREAD_HPP__
#define __THREAD_HPP__
#include <pthread.h>
#include <iostream>
#include <string>
#include <functional>
namespace ThreadModule
{
template<typename T>
using func_t = std::function<void(T)>;//将 std::function<void()> 这个类型起一个别名 func_t, 用于保存传入T参数,返回值为void的函数(可调用对象)
template<typename T>
class Thread
{
private:
void Excute()
{
_func(_data);
return;
}
public:
Thread(func_t<T> func, T data, const std::string &name="none-name")
: _func(func), _data(data), _threadname(name), _stop(true)
{}
// static void *threadroutine(void* args)//类成员函数,形参是有this指针的,所以在前面要加static
// {
// _func(_data);
// return nullptr;
// }
static void *threadroutine(void* args)//类成员函数,形参是有this指针的,所以在前面要加static
{
Thread<T> *self = static_cast<Thread<T>*>(args);
self->Excute();
return nullptr;
}
std::string name() const
{
return _threadname;
}
bool start()
{
int n = pthread_create(&_tid, nullptr, threadroutine, this);
if(n != 0)//创建线程失败
{
return false;
}
else//创建线程成功
{
_stop = false;
return true;
}
}
void detach()
{
if(!_stop)
{
pthread_detach(_tid);
}
}
void join()
{
if(!_stop)
{
pthread_join(_tid, nullptr);
}
}
void stop()
{
_stop = true;
}
~Thread(){}
private:
pthread_t _tid;
std::string _threadname;
T _data;
func_t<T> _func;
bool _stop;
};
}
#endif // __THREAD_HPP__
细节一:
原生线程被使用时,类内成员函数被使用时,要加static,去掉this指针。
因为调用pthread_creare时传入的函数有格式要求只能是形如void *function(void* args),返回值必须是void类型,传入参数只有一个,是void类型。
但是在类中,作为成员函数,这个void *threadroutine(void* args)函数的第一个参数实际上是this指针(Thread* const this),用来传递自己属于哪个对象的。
所以这里要加上static,变成一个类的专属,这时没有this指针,符合pthread_creare时传入的函数的格式要求。
细节二:
static void *threadroutine(void* args)
{
_func(_data);//这个函数无法直接用_data
return nullptr;
}
这里是行不通的,加了static已经无this指针了,直接用_data是不行的(原因:函数是在公共代码区,调用时不知道是哪个对象调用,需要this指针指明,但是这里由于加了static,没有this指针)。
解决方法:可以间接的用其他成员函数去调用_data。
private:
void Excute()
{
_func(_data);
return;
}
public:
// static void *threadroutine(void* args)
// {
// _func(_data);
// return nullptr;
// }
static void *threadroutine(void* args)
{
Thread<T> *self = static_cast<Thread<T>*>(args);//这时args里面要传一个类对象,利用这个对象去调用Excute从而访问_data
self->Excute();
return nullptr;
}
这种写法是 C++ 中使用类成员函数作为线程入口的标准范式,既满足了pthread_create对函数格式的要求(静态函数,无隐含this),又通过显式传递对象指针实现了对类内部资源的访问。
858

被折叠的 条评论
为什么被折叠?



