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

webrtc 源码阅读 make_ref_counted模板函数用法

目录

1. 模板参数解析

1.1 typename T

1.2 typename... Args

1.3 typename std::enable_if::value, T>::type* = nullptr

2. scoped_refptr

3. new RefCountedObject(std::forward(args)...);

4. 综合说明

5.在webrtc中的用法

5.1 peerConnectionFactory对象的构建过程


先看make_ref_counted模板函数的定义

template <typename T,typename... Args,typename std::enable_if<std::is_convertible<T*, RefCountInterface*>::value,T>::type* = nullptr>
scoped_refptr<T> make_ref_counted(Args&&... args) {return new RefCountedObject<T>(std::forward<Args>(args)...);
}
template <class T>
class RefCountedObject : public T {public:RefCountedObject() {}template <class P0>explicit RefCountedObject(P0&& p0) : T(std::forward<P0>(p0)) {}template <class P0, class P1, class... Args>RefCountedObject(P0&& p0, P1&& p1, Args&&... args): T(std::forward<P0>(p0),std::forward<P1>(p1),std::forward<Args>(args)...) {}void AddRef() const override { ref_count_.IncRef(); }RefCountReleaseStatus Release() const override {const auto status = ref_count_.DecRef();if (status == RefCountReleaseStatus::kDroppedLastRef) {delete this;}return status;}// Return whether the reference count is one. If the reference count is used// in the conventional way, a reference count of 1 implies that the current// thread owns the reference and no other thread shares it. This call// performs the test for a reference count of one, and performs the memory// barrier needed for the owning thread to act on the object, knowing that it// has exclusive access to the object.virtual bool HasOneRef() const { return ref_count_.HasOneRef(); }protected:~RefCountedObject() override {}mutable webrtc::webrtc_impl::RefCounter ref_count_{0};RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedObject);
};

WebRTC 源码中的一个 make_ref_counted 函数模板,它用于创建具有引用计数的对象。通过使用 C++ 的 SFINAE(Substitution Failure Is Not An Error)和 std::enable_if,该函数确保只有在某些条件下才能创建对象,这些条件是 T 类型必须能够转换为 RefCountInterface*

对如上源码解读:

1. 模板参数解

1.1 typename T
  • T 是模板的类型参数,表示要创建的对象类型。例如,如果你想创建一个 MyClass 类型的对象,则 T 将是 MyClass
1.2 typename... Args
  • Args 是一个 可变模板参数,表示你可以传入任意数量的构造函数参数。这使得 make_ref_counted 可以用于创建任何带有不同构造参数的对象。
1.3 typename std::enable_if<std::is_convertible<T*, RefCountInterface*>::value, T>::type* = nullptr
  • 这一部分使用了 SFINAE 技巧来约束模板的实例化条件。通过 std::enable_ifstd::is_convertible,它确保只有当 T*(即 T 类型的指针)能够转换为 RefCountInterface* 类型时,才会启用该模板。

    • std::is_convertible<T*, RefCountInterface*>::value 是一个类型特性(type trait),它检查类型 T* 是否可以转换为 RefCountInterface*。如果可以转换,表达式的值为 true,否则为 false
    • 如果 T* 可以转换为 RefCountInterface*,则 std::enable_if 会定义类型别名 type,从而允许模板实例化。
    • 如果 T* 不能转换为 RefCountInterface*,则模板实例化将失败,不会生成该函数。
  • std::enable_if<Condition, T>::type*:当条件成立时,enable_if 会提供一个类型别名 type,而 type* 是指向 T 类型的指针。= nullptr 是默认参数,表示 type* 参数是一个指针类型且值为 nullptr

2. scoped_refptr<T>

  • scoped_refptr<T> 是 WebRTC 中的智能指针,用于管理引用计数对象的生命周期。它会在对象超出作用域时自动减少引用计数,如果引用计数降到零,T 类型的对象会被销毁。

    在这段代码中,scoped_refptr<T> 被用作返回类型,表示 make_ref_counted 函数会返回一个智能指针,管理创建的对象。

3. new RefCountedObject<T>(std::forward<Args>(args)...);

  • new RefCountedObject<T>(std::forward<Args>(args)...); 会创建一个新的 RefCountedObject<T> 对象,并传递参数 args 给其构造函数。RefCountedObject<T> 是一个继承自 RefCountInterface 的类,用于为对象提供引用计数功能。

    • std::forward<Args>(args)...:这个语法用于完美转发参数。如果 Args 是一个左值引用类型,那么它会以左值方式传递;如果是右值,则会以右值方式传递。完美转发保证了参数的传递不发生不必要的拷贝或移动。

    • RefCountedObject<T> 是 WebRTC 中专门为引用计数管理而设计的一个模板类,它负责管理 T 类型的对象的生命周期。当 scoped_refptr<T> 被销毁时,它会自动减少 RefCountedObject<T> 的引用计数。

4. 综合说明

整个函数的作用是创建一个 T 类型的对象,并将其包装在一个具有引用计数的智能指针(scoped_refptr<T>)中。它的关键是通过 std::enable_if 限制,只有当 T 类型能够转换为 RefCountInterface* 时,才会进行实例化,确保只有支持引用计数的对象才会被创建。

5.在webrtc中的用法

5.1 peerConnectionFactory对象的构建过程

  从webrtc源码看peerConnectionFactory类的继承关系如下图所示。它公有继承自PeerConnectionFactoryInterface(抽象类),而PeerConnectionFactoryInterface又公有继承自RefCountInterface(抽象类)。peerConnectionFactory并没有实现父抽象类的虚函数,所以peerConnectionFactory也是一个抽象类,那是如何创建出peerConnectionFactory对象呢?

 如下代码是webrtc创建peerConnectionFactory对象的位置,

rtc::scoped_refptr<PeerConnectionFactory> PeerConnectionFactory::Create(PeerConnectionFactoryDependencies dependencies) {auto context = ConnectionContext::Create(&dependencies);if (!context) {return nullptr;}return rtc::make_ref_counted<PeerConnectionFactory>(context, &dependencies);
}

根据上述对make_ref_counted的介绍,因为PeerConnectionFactory类型可以转换成RefCountInterface*类型,

new RefCountedObject<T>(std::forward<Args>(args)...);

所以如上这行代码,是把peerConnectionFactory类型当做模版类型T传入。展开后的代码应该长这样:

new RefCountedObject<peerConnectionFactory>(context, &dependencies);

对于模板类RefCountedObject,内部实现了RefCountInterface抽象类的两个接口。

template <class T>
class RefCountedObject : public T {public:RefCountedObject() {}template <class P0>explicit RefCountedObject(P0&& p0) : T(std::forward<P0>(p0)) {}template <class P0, class P1, class... Args>RefCountedObject(P0&& p0, P1&& p1, Args&&... args): T(std::forward<P0>(p0),std::forward<P1>(p1),std::forward<Args>(args)...) {}void AddRef() const override { ref_count_.IncRef(); }RefCountReleaseStatus Release() const override {const auto status = ref_count_.DecRef();if (status == RefCountReleaseStatus::kDroppedLastRef) {delete this;}return status;}// Return whether the reference count is one. If the reference count is used// in the conventional way, a reference count of 1 implies that the current// thread owns the reference and no other thread shares it. This call// performs the test for a reference count of one, and performs the memory// barrier needed for the owning thread to act on the object, knowing that it// has exclusive access to the object.virtual bool HasOneRef() const { return ref_count_.HasOneRef(); }protected:~RefCountedObject() override {}mutable webrtc::webrtc_impl::RefCounter ref_count_{0};RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedObject);
};

 所以调用

rtc::scoped_refptr<PeerConnectionFactory> PeerConnectionFactory::Create(
    PeerConnectionFactoryDependencies dependencies) {
  auto context = ConnectionContext::Create(&dependencies);
  if (!context) {
    return nullptr;
  }
  return rtc::make_ref_counted<PeerConnectionFactory>(context, &dependencies);
}

后,接着调用rtc::make_ref_counted模版函数后,在这个模版函数内是new一个模版类,这个模版类的参数类型是PeerConnectionFactory。

new RefCountedObject<T>(std::forward<Args>(args)...);

最终看到的PeerConnectionFactory对象,其实是在其外部又封装了一层。这样做的好处是PeerConnectionFactory对象会在其生命期结束后释放对象,实现这个功能主要是靠rtc::scoped_refptr实现的。有时间再接着介绍rtc::scoped_refptr。

从下图可以看出创建的peerConnectionFactory对象确实是来自模板类RefCountedObject。

类似PeerConnection类、EncoderStreamFactory类、 VideoRtpSender类等都是采用这种方式初始化对象的

相关文章:

webrtc 源码阅读 make_ref_counted模板函数用法

目录 1. 模板参数解析 1.1 typename T 1.2 typename... Args 1.3 typename std::enable_if::value, T>::type* nullptr 2. scoped_refptr 3. new RefCountedObject(std::forward(args)...); 4. 综合说明 5.在webrtc中的用法 5.1 peerConnectionFactory对象的构建过…...

【深度学习基础之多尺度特征提取】特征金字塔(Feature Pyramid)是如何在深度学习网络中提取多尺度特征的?附代码

【深度学习基础之多尺度特征提取】特征金字塔&#xff08;Feature Pyramid&#xff09;是如何在深度学习网络中提取多尺度特征的&#xff1f;附代码 【深度学习基础之多尺度特征提取】特征金字塔&#xff08;Feature Pyramid&#xff09;是如何在深度学习网络中提取多尺度特征…...

【Docker】离线安装 Docker

离线安装 Docker 在CentOS系统上安装Docker 1、下载 Docker 仓库文件 https://download.docker.com/linux/centos/docker-ce.repo 2、添加 Docker 仓库文件 将上一步下载的文件&#xff0c;移动到 /etc/yum.repos.d/ 目录 3、清除 YUM 缓存 sudo yum clean all sudo yum…...

三大行业案例:AI大模型+Agent实践全景

本文将从AI Agent和大模型的发展背景切入&#xff0c;结合51Talk、哈啰出行以及B站三个各具特色的行业案例&#xff0c;带你一窥事件驱动架构、RAG技术、人机协作流程&#xff0c;以及一整套行之有效的实操方法。具体包含内容有&#xff1a;51Talk如何让智能客服“主动进攻”&a…...

Dockerfile基础指令

1.FROM 基于基准镜像&#xff08;建议使用官方提供的镜像作为基准镜像&#xff0c;相对安全一些&#xff09; 举例&#xff1a; 制作基准镜像&#xff08;基于centos:lastest&#xff09; FROM cenots 不依赖于任何基准镜像 FROM scratch 依赖于9.0.22版本的tomcat镜像 FROM…...

12.30 linux 文件操作,磁盘分区挂载

ubuntu 在linux 对文件的相关操作【压缩&#xff0c;打包&#xff0c;软链接&#xff0c;文件权限】【head&#xff0c;tail&#xff0c;管道符&#xff0c;通配符&#xff0c;find&#xff0c;grep&#xff0c;cut等】脑图-CSDN博客 1.文件操作 在家目录下创建目录文件&#…...

[图形渲染]【Unity Shader】【游戏开发】 Shader数学基础17-法线变换基础与应用

在计算机图形学中,法线(normal) 是表示表面方向的向量。它在光照、阴影、碰撞检测等领域有着重要作用。本文将介绍如何在模型变换过程中正确变换法线,确保其在光照计算中的正确性,特别是法线与顶点的变换问题。 1. 法线与切线的基本概念 法线(Normal Vector) 法线(或…...

YOLOv9-0.1部分代码阅读笔记-train.py

train.py train.py 目录 train.py 1.所需的库和模块 2.def train(hyp, opt, device, callbacks): 3.def parse_opt(knownFalse): 4.def main(opt, callbacksCallbacks()): 5.def run(**kwargs): 6.if __name__ "__main__": 1.所需的库和模块 import …...

等保测评和密评的相关性和区别

等保测评和密评在网络安全领域均扮演着至关重要的角色&#xff0c;它们之间既存在相关性&#xff0c;又各具特色。 以下是对两者相关性和区别的详细阐述&#xff1a;相关性 1.法律基础&#xff1a;等保测评和密评都是依据国家相关法律法规开展的活动。 等保测评主要依据《网…...

活动预告 |【Part2】 Azure 在线技术公开课:迁移和保护 Windows Server 和 SQL Server 工作负载

课程介绍 通过 Microsoft Learn 免费参加 Microsoft Azure 在线技术公开课&#xff0c;掌握创造新机遇所需的技能&#xff0c;加快对 Microsoft 云技术的了解。参加我们举办的“迁移和保护 Windows Server 和 SQL Server 工作负载”活动&#xff0c;了解 Azure 如何为将工作负载…...

大语言模型(LLM)一般训练过程

大语言模型(LLM)一般训练过程 数据收集与预处理 收集:从多种来源收集海量文本数据,如互联网的新闻文章、博客、论坛,以及书籍、学术论文、社交媒体等,以涵盖丰富的语言表达和知识领域。例如,训练一个通用型的LLM时,可能会收集数十亿甚至上百亿字的文本数据.清洗:去除…...

单片机的基本组成

单片机&#xff0c;即单芯片微型计算机&#xff08;Single-Chip Microcomputer&#xff09;&#xff0c;是一种将中央处理器(CPU)、内存、输入输出接口等功能集成在一块集成电路芯片上的微型计算机。它具有体积小、成本低、可靠性高、功耗低等优点&#xff0c;在现代电子产品中…...

GO性能优化的一些记录:trace工具的使用

使用场景&#xff1a; 1 想要查看接口延时性偏高 2 深入了解协程具体如何运营的详细信息&#xff08;运行时长&#xff0c;或者什么原因导致了协程运行受阻&#xff09; 可以使用 trace 功能&#xff0c;程序便会对下面的一系列事件进行详细记录&#xff0c;并且会依据所搜集到…...

dede-cms关于shell漏洞

一.文件式管理器 1.新建文件 新建一个php文件&#xff0c;内容写个php脚本语言 访问&#xff0c;可以运行 2.文件上传 上传一个php文件&#xff0c;内容同样写一个php代码 访问&#xff0c;运行成功 二.模块-广告管理 来到模块-广告管理——>增加一个新广告 在这里试一下…...

NAT 技术如何解决 IP 地址短缺问题?

NAT 技术如何解决 IP 地址短缺问题&#xff1f; 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 随着互联网的普及和发展&#xff0c;IP 地址的需求量迅速增加。尤其是 IPv4 地址&…...

使用 IDE生成 Java Doc

使用步骤 Android Studio界面->Tools->Generate JavaDoc zh-CN -encoding UTF-8 -charset UTF-8 -classpath “C:\Users\fangjian\AppData\Local\Android\Sdk\platforms\android-34\android.jar” 报错问题 错误: 目标 17 不允许选项 --boot-class-path 如果你正在使用…...

通过无障碍服务(AccessibilityService)实现Android设备全局水印显示

一、无障碍功能简介 首先我们先来了解下无障碍功能的官方介绍&#xff1a; 无障碍服务仅应用于帮助残障用户使用 Android 设备和应用。它们在后台运行&#xff0c;并在触发 AccessibilityEvents 时接收系统的回调。此类事件表示用户界面中的某些状态转换&#xff0c;例如焦点已…...

flask后端开发(2):URL与视图

目录 URL定义request获取请求参数 gitcode地址&#xff1a; https://gitcode.com/qq_43920838/flask_project.git URL定义 from flask import FlaskappFlask(__name__)app.route(/) def hello_world():return Hello World!app.route(/profile) def profile():return 我是个人…...

力扣-数据结构-7【算法学习day.78】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;建议灵神的题单和代码随想录&#xff09;和记录自己的学习过程&#xff0c;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关…...

【潜意识Java】Java中深入解析抽象类与接口的差异的完整笔记总结【保姆级详细教程】

目录 一、抽象类和接口的基本概念 &#xff08;一&#xff09;抽象类是什么 &#xff08;二&#xff09;接口是什么 二、抽象类和接口的设计目的差异 &#xff08;一&#xff09;抽象类的设计初衷 &#xff08;二&#xff09;接口的设计意图 三、抽象类和接口的语法特性…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...