当前位置: 首页 > news >正文

详解WebRTC rtc::Thread实现

rtc::Thread介绍

rtc::Thread类不仅仅实现了线程这个执行器(比如posix底层调用pthread相关接口创建线程,管理线程等),还包括消息队列(message_queue)的实现,rtc::Thread启动后就作为一个永不停止的event loop,没有任务待执行就阻塞等待,添加任务后就唤醒event loop,去执行任务,周而复始,直到调用stop退出event loop,退出线程(线程join)。

在WebRTC内部,可以将消息队列等同于event loop,消息队列为空,就进行阻塞等待。


class RTC_LOCKABLE Thread : public MessageQueue {

Thread关键接口

public:// Starts the execution of the thread.bool Start(Runnable* runnable = nullptr);// Tells the thread to stop and waits until it is joined.// Never call Stop on the current thread.  Instead use the inherited Quit// function which will exit the base MessageQueue without terminating the// underlying OS thread.virtual void Stop();virtual void Send(const Location& posted_from,MessageHandler* phandler,uint32_t id = 0,MessageData* pdata = nullptr);// Convenience method to invoke a functor on another thread.  Caller must// provide the |ReturnT| template argument, which cannot (easily) be deduced.// Uses Send() internally, which blocks the current thread until execution// is complete.// Ex: bool result = thread.Invoke<bool>(RTC_FROM_HERE,// &MyFunctionReturningBool);// NOTE: This function can only be called when synchronous calls are allowed.// See ScopedDisallowBlockingCalls for details.template <class ReturnT, class FunctorT>ReturnT Invoke(const Location& posted_from, FunctorT&& functor) {FunctorMessageHandler<ReturnT, FunctorT> handler(std::forward<FunctorT>(functor));InvokeInternal(posted_from, &handler);return handler.MoveResult();}// ProcessMessages will process I/O and dispatch messages until://  1) cms milliseconds have elapsed (returns true)//  2) Stop() is called (returns false)bool ProcessMessages(int cms);protected:// Blocks the calling thread until this thread has terminated.void Join();

MessageQueue关键接口

public:
virtual void Quit();// Get() will process I/O until:
//  1) A message is available (returns true)
//  2) cmsWait seconds have elapsed (returns false)
//  3) Stop() is called (returns false)
virtual bool Get(Message* pmsg,int cmsWait = kForever,bool process_io = true);virtual void Post(const Location& posted_from,MessageHandler* phandler,uint32_t id = 0,MessageData* pdata = nullptr,bool time_sensitive = false);
virtual void PostDelayed(const Location& posted_from,int cmsDelay,MessageHandler* phandler,uint32_t id = 0,MessageData* pdata = nullptr);
virtual void PostAt(const Location& posted_from,int64_t tstamp,MessageHandler* phandler,uint32_t id = 0,MessageData* pdata = nullptr);virtual void Dispatch(Message* pmsg);
virtual void ReceiveSends();protected:
void WakeUpSocketServer();MessageList msgq_ RTC_GUARDED_BY(crit_);
PriorityQueue dmsgq_ RTC_GUARDED_BY(crit_);

线程启动Start

调用Start接口启动底层线程,同时进入一个永不停止的event loop(除非调用Stop接口)
流程如下:
Start->pthread_create->PreRun->Run

void Thread::Run() {ProcessMessages(kForever);
}

在这里插入图片描述
最终通过Get接口获取消息去执行(Dispatch),Get获取不到消息就是进入阻塞状态(wait),等待有消息后被唤醒。
在这里插入图片描述

线程消息队列处理消息的流程ProcessMessage

  • 1、处理从其他线程发送的要在本线程去执行的消息,即同步调用
    在这里插入图片描述

接收者线程处理流程:
在这里插入图片描述在这里插入图片描述

发送者线程流程:
在这里插入图片描述

  • 2、处理延迟消息(存储在优先级队列)
    延迟消息是通过PostDelayed和PostAt接口调用然后push到优先级队列中(dmsgq_,小根堆)
    在这里插入图片描述

  • 3、异步消息(存储在普通队列里)
    延迟消息是通过Pos接口调用然后push到普通队列中(msgq_)
    在这里插入图片描述

任务提交方式(Invoke/Post)

webrtc内部消息其实是对待执行任务的封装,消息和任务可以认为是一个意思

消息要继承MessageHandler,实现OnMessage

class MessageHandler {public:virtual ~MessageHandler();virtual void OnMessage(Message* msg) = 0;protected:MessageHandler() {}private:RTC_DISALLOW_COPY_AND_ASSIGN(MessageHandler);
};

因为执行消息,实际上就是执行OnMessage(详见Dispatch接口实现)
在这里插入图片描述

上一章节其实已经把三种任务提交方式介绍过了
1、同步阻塞调用(Send,Invoke)
Invoke其实最终也是调用Send,Invoke是个函数模版,可以非常方便在目标执行线程执行函数然后获得返回值,Invoke实现如下:

  // Convenience method to invoke a functor on another thread.  Caller must// provide the |ReturnT| template argument, which cannot (easily) be deduced.// Uses Send() internally, which blocks the current thread until execution// is complete.// Ex: bool result = thread.Invoke<bool>(RTC_FROM_HERE,// &MyFunctionReturningBool);// NOTE: This function can only be called when synchronous calls are allowed.// See ScopedDisallowBlockingCalls for details.template <class ReturnT, class FunctorT>ReturnT Invoke(const Location& posted_from, FunctorT&& functor) {FunctorMessageHandler<ReturnT, FunctorT> handler(std::forward<FunctorT>(functor));InvokeInternal(posted_from, &handler);return handler.MoveResult();}void Thread::InvokeInternal(const Location& posted_from,MessageHandler* handler) {TRACE_EVENT2("webrtc", "Thread::Invoke", "src_file_and_line",posted_from.file_and_line(), "src_func",posted_from.function_name());Send(posted_from, handler);
}

调用方式举例:

bool result = thread.Invoke<bool>(RTC_FROM_HERE, &MyFunctionReturningBool);

2、异步非阻塞延迟调用
PostDelayed和PostAt

3、异步非阻塞调用
Post

线程退出Stop

void Thread::Stop() {MessageQueue::Quit();Join();
}void MessageQueue::Quit() {AtomicOps::ReleaseStore(&stop_, 1);WakeUpSocketServer();
}void Thread::Join() {if (!IsRunning())return;RTC_DCHECK(!IsCurrent());if (Current() && !Current()->blocking_calls_allowed_) {RTC_LOG(LS_WARNING) << "Waiting for the thread to join, "<< "but blocking calls have been disallowed";}#if defined(WEBRTC_WIN)RTC_DCHECK(thread_ != nullptr);WaitForSingleObject(thread_, INFINITE);CloseHandle(thread_);thread_ = nullptr;thread_id_ = 0;
#elif defined(WEBRTC_POSIX)pthread_join(thread_, nullptr);thread_ = 0;
#endif
}

相关文章:

详解WebRTC rtc::Thread实现

rtc::Thread介绍 rtc::Thread类不仅仅实现了线程这个执行器&#xff08;比如posix底层调用pthread相关接口创建线程&#xff0c;管理线程等&#xff09;&#xff0c;还包括消息队列&#xff08;message_queue)的实现&#xff0c;rtc::Thread启动后就作为一个永不停止的event l…...

阿赵UE学习笔记——13、贴花

阿赵UE学习笔记目录 大家好&#xff0c;我是阿赵。   继续学习虚幻引擎的使用。这次介绍一种特殊的材质类型&#xff0c;贴花。 一、获取贴花资源 在没有分析贴花的原理之前&#xff0c;可以先去获得一些免费的贴花资源来使用&#xff0c;比如在Quixel上面就有专门的一个资源…...

简单说说mysql的日志

今天我们通过mysql日志了解mysqld的错误日志、慢查询日志、二进制日志&#xff0c;redolog, undolog等。揭示它们的作用和用途&#xff0c;让我们工作中更能驾驭mysql。 redo 日志 如果mysql事务提交后发生了宕机现象&#xff0c;那怎么保证数据的持久性与完整性&#xff1f;…...

如何在CentOS安装DataEase数据分析服务并实现远程访问管理界面

如何在CentOS安装DataEase数据分析服务并实现远程访问管理界面 前言1. 安装DataEase2. 本地访问测试3. 安装 cpolar内网穿透软件4. 配置DataEase公网访问地址5. 公网远程访问Data Ease6. 固定Data Ease公网地址 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 202…...

HTTP请求传递参数方式【2024-02-01】

1、HTTP请求传递参数分类 1.1、按照请求方式分类 GET方法:通过查询字符串&#xff08;Query String&#xff0c;每个参数由参数名和参数值组成&#xff0c;使用等号 连接&#xff0c;不同参数之间使用 & 符号分隔&#xff09;的方式或直接将参数放在URL中来传递参数POST…...

Error: Projects must list all files or use an ‘include‘ pattern.

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…...

移动应用开发的方式

移动应用开发的方式(三种) Native App&#xff1a; 本地应用程序&#xff08;原生App&#xff09; Web App&#xff1a;网页应用程序&#xff08;移动web&#xff09; Hybrid App&#xff1a;混合应用程序&#xff08;混合App&#xff09; hybrid应用场景 1、微信公众号&…...

C#学习笔记_类(Class)

类的定义 类的定义是以关键字 class 开始&#xff0c;后跟类的名称。类的主体&#xff0c;包含在一对花括号内。 语法格式如下&#xff1a; 访问标识符 class 类名 {//变量定义访问标识符 数据类型 变量名;访问标识符 数据类型 变量名;访问标识符 数据类型 变量名;......//方…...

壹[1],Xamarin开发环境配置

1&#xff0c;环境 VS2022 注&#xff1a; 1&#xff0c;本来计划使用AndroidStudio&#xff0c;但是也是一堆莫名的配置让人搞得很神伤&#xff0c;还是回归C#。 2&#xff0c;MAUI操作类似&#xff0c;但是很多错误解来解去&#xff0c;且调试起来很卡。 3&#xff0c;最…...

SAM:基于 prompt 的通用图像分割模型

Paper: Kirillov A, Mintun E, Ravi N, et al. Segment anything[J]. arXiv preprint arXiv:2304.02643, 2023. Introduction: https://segment-anything.com/ Code: https://github.com/facebookresearch/segment-anything SAM 是 Meta AI 开发的一款基于 prompt 的通用视觉大…...

2024美赛数学建模C题思路+模型+代码+论文

2024美赛A-F题思路代码模型论文&#xff1a;2.2开赛第一时间更新&#xff0c;获取见文末名片 美赛流程以及经验分享 今天主要和大家分享一下我之前参加美赛的经验&#xff0c;主要分两部分来讲。一部分是美赛流程&#xff0c;另一部分是美赛经验。 一 美赛流程 比赛前&#x…...

npm run serve和npm run dev的区别

1. 功能&#xff1a;通常&#xff0c;"npm run serve"用于启动开发服务器&#xff0c;提供实时的开发环境&#xff0c;支持自动重新加载和热模块替换。这样可以在开发过程中实时查看代码更改的效果。而"npm run dev"可以是一个自定义的指令&#xff0c;用于…...

已解决:winform开发中删除某方法导致窗体设计报错

一、报错截图 二、解决方案 第一步&#xff0c;点击上图的转到代码 第二步&#xff0c;注释掉报错的部分&#xff08;代码前面加//&#xff09; 第三步&#xff0c;重新编译 最后&#xff0c;恢复正常...

开源软件的影响力

开源软件如何推动技术创新 开源软件通过开放源代码,为全球开发者提供了共同的平台,促进了协作、交流,并推动了软件技术的创新和发展。以下是一些关键方面的分析: 透明度与信任: 开源软件的源代码是公开可见的,这种透明度带来了更高水平的信任。开发者和用户能够审查代码,…...

postgresql lc_ctype不同值之间的转换

LC_CTYPE 用于决定字元是否为数字,字母,空格,标点符号,及大小写等[1]。将 LC_CTYPE 设为「C」表示 isupper(c) 或 tolower(c) 等 C 语言函数[2]仅针对 US-ASCII 范围内的字元给出预期结果。因为像 upper()、lower() 或 initcap 这类型的Postgres SQL 语句是在libc 函数上实…...

纸盒生产ERP软件怎么样?常用纸盒生产ERP系统有哪几种

市场上的纸盒种类繁多&#xff0c;这些差异化的商品对应多元化的销售渠道和营销策略&#xff0c;日常的经营管理工作较为繁琐。而纸盒生产涉及原材料、发料、车间、工时评估、排产、质检、委外、工单等诸多流程&#xff0c;想要随时掌握各环节进度&#xff0c;及时处理存在的问…...

2024年重庆市考报名照上传失败的原因

2024年重庆市考报名照需要根据以下要求生成&#xff1a; 1、近期6个月&#xff0c;免冠证件照。 2、照片背景白底或者蓝底或者红底背景。 3、照片文件jpg格式&#xff0c;大小在20KB以下 4、照片像素大小&#xff0c;295*413像素 5、照片必须使用审核工具审核后才能上传...

2023年出版的新书中提到的《人月神话》(202402更新)(1)

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 《人月神话》于1975年出版&#xff0c;1995年出二十周年版。自出版以来&#xff0c;该书被大量的书籍和文章引用&#xff0c;直到现在热潮不退。 2023年&#xff0c;清华大学出版社推…...

gtkmm xml ui 例子(from string)

文章目录 前言来看一个从字符串中生成UI的例子 前言 glade生成的xml格式不被gtkmm4支持, 需要作修改 来看一个从字符串中生成UI的例子 #include <gtkmm/application.h> #include <gtkmm.h> #include <iostream> using namespace std;class ExampleWindow :…...

第2章 Linux 中执行命令

第2章 Linux 中执行命令 命令格式 命令 [选项] [参数....] 在linux 中命令分为内部命令和外部命令。 ctrll 可以清屏 查看帮助的命令 在使用命令之前&#xff0c;我们可以通过帮助来查看这个命令的格式和使用方式。在 Linux 中有两个帮助命令&#xff0c; help 和 man help…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

k8s从入门到放弃之HPA控制器

k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率&#xff08;或其他自定义指标&#xff09;来调整这些对象的规模&#xff0c;从而帮助应用程序在负…...

倒装芯片凸点成型工艺

UBM&#xff08;Under Bump Metallization&#xff09;与Bump&#xff08;焊球&#xff09;形成工艺流程。我们可以将整张流程图分为三大阶段来理解&#xff1a; &#x1f527; 一、UBM&#xff08;Under Bump Metallization&#xff09;工艺流程&#xff08;黄色区域&#xff…...