《ZLToolKit源码学习笔记》(1)VS2019源码编译
《ZLToolKit源码学习笔记》(2)工具模块之日志功能分析
《ZLToolKit源码学习笔记》(3)工具模块之终端命令解析
《ZLToolKit源码学习笔记》(4)工具模块之消息广播器
《ZLToolKit源码学习笔记》(5)工具模块之资源池
《ZLToolKit源码学习笔记》(6)线程模块之整体框架概述
《ZLToolKit源码学习笔记》(7)线程模块之线程池组件:任务队列与线程组
《ZLToolKit源码学习笔记》(8)线程模块之线程负载计算器
《ZLToolKit源码学习笔记》(9)线程模块之任务执行器(本文)
任务执行器是一个抽象接口类,定义了一套同步及异步执行任务的接口。
目录
系列文章目录
前言
一、概述
1.1、TaskExecutorInterface
1.1.1、异步执行任务
1.1.2、同步执行任务
1.2、TaskExecutor
TaskExecutor继承了ThreadLoadCounter和TaskExecutorInterface,其除了构造函数外,没有其他成员函数。因为TaskExecutorInterface是一个抽象类,所以TaskExecutor也是一个抽象类。
ThreadLoadCounter已经在前面学习过,本节只看下TaskExecutorInterface和TaskExecutor。
virtual Task::Ptr async(TaskIn task, bool may_sync = true) = 0; virtual Task::Ptr async_first(TaskIn task, bool may_sync = true); Task::Ptr TaskExecutorInterface::async_first(TaskIn task, bool may_sync) { return async(std::move(task),may_sync); }
async是一个纯虚函数,需要派生类来实现, async_first需要将任务插入到队列头部优先执行,虽然该类中默认直接调用了async,但实际使用时,用户需要重新定义该函数。
void TaskExecutorInterface::sync(const TaskIn &task) { semaphore sem; auto ret = async([&]() { onceToken token(nullptr, [&]() { //通过RAII原理防止抛异常导致不执行这句代码 sem.post(); }); task(); }); if (ret && *ret) { sem.wait(); } } void TaskExecutorInterface::sync_first(const TaskIn &task) { semaphore sem; auto ret = async_first([&]() { onceToken token(nullptr, [&]() { //通过RAII原理防止抛异常导致不执行这句代码 sem.post(); }); task(); }); if (ret && *ret) { sem.wait(); } }
同步执行任务sync通过调用async接口实现,接口阻塞在sem条件变量上,直到任务被异步执行完成触发post后,wait被唤醒,接口才能返回。所以,任务的执行实际是异步的,但该接口是同步的。
类似的,同步优先执行任务sync_first是通过async_first接口实现。
TaskExecutor(uint64_t max_size = 32, uint64_t max_usec = 2 * 1000 * 1000);
该类没有其它成员函数,构造函数中,指定了线程负载计算器的统计样本数量和统计时间范围。默认情况下,样本数量是32,时间范围是最近2秒钟(时间单位是微秒)。