Extend make_ref_counted to interoperate with RefCountedNonVirtual

Update RtpPacketInfos internals to use rtc::make_ref_counted, and a
Data class with no virtual methods.

Bug: webrtc:13464, webrtc:12701
Change-Id: I03f6bee69a9f060dcf287284fc779268d5eb433e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/244505
Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35660}
This commit is contained in:
Niels Möller 2022-01-11 15:40:22 +01:00 committed by WebRTC LUCI CQ
parent b82193cec8
commit bb57de2959
3 changed files with 60 additions and 20 deletions

View File

@ -168,6 +168,9 @@ specific_include_rules = {
# For private member and constructor. # For private member and constructor.
"+rtc_base/system/file_wrapper.h", "+rtc_base/system/file_wrapper.h",
], ],
"rtp_packet_infos\.h": [
"+rtc_base/ref_counted_object.h",
],
"rtp_receiver_interface\.h": [ "rtp_receiver_interface\.h": [
"+rtc_base/ref_count.h", "+rtc_base/ref_count.h",
], ],

View File

@ -18,6 +18,7 @@
#include "api/ref_counted_base.h" #include "api/ref_counted_base.h"
#include "api/rtp_packet_info.h" #include "api/rtp_packet_info.h"
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/system/rtc_export.h" #include "rtc_base/system/rtc_export.h"
namespace webrtc { namespace webrtc {
@ -79,7 +80,7 @@ class RTC_EXPORT RtpPacketInfos {
size_type size() const { return entries().size(); } size_type size() const { return entries().size(); }
private: private:
class Data : public rtc::RefCountedBase { class Data final : public rtc::RefCountedNonVirtual<Data> {
public: public:
static rtc::scoped_refptr<Data> Create(const vector_type& entries) { static rtc::scoped_refptr<Data> Create(const vector_type& entries) {
// Performance optimization for the empty case. // Performance optimization for the empty case.
@ -87,7 +88,7 @@ class RTC_EXPORT RtpPacketInfos {
return nullptr; return nullptr;
} }
return new Data(entries); return rtc::make_ref_counted<Data>(entries);
} }
static rtc::scoped_refptr<Data> Create(vector_type&& entries) { static rtc::scoped_refptr<Data> Create(vector_type&& entries) {
@ -96,16 +97,16 @@ class RTC_EXPORT RtpPacketInfos {
return nullptr; return nullptr;
} }
return new Data(std::move(entries)); return rtc::make_ref_counted<Data>(std::move(entries));
} }
const vector_type& entries() const { return entries_; } const vector_type& entries() const { return entries_; }
private:
explicit Data(const vector_type& entries) : entries_(entries) {} explicit Data(const vector_type& entries) : entries_(entries) {}
explicit Data(vector_type&& entries) : entries_(std::move(entries)) {} explicit Data(vector_type&& entries) : entries_(std::move(entries)) {}
~Data() override {} ~Data() = default;
private:
const vector_type entries_; const vector_type entries_;
}; };

View File

@ -20,6 +20,23 @@
namespace rtc { namespace rtc {
namespace webrtc_make_ref_counted_internal {
// Determines if the given class has AddRef and Release methods.
template <typename T>
class HasAddRefAndRelease {
private:
template <typename C,
decltype(std::declval<C>().AddRef())* = nullptr,
decltype(std::declval<C>().Release())* = nullptr>
static int Test(int);
template <typename>
static char Test(...);
public:
static constexpr bool value = std::is_same_v<decltype(Test<T>(0)), int>;
};
} // namespace webrtc_make_ref_counted_internal
template <class T> template <class T>
class RefCountedObject : public T { class RefCountedObject : public T {
public: public:
@ -64,10 +81,9 @@ template <class T>
class FinalRefCountedObject final : public T { class FinalRefCountedObject final : public T {
public: public:
using T::T; using T::T;
// Until c++17 compilers are allowed not to inherit the default constructors. // Above using declaration propagates a default move constructor
// Thus the default constructors are forwarded explicitly. // FinalRefCountedObject(FinalRefCountedObject&& other), but we also need
FinalRefCountedObject() = default; // move construction from T.
explicit FinalRefCountedObject(const T& other) : T(other) {}
explicit FinalRefCountedObject(T&& other) : T(std::move(other)) {} explicit FinalRefCountedObject(T&& other) : T(std::move(other)) {}
FinalRefCountedObject(const FinalRefCountedObject&) = delete; FinalRefCountedObject(const FinalRefCountedObject&) = delete;
FinalRefCountedObject& operator=(const FinalRefCountedObject&) = delete; FinalRefCountedObject& operator=(const FinalRefCountedObject&) = delete;
@ -106,8 +122,13 @@ class FinalRefCountedObject final : public T {
// //
// auto p = scoped_refptr<Foo>(new RefCountedObject<Foo>("bar", 123)); // auto p = scoped_refptr<Foo>(new RefCountedObject<Foo>("bar", 123));
// //
// If the class does not inherit from RefCountInterface, the example is // If the class does not inherit from RefCountInterface, but does have
// equivalent to: // AddRef/Release methods (so a T* is convertible to rtc::scoped_refptr), this
// is equivalent to just
//
// auto p = scoped_refptr<Foo>(new Foo("bar", 123));
//
// Otherwise, the example is equivalent to:
// //
// auto p = scoped_refptr<FinalRefCountedObject<Foo>>( // auto p = scoped_refptr<FinalRefCountedObject<Foo>>(
// new FinalRefCountedObject<Foo>("bar", 123)); // new FinalRefCountedObject<Foo>("bar", 123));
@ -122,21 +143,36 @@ class FinalRefCountedObject final : public T {
// needed. // needed.
// `make_ref_counted` for classes that are convertible to RefCountInterface. // `make_ref_counted` for classes that are convertible to RefCountInterface.
template < template <typename T,
typename T,
typename... Args, typename... Args,
typename std::enable_if<std::is_convertible<T*, RefCountInterface*>::value, typename std::enable_if<std::is_convertible_v<T*, RefCountInterface*>,
T>::type* = nullptr> T>::type* = nullptr>
scoped_refptr<T> make_ref_counted(Args&&... args) { scoped_refptr<T> make_ref_counted(Args&&... args) {
return new RefCountedObject<T>(std::forward<Args>(args)...); return new RefCountedObject<T>(std::forward<Args>(args)...);
} }
// `make_ref_counted` for complete classes that are not convertible to // `make_ref_counted` for complete classes that are not convertible to
// RefCountInterface. // RefCountInterface and already carry a ref count.
template < template <
typename T, typename T,
typename... Args, typename... Args,
typename std::enable_if<!std::is_convertible<T*, RefCountInterface*>::value, typename std::enable_if<
!std::is_convertible_v<T*, RefCountInterface*> &&
webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value,
T>::type* = nullptr>
scoped_refptr<T> make_ref_counted(Args&&... args) {
return scoped_refptr<T>(new T(std::forward<Args>(args)...));
}
// `make_ref_counted` for complete classes that are not convertible to
// RefCountInterface and have no ref count of their own.
template <
typename T,
typename... Args,
typename std::enable_if<
!std::is_convertible_v<T*, RefCountInterface*> &&
!webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value,
T>::type* = nullptr> T>::type* = nullptr>
scoped_refptr<FinalRefCountedObject<T>> make_ref_counted(Args&&... args) { scoped_refptr<FinalRefCountedObject<T>> make_ref_counted(Args&&... args) {
return new FinalRefCountedObject<T>(std::forward<Args>(args)...); return new FinalRefCountedObject<T>(std::forward<Args>(args)...);
@ -188,7 +224,7 @@ scoped_refptr<FinalRefCountedObject<T>> make_ref_counted(Args&&... args) {
template <typename T> template <typename T>
struct Ref { struct Ref {
typedef typename std::conditional< typedef typename std::conditional<
std::is_convertible<T*, RefCountInterface*>::value, webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value,
T, T,
FinalRefCountedObject<T>>::type Type; FinalRefCountedObject<T>>::type Type;