当前位置:网站首页>webrtc中的引用计框架
webrtc中的引用计框架
2022-08-04 05:25:00 【mo4776】
webrtc中的引用计框架
基本框架类
webrtc中通过RefCounter
,RefCountedObject
,RefCountInterface
类提供了一个引用计数框架。RefCounter
是计数器类,实现了线程安全的计数功能;RefCountedObject
对RefCounter
进行了封装;RefCountInterface
是接口类,要求实现AddRef()
和Release()
接口。它们可以单独使用,可以结合使用。
在webrtc中有两个方面的运用
使用
scoped_refptr
引用计数类时,需要把这上面的几个类结合起来使用在
help_functions_ds.h
文件中,实现了一个ComRefCount
类,它是用来对COM组件进行管理的,它直接使用了RefCounter
类,来实现引用计数
下面主要介绍scoped_refptr
的实现及用法
scoped_refptr
实现
webrtc的代码中大量使用的scoped_refptr
,是一个有引用计数的智能指针,与STL中的shared_ptr
类似。不过它更轻量级,它的功能只限于增加/减少引用计数,超出作用域时自动释放所管理的对象。socped_refptr
引用计数的实现为侵入式,它只有一个用于保存对象的指针变量,计数的功能由该对象实现。可以通过RefCountedObject
类来包装自定义类使其具有计数功能,来满足scoped_refptr
的要求。
代码比较简单,如下:
template <class T>
class scoped_refptr {
public:
typedef T element_type;
scoped_refptr() : ptr_(nullptr) {}
scoped_refptr(T* p) : ptr_(p) { // NOLINT(runtime/explicit)
if (ptr_)
ptr_->AddRef();
}
scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
if (ptr_)
ptr_->AddRef();
}
template <typename U>
scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
if (ptr_)
ptr_->AddRef();
}
// Move constructors.
scoped_refptr(scoped_refptr<T>&& r) noexcept : ptr_(r.release()) {}
template <typename U>
scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.release()) {}
~scoped_refptr() {
if (ptr_)
ptr_->Release();
}
T* get() const { return ptr_; }
operator T*() const { return ptr_; }
T* operator->() const { return ptr_; }
// Returns the (possibly null) raw pointer, and makes the scoped_refptr hold a
// null pointer, all without touching the reference count of the underlying
// pointed-to object. The object is still reference counted, and the caller of
// release() is now the proud owner of one reference, so it is responsible for
// calling Release() once on the object when no longer using it.
T* release() {
T* retVal = ptr_;
ptr_ = nullptr;
return retVal;
}
scoped_refptr<T>& operator=(T* p) {
// AddRef first so that self assignment should work
if (p)
p->AddRef();
if (ptr_)
ptr_->Release();
ptr_ = p;
return *this;
}
scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
return *this = r.ptr_;
}
template <typename U>
scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
return *this = r.get();
}
scoped_refptr<T>& operator=(scoped_refptr<T>&& r) noexcept {
scoped_refptr<T>(std::move(r)).swap(*this);
return *this;
}
template <typename U>
scoped_refptr<T>& operator=(scoped_refptr<U>&& r) noexcept {
scoped_refptr<T>(std::move(r)).swap(*this);
return *this;
}
void swap(T** pp) noexcept {
T* p = ptr_;
ptr_ = *pp;
*pp = p;
}
void swap(scoped_refptr<T>& r) noexcept { swap(&r.ptr_); }
protected:
T* ptr_;
};
scoped_refptr
要求所管理的对象,实现了计数功能,它只保有指向该对象的一个裸指针。在复制构造函数,赋值函数中对计数进行增减。核心函数是scoped_refptr<T>& operator=(T* p)
,用T类型的裸指针给scoped_refptr
赋值,对应的计数也会变化,这个跟STL中的智能指针不一样,不能将一个裸指针赋给智能指针。
有几个地方需要注意的
release()
方法的语意是释放scoped_refptr
对管理对象的所有权,对象超出作用域后,需要手动释放。这个跟STL中shared_ptr
,unique_ptr
的release()
方法的语意是一致的scoped_refptr
的构造
- 通过裸指针构造一个
socped_refptr
scoped_refptr(T* p) : ptr_(p) { // NOLINT(runtime/explicit)
if (ptr_)
ptr_->AddRef();
}
- 下面的这个复制构造函数,可以通过一个包装子类的
scoped_refptr
对象,构造一个包装父类的scoped_refptr
对象
template <typename U>
scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
if (ptr_)
ptr_->AddRef();
}
例如:
//类s是类p的子类
scoped_refptr<s> sptr;
scoped_refptr<p> pPtr(sptr);
当然如果用一个没有继承关系的对象去构造,是会编译错误的。这是通过裸指针的多态实现。
用法
要使用scoped_refptr
,通过了解RefCounter
,RefCountedObject
的功能,可以加深理解
- 类
RefCounter
它就是实现了计数的类,它通过std::atomic<int>
实现了线程安全的计数
- 类
RefCountedObject
它封装了RefCounter
,提供AddRef()
和Release()
方法,满足scoped_refptr()
的要求。但是对包装的类型要求是RefCountInterface
template <class T>
class RefCountedObject : public T {
public:
RefCountedObject() {}
//形参是右值引用,表示万能引用
template <class P0>
explicit RefCountedObject(P0&& p0) : T(std::forward<P0>(p0)) {}
//形参是右值引用,表示万能引用,可以适配T类型的构造函数
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)...) {}
virtual void AddRef() const { ref_count_.IncRef(); }
//Release包含了两个操作,将计数减1,如果再没有引用则释放对象
virtual RefCountReleaseStatus Release() const {
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:
virtual ~RefCountedObject() {}
mutable webrtc::webrtc_impl::RefCounter ref_count_{0};
RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedObject);
};
RefCountInterface
是个接口类
class RefCountInterface {
public:
virtual void AddRef() const = 0;
virtual RefCountReleaseStatus Release() const = 0;
// Non-public destructor, because Release() has exclusive responsibility for
// destroying the object.
protected:
virtual ~RefCountInterface() {}
};
使用示例
对需要使用scoped_refptr
管理的类,需要继承RefCountInterface
, 然后在通过RefCountedObject
包装。
#include <iostream>
#include "rtc_base/ref_counted_object.h"
#include "api/scoped_refptr.h"
//类Test继承RefCountInterface
class Test:public rtc::RefCountInterface {
public:
Test() = default;
virtual void PrintTest() {
std::cout<<"in Test PrintTest"<<std::endl;
}
protected:
virtual ~Test() = default;
};
int main() {
//通过RefCountedObject包装
rtc::scoped_refptr<Test> ptr = new rtc::RefCountedObject<Test>();
ptr->PrintTest();
}
边栏推荐
- FPGA学习笔记——知识点总结
- 文献管理工具 | Zotero
- 关于C#的反射,你真的运用自如嘛?
- Cannot read properties of null (reading 'insertBefore')
- 解决安装nbextensions后使用Jupyter Notebook时出现template_paths相关错误的问题
- 读者让我总结一波 redis 面试题,现在肝出来了
- ORACLE LINUX 6.5 安装重启后Kernel panic - not syncing : Fatal exception
- Tactile intelligent sharing - SSD20X realizes upgrade display progress bar
- 部署LVS-DR群集【实验】
- 力扣题解8/3
猜你喜欢
8.03 Day34---BaseMapper查询语句用法
Can‘t connect to MySQL server on ‘localhost3306‘ (10061) 简洁明了的解决方法
部署LVS-DR群集【实验】
7.18 Day23----标记语言
利用Jenkins实现Unity自动化构建
在被面试官说了无数次后,终于潜下心来整理了一下JVM的类加载器
Web Basics and Exercises for C1 Certification - My Study Notes
Unity自动生成阻挡Collider的GameObject工具
Deploy LVS-DR cluster [experimental]
7.16 Day22---MYSQL (Dao mode encapsulates JDBC)
随机推荐
Grain Mall - Basics (Project Introduction & Project Construction)
npm安装依赖报错npm ERR! code ENOTFOUNDnpm ERR! syscall getaddrinfonpm ERR! errno ENOTFOUND
9、动态SQL
EntityComponentSystemSamples学习笔记
FPGA学习笔记——知识点总结
npm init [email protected] 构建项目报错SyntaxError: Unexpected token ‘.‘解决办法
12. Paging plugin
The cost of automated testing is high and the effect is poor, so what is the significance of automated testing?
解决安装nbextensions后使用Jupyter Notebook时出现template_paths相关错误的问题
力扣:70. 爬楼梯
MySQL database (basic)
7.16 Day22---MYSQL (Dao mode encapsulates JDBC)
关于C#的反射,你真的运用自如嘛?
The Road to Ad Monetization for Uni-app Mini Program Apps: Full Screen Video Ads
What is the salary of a software testing student?
Web Basics and Exercises for C1 Certification - My Study Notes
Unity动画生成工具
How to view sql execution plan offline collection
The idea setting recognizes the .sql file type and other file types
FLV格式详解