写点什么

WebRTC 中的 RefCountedObject 解析

发布于: 5 小时前
WebRTC中的RefCountedObject解析

引用计数功能在对象的回收中至关重要,java 中,每个对象都会有引用计数,当引用计数为 0 时,对象将被标记会可回收,等待着垃圾回收机制进行回收。C++中没有垃圾自动回收的机制,但是不妨碍我们想办法自己实现这种引用计数的功能。在 Webrtc 中,RefCountedObject 类就是承担了这样的功能。

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)...) {}  virtual void AddRef() const { ref_count_.IncRef(); }  virtual RefCountReleaseStatus Release() const {    const auto status = ref_count_.DecRef();    if (status == RefCountReleaseStatus::kDroppedLastRef) {      delete this;    }    return status;  }  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);};
复制代码

代码比较简单,是一个模板类。我注意到这里有个比较高级的用法,RefCountedObject 类继承了 class T。也就是说 RefCountedObject<A>是 A 的一个子类,这样的好处是 A 的代码无需继承 RefCountedObject。但我不是特别喜欢这种代码样式,不符合我们一般人的思维方式。

类中有一个变量 ref_count_,里面封装了 long 型的变量,并且实现了线程安全的加 1 和减 1。

RefCountedObject 只是让类拥有了引用计数的功能,并没有自动回收的功能,或许你看到 Release 函数里有 delete this 的代码,觉得这个就是回收的功能。这样理解好像也没什么问题,但是类 A 中并没有调用 Release,它甚至不知道 RefCountedObject 的存在,那 Release 究竟是在哪被调用呢?因此要实现引用计数自动回收的功能,必须配合 scoped_refptr<>模板类进行使用。

scoped_refptr<A> sa = new RefCountedObject<A>();
复制代码

这个语句看起来语法有点问题,等号左边是一个非指针对象 sa,等号右边却是一个 new 的指针对象。想做到这样其实也不难,重载一下 operator=就可以了

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;
  }
复制代码

可以看到,RefCountedObject 中实现的 AddRef 以及 Release 函数是在 scoped_refptr 中被调用的。关于 scoped_refptr,我会在另一篇文章中解析。

发布于: 5 小时前阅读数: 3
用户头像

还未添加个人签名 2018.03.11 加入

还未添加个人简介

评论

发布
暂无评论
WebRTC中的RefCountedObject解析