当前位置:网站首页>webrtc中的任务队列TaskQueue
webrtc中的任务队列TaskQueue
2022-08-04 05:25:00 【mo4776】
在webrtc中,有一个任务队列TaskQueue,在视频编码模块中就是通过它是实现编码线程,这篇文章将讲解它的实现和应用场景。
TaskQueue
-任务队列 TaskQueue的用途是将任务放到到另外一个线程执行,与std::aysnc功能相似,但是它不能取得执行结果。任务队列是多线程编程下的基础设施,是一种线程间交互手段。
一个TaskQueue对象就代表了一个任务执行线程,在构造时产生线程,在析构时结束线程。
TaskQeueue采用Pimpl技术实现,它提供的是接口,内部的impl_对象封装了具体实现,如下类图,TaskQueue通过impl_持有一个TaskQueueBase类型的对象。

它的构造函数传入一个TaskQueueBase的实例。
explicit TaskQueue(std::unique_ptr<webrtc::TaskQueueBase,
webrtc::TaskQueueDeleter> task_queue);
TaskQueue的接口
这里列出它的主要的四个接口: PostTask,PostDelayedTask,isCurrent,Current
PostTask和PostDelayedTask
一个是将task放入TaskQueue立即执行,一个将task放入TaskQueue,指定delay后时间执行。
TaskQueue类中有两个类型的接口PostTask和PostDelayedTask,重载了两种不同类型的参数,一个是传入QueueTask对象,一个是传入Closure(Clousre是模板参数),Closure使用更加方便,它可以传入一个lambda表达式。
isCurrent和Current
isCurrent可以用于判断任务是否运行在TaskQueue对象所代表的线程上Current 获取任务线程关联的TaskQueue对象
这两个方法基于thread_local类型的变量实现(即线程局部变量),每个线程都有自己的局部变量,在线程内可见,线程间不可见。所以不需要对该类型的变量进行互斥。
首先定义了一个thread_local类型的TaskQueueBase指针
thread_local TaskQueueBase* current = nullptr;
在线程执行时,赋值为this
那么isCurrent的实现如下:
bool IsCurrent() const { return Current() == this; }
Current的实现如下:
TaskQueueBase* TaskQueueBase::Current() {
return current;
}
TaskQueue对象就代表了一个线程,它可以在任意其它线程使用,在任务中调用IsCurrent()方法可以判断它是否在TaskQueue对象所代表的线程上执行。通过这种方式人为的将任务分发到指定的线程,而避免加锁互斥。
TaskQueueBase具体子类
前面提到 TaskQueue只是封装接口,TaskQueueBase才是真正的实现,但它是个抽象接口类,如下图

有4个具体的实现类``TaskQueueStdlib,TaskQueueWin,TaskQueueLibevent,TaskQueueGcd,分别对应的不同平台的具体实现
- TaskQueueStdlib 跨平台通用版本(linux下的实现,也可以用在windows环境下)
- TaskQueueWin 是windows下的实现
- TaskQueueLibevent 基于libevent实现
- TaskQueueGcd 是IOS下的实现
平台相关的实现主要是在线程的实现(webrtc中并没有使用C++ 11中thread,是自己封装了thread的API)和定时功能的实现,TaskQueueLibevent通过libevent实现定时,TaskQueueWin通过windows的消息队列实现定时。TaskQueueStdlib则是通过条件变量超时机制实现的定时。
TaskQueueBase对象创建
TaskQueueBase通过工厂类TaskQueueFactory来创建具体类型的实例,这个工厂类它还有一个工厂方法,用来创建不同的工厂类实例(有点绕- -!)
task_queue_factory.h中定义了创建TaskQueue的工厂类TaskQueueFactory,有多个工厂方法创建工厂类TaskQueueFactory。
如下代码,通过工厂类task_queue_factory创建一个TaskQueueBase对象,用于构造TaskQueue对象encoder_queue_。
//创建一个TaskQueue对象
rtc::TaskQueue encoder_queue_(task_queue_factory->CreateTaskQueue(
"EncoderQueue",
TaskQueueFactory::Priority::NORMAL));
用途
一个TaskQueue对象产生一个Task执行线程,它本质上是一个异步任务队列,将任务从一个线程分发至任务执行队列,可以起到线程隔离的作用,而减少同步的需求,比如将一系列关联方法放入任务队列可以减少互斥的使用,通过isCurrent判断方法是否运行在任务执行线程 ,如果是则无需添加同步措施。
可以将TaskQueue作为特定用途的线程,比如用作编码线程,将编码任务放入线程中。在webrtc中的视频编码就是如此。
代码实例
TaskQueue的使用比较简单,先通过工厂类创建一个TaskQueueBase的实例,再根据需求调用PostTask或PostDelayTask。在VideoStreamEncoder类中有个encoder_queue_的TaskQueue对象,示例如下:
//创建一个TaskQueue对象
rtc::TaskQueue encoder_queue_(task_queue_factory->CreateTaskQueue(
"EncoderQueue",
TaskQueueFactory::Priority::NORMAL));
//PostTask传入了一个lambada表达式,执行SendKeyFrame方法
encoder_queue_.PostTask([this] {
SendKeyFrame(); });
边栏推荐
- 7.18 Day23 - the markup language
- Dynamic programming of the division of numbers
- 8大软件供应链攻击事件概述
- Delphi-C端有趣的菜单操作界面设计
- 想低成本保障软件安全?5大安全任务值得考虑
- npm安装依赖报错npm ERR! code ENOTFOUNDnpm ERR! syscall getaddrinfonpm ERR! errno ENOTFOUND
- [One step in place] Jenkins installation, deployment, startup (complete tutorial)
- string类简介
- 7.13 Day20----MYSQL
- 7.13 Day20----MYSQL
猜你喜欢

部署LVS-DR群集【实验】

7.13 Day20----MYSQL

3面头条,花7天整理了面试题和学习笔记,已正式入职半个月

The idea setting recognizes the .sql file type and other file types

TSF微服务治理实战系列(一)——治理蓝图

Web Basics and Exercises for C1 Certification - My Study Notes

Can 't connect to MySQL server on' localhost3306 '(10061) simple solutions

谷粒商城-基础篇(项目简介&项目搭建)

Do you think border-radius is just rounded corners?【Various angles】

乱码解决方案
随机推荐
符号表
sql server如何得到本条记录与上一条记录的差异,即变动值
力扣题解8/3
Wwise入门和实战
OpenGLES 学习之帧缓存
Cannot read properties of null (reading 'insertBefore')
EventBus源码分析
What are the functions of mall App development?
C language -- operator details
Swoole学习(二)
C语言 -- 操作符详解
php实现telnet访问端口
力扣:63. 不同路径 II
MySQL log articles, binlog log of MySQL log, detailed explanation of binlog log
Several ways to heavy
高性能高可靠性高扩展性分布式防火墙架构
7、特殊SQL的执行
4.1 JdbcTemplate for declarative transactions
12、分页插件
少年成就黑客,需要这些技能