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}
diff --git a/rtc_base/ref_counted_object.h b/rtc_base/ref_counted_object.h
index 2a55d86..37612ad 100644
--- a/rtc_base/ref_counted_object.h
+++ b/rtc_base/ref_counted_object.h
@@ -20,6 +20,23 @@
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>
class RefCountedObject : public T {
public:
@@ -64,10 +81,9 @@
class FinalRefCountedObject final : public T {
public:
using T::T;
- // Until c++17 compilers are allowed not to inherit the default constructors.
- // Thus the default constructors are forwarded explicitly.
- FinalRefCountedObject() = default;
- explicit FinalRefCountedObject(const T& other) : T(other) {}
+ // Above using declaration propagates a default move constructor
+ // FinalRefCountedObject(FinalRefCountedObject&& other), but we also need
+ // move construction from T.
explicit FinalRefCountedObject(T&& other) : T(std::move(other)) {}
FinalRefCountedObject(const FinalRefCountedObject&) = delete;
FinalRefCountedObject& operator=(const FinalRefCountedObject&) = delete;
@@ -106,8 +122,13 @@
//
// auto p = scoped_refptr<Foo>(new RefCountedObject<Foo>("bar", 123));
//
-// If the class does not inherit from RefCountInterface, the example is
-// equivalent to:
+// If the class does not inherit from RefCountInterface, but does have
+// 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>>(
// new FinalRefCountedObject<Foo>("bar", 123));
@@ -122,22 +143,37 @@
// needed.
// `make_ref_counted` for classes that are convertible to RefCountInterface.
-template <
- typename T,
- typename... Args,
- typename std::enable_if<std::is_convertible<T*, RefCountInterface*>::value,
- T>::type* = nullptr>
+template <typename T,
+ typename... Args,
+ typename std::enable_if<std::is_convertible_v<T*, RefCountInterface*>,
+ T>::type* = nullptr>
scoped_refptr<T> make_ref_counted(Args&&... args) {
return new RefCountedObject<T>(std::forward<Args>(args)...);
}
// `make_ref_counted` for complete classes that are not convertible to
-// RefCountInterface.
+// RefCountInterface and already carry a ref count.
template <
typename T,
typename... Args,
- typename std::enable_if<!std::is_convertible<T*, RefCountInterface*>::value,
- T>::type* = nullptr>
+ 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>
scoped_refptr<FinalRefCountedObject<T>> make_ref_counted(Args&&... args) {
return new FinalRefCountedObject<T>(std::forward<Args>(args)...);
}
@@ -188,7 +224,7 @@
template <typename T>
struct Ref {
typedef typename std::conditional<
- std::is_convertible<T*, RefCountInterface*>::value,
+ webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value,
T,
FinalRefCountedObject<T>>::type Type;