Allow scoped_refptr to be used with absl nullability annotation

Bug: None
Change-Id: I6529e85b69e2430b8e57d7ac5f7842a4a74307b0
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/363821
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43094}
This commit is contained in:
Danil Chapovalov 2024-09-26 20:46:17 +02:00 committed by WebRTC LUCI CQ
parent 0af0c059f2
commit 3ae9578f4d
3 changed files with 24 additions and 62 deletions

View File

@ -464,6 +464,7 @@ rtc_source_set("ref_count") {
rtc_source_set("scoped_refptr") { rtc_source_set("scoped_refptr") {
visibility = [ "*" ] visibility = [ "*" ]
sources = [ "scoped_refptr.h" ] sources = [ "scoped_refptr.h" ]
deps = [ "//third_party/abseil-cpp/absl/base:nullability" ]
} }
rtc_source_set("make_ref_counted") { rtc_source_set("make_ref_counted") {
@ -473,6 +474,7 @@ rtc_source_set("make_ref_counted") {
":ref_count", ":ref_count",
":scoped_refptr", ":scoped_refptr",
"../rtc_base:refcount", "../rtc_base:refcount",
"//third_party/abseil-cpp/absl/base:nullability",
] ]
} }

View File

@ -13,6 +13,7 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include "absl/base/nullability.h"
#include "api/ref_count.h" #include "api/ref_count.h"
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "rtc_base/ref_counted_object.h" #include "rtc_base/ref_counted_object.h"
@ -85,7 +86,7 @@ template <
typename std::enable_if<std::is_convertible_v<T*, RefCountInterface*> && typename std::enable_if<std::is_convertible_v<T*, RefCountInterface*> &&
std::is_abstract_v<T>, std::is_abstract_v<T>,
T>::type* = nullptr> T>::type* = nullptr>
scoped_refptr<T> make_ref_counted(Args&&... args) { absl::Nonnull<scoped_refptr<T>> make_ref_counted(Args&&... args) {
return scoped_refptr<T>(new RefCountedObject<T>(std::forward<Args>(args)...)); return scoped_refptr<T>(new RefCountedObject<T>(std::forward<Args>(args)...));
} }
@ -98,7 +99,7 @@ template <
!std::is_convertible_v<T*, RefCountInterface*> && !std::is_convertible_v<T*, RefCountInterface*> &&
webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value, webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value,
T>::type* = nullptr> T>::type* = nullptr>
scoped_refptr<T> make_ref_counted(Args&&... args) { absl::Nonnull<scoped_refptr<T>> make_ref_counted(Args&&... args) {
return scoped_refptr<T>(new T(std::forward<Args>(args)...)); return scoped_refptr<T>(new T(std::forward<Args>(args)...));
} }
@ -112,61 +113,18 @@ template <
!webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value, !webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value,
T>::type* = nullptr> T>::type* = nullptr>
scoped_refptr<FinalRefCountedObject<T>> make_ref_counted(Args&&... args) { absl::Nonnull<scoped_refptr<FinalRefCountedObject<T>>> make_ref_counted(
Args&&... args) {
return scoped_refptr<FinalRefCountedObject<T>>( return scoped_refptr<FinalRefCountedObject<T>>(
new FinalRefCountedObject<T>(std::forward<Args>(args)...)); new FinalRefCountedObject<T>(std::forward<Args>(args)...));
} }
} // namespace webrtc } // namespace webrtc
// Backwards compatibe aliases.
// TODO: https://issues.webrtc.org/42225969 - deprecate and remove.
namespace rtc { namespace rtc {
// This doesn't work: // Backwards compatibe alias.
// template <typename T, typename... Args> // TODO: bugs.webrtc.org/42225969 - deprecate and remove.
// using make_ref_counted(Args&&... args) = using ::webrtc::make_ref_counted;
// webrtc::make_ref_counted<T>(Args&&... args);
// Instead, reproduce the templates.
template <typename T,
typename... Args,
typename std::enable_if<
std::is_convertible_v<T*, webrtc::RefCountInterface*> &&
std::is_abstract_v<T>,
T>::type* = nullptr>
scoped_refptr<T> make_ref_counted(Args&&... args) {
return webrtc::scoped_refptr<T>(
new webrtc::RefCountedObject<T>(std::forward<Args>(args)...));
}
// `make_ref_counted` for complete classes that are not convertible to
// RefCountInterface and already carry a ref count.
template <typename T,
typename... Args,
typename std::enable_if<
!std::is_convertible_v<T*, webrtc::RefCountInterface*> &&
webrtc::webrtc_make_ref_counted_internal::HasAddRefAndRelease<
T>::value,
T>::type* = nullptr>
scoped_refptr<T> make_ref_counted(Args&&... args) {
return webrtc::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*, webrtc::RefCountInterface*> &&
!webrtc::webrtc_make_ref_counted_internal::
HasAddRefAndRelease<T>::value,
T>::type* = nullptr>
scoped_refptr<webrtc::FinalRefCountedObject<T>> make_ref_counted(
Args&&... args) {
return webrtc::scoped_refptr<FinalRefCountedObject<T>>(
new webrtc::FinalRefCountedObject<T>(std::forward<Args>(args)...));
}
} // namespace rtc } // namespace rtc
#endif // API_MAKE_REF_COUNTED_H_ #endif // API_MAKE_REF_COUNTED_H_

View File

@ -22,13 +22,13 @@
// }; // };
// //
// void some_function() { // void some_function() {
// scoped_refptr<MyFoo> foo = new MyFoo(); // scoped_refptr<MyFoo> foo = make_ref_counted<MyFoo>();
// foo->Method(param); // foo->Method(param);
// // `foo` is released when this function returns // // `foo` is released when this function returns
// } // }
// //
// void some_other_function() { // void some_other_function() {
// scoped_refptr<MyFoo> foo = new MyFoo(); // scoped_refptr<MyFoo> foo = make_ref_counted<MyFoo>();
// ... // ...
// foo = nullptr; // explicitly releases `foo` // foo = nullptr; // explicitly releases `foo`
// ... // ...
@ -41,7 +41,7 @@
// references between the two objects, like so: // references between the two objects, like so:
// //
// { // {
// scoped_refptr<MyFoo> a = new MyFoo(); // scoped_refptr<MyFoo> a = make_ref_counted<MyFoo>();
// scoped_refptr<MyFoo> b; // scoped_refptr<MyFoo> b;
// //
// b.swap(a); // b.swap(a);
@ -52,7 +52,7 @@
// object, simply use the assignment operator: // object, simply use the assignment operator:
// //
// { // {
// scoped_refptr<MyFoo> a = new MyFoo(); // scoped_refptr<MyFoo> a = make_ref_counted<MyFoo>();
// scoped_refptr<MyFoo> b; // scoped_refptr<MyFoo> b;
// //
// b = a; // b = a;
@ -66,17 +66,20 @@
#include <cstddef> #include <cstddef>
#include <utility> #include <utility>
#include "absl/base/nullability.h"
namespace webrtc { namespace webrtc {
template <class T> template <class T>
class scoped_refptr { class ABSL_NULLABILITY_COMPATIBLE scoped_refptr {
public: public:
typedef T element_type; using absl_nullability_compatible = void;
using element_type = T;
scoped_refptr() : ptr_(nullptr) {} scoped_refptr() : ptr_(nullptr) {}
scoped_refptr(std::nullptr_t) : ptr_(nullptr) {} // NOLINT(runtime/explicit) scoped_refptr(std::nullptr_t) : ptr_(nullptr) {} // NOLINT(runtime/explicit)
explicit scoped_refptr(T* p) : ptr_(p) { explicit scoped_refptr(absl::Nullable<T*> p) : ptr_(p) {
if (ptr_) if (ptr_)
ptr_->AddRef(); ptr_->AddRef();
} }
@ -119,7 +122,7 @@ class scoped_refptr {
return retVal; return retVal;
} }
scoped_refptr<T>& operator=(T* p) { scoped_refptr<T>& operator=(absl::Nullable<T*> p) {
// AddRef first so that self assignment should work // AddRef first so that self assignment should work
if (p) if (p)
p->AddRef(); p->AddRef();
@ -149,7 +152,7 @@ class scoped_refptr {
return *this; return *this;
} }
void swap(T** pp) noexcept { void swap(absl::Nonnull<T**> pp) noexcept {
T* p = ptr_; T* p = ptr_;
ptr_ = *pp; ptr_ = *pp;
*pp = p; *pp = p;
@ -219,9 +222,8 @@ bool operator<(const scoped_refptr<T>& a, const scoped_refptr<U>& b) {
namespace rtc { namespace rtc {
// Backwards compatible alias. // Backwards compatible alias.
// TODO(bugs.webrtc.org/15622): Deprecate and remove. // TODO: bugs.webrtc.org/42225969 - Deprecate and remove.
template <typename T> using ::webrtc::scoped_refptr;
using scoped_refptr = webrtc::scoped_refptr<T>;
} // namespace rtc } // namespace rtc
#endif // API_SCOPED_REFPTR_H_ #endif // API_SCOPED_REFPTR_H_