Bo——使用基于对象的方法封装一个线程库-- function<> & bind
function<> & bind
std::fuinction<R(T1,T2,T3…Tn)>
☞这是一个模板实现的函数对象类,它可以包装其它任意的函数对象,而被包装的函数对象具有类型为T1,T2,…,TN的参数,其返回值为R类型
☞function 对象的最大用处在于实现函数回调
std::bind()
☞bind是这样一种机制,它可以预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调用实体
☞绑定的参数的个数不受限制
☞绑定的具体哪些参数也不受限制,由用户指定
☞bind预先绑定的参数需要传具体的变量或值进去,是pass-by-value(值传递)的
☞对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增
☞bind的返回值是可调用实体,可以直接赋给std::function对象
基于对象 线程库UML类图
Thread.h
// Created by 60263 on 2020/10/16.
// This is
#ifndef __THREAD_H_
#define __THREAD_H_
#include "Noncopyable.hpp"
#include <pthread.h>
#include <functional>
namespace wd {
class Thread : public Noncopyable {
public:
using ThreadCallback = std::function<void()>;
Thread(ThreadCallback && cb);//传递bind绑定的函数对象
~Thread();
void start();
void join();
private:
static void* threadFunc(void * arg);//线程函数
pthread_t _pthid;//线程id
bool _isRunning;//判断线程是否运行
ThreadCallback _cb;//function函数对象
};
}
#endif //__THREAD_H_
Thread.cpp
// Authors: Handling
// Created by 60263 on 2020/10/16.
// This is
#include "Thread.h"
namespace wd {
Thread::Thread(ThreadCallback &&cb) : _pthid(0),
_isRunning(false),
_cb(std::move(cb)) {}
Thread::~Thread() {
if(_isRunning){
pthread_detach(_pthid);//如果线程仍在运行则detach交给系统托管
}
}
void Thread::start() {
if(pthread_create(&_pthid, nullptr,threadFunc,this)){//threaFunc必须为static如果是成员函数
//则它默认含有this参数,再传参的时候会报错。
perror("pthread_create");
return;
}
_isRunning =true;
}
void Thread::join() {
if(_isRunning){
pthread_join(_pthid, nullptr);
}
}
void* Thread::threadFunc(void *arg) {
Thread *p = static_cast<Thread *>(arg);//传递进来的是this,即thread对象的入口地址
if(p){
p->_cb();
}
return nullptr;
}
}
TestMain.cpp
#include "Thread.h"
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <memory>
#include <iostream>
using std::cout;
using std::endl;
using std::unique_ptr;
void run(){
::srand(::time(nullptr));
int cnt = 20;
while (cnt-- >0){
int number = ::rand()%100;
cout << "threadid " << pthread_self()
<< ": number = " << number << endl;
::sleep(1);
}
}
class Task
{
public:
void process()
{
cout << "Task::process()" << endl;
run();
}
void execute(int x, int y)
{
cout << "Task::execute(int,int)" << x << "," << y << endl;
}
};
void test0()
{
cout << "main thread: " << pthread_self() << endl;
//unique_ptr<wd::Thread> mythread(new wd::Thread(run));
unique_ptr<Task> ptask(new Task());
//基于对象的写法会更灵活
unique_ptr<wd::Thread> mythread(new wd::Thread(
std::bind(&Task::process, ptask.get())));//ptask.get()代表this指针
//std::bind(&Task::execute, ptask.get(), 1, 2)));
//
//提前绑定参数时, bind采用的是值传递, 会对Task() 临时对象进行复制
//std::bind(&Task::execute, Task(), 1, 2)));
mythread->start();
mythread->join();
}
int main() {
test0();
return 0;
}
运算结果
如主程序所示,借用智能指针托管,thread在创建对象的时候参数列表中创建临时对象临时对象又使用bind函数绑定了不同实现的回调函数,十分灵活。
总结一下总体思路:
在Thread类中注册一个 function<void()>的回调函数,这个回调函数会在thread对象创建时通过bind函数绑定。之后手动调用start成员函数,进行了子线程的创建,子线程函数threadFunc中调用回调函数。
bind的参数为可变参数,它可以传递一个task()临时对象也可以通过。ptask.get()获取对象的this指针。