Reject double RefCountedObject inheritance in rtc::make_ref_counted.

Bug: webrtc:12701
Change-Id: Ie45707e3266e6a27cae073f824a1c77707d77000
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/256240
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36281}
This commit is contained in:
Niels Möller 2022-03-21 10:36:32 +01:00 committed by WebRTC LUCI CQ
parent cf08d33944
commit 9dde120d65
6 changed files with 28 additions and 26 deletions

View File

@ -25,8 +25,7 @@
namespace webrtc { namespace webrtc {
class MockPeerConnectionInterface class MockPeerConnectionInterface : public webrtc::PeerConnectionInterface {
: public rtc::RefCountedObject<webrtc::PeerConnectionInterface> {
public: public:
static rtc::scoped_refptr<MockPeerConnectionInterface> Create() { static rtc::scoped_refptr<MockPeerConnectionInterface> Create() {
return rtc::make_ref_counted<MockPeerConnectionInterface>(); return rtc::make_ref_counted<MockPeerConnectionInterface>();
@ -199,7 +198,9 @@ class MockPeerConnectionInterface
MOCK_METHOD(void, Close, (), (override)); MOCK_METHOD(void, Close, (), (override));
}; };
static_assert(!std::is_abstract<MockPeerConnectionInterface>::value, ""); static_assert(
!std::is_abstract_v<rtc::RefCountedObject<MockPeerConnectionInterface>>,
"");
} // namespace webrtc } // namespace webrtc

View File

@ -69,8 +69,7 @@ using ::testing::Values;
const uint32_t kDefaultTimeout = 10000u; const uint32_t kDefaultTimeout = 10000u;
template <typename MethodFunctor> template <typename MethodFunctor>
class OnSuccessObserver : public rtc::RefCountedObject< class OnSuccessObserver : public webrtc::SetRemoteDescriptionObserverInterface {
webrtc::SetRemoteDescriptionObserverInterface> {
public: public:
explicit OnSuccessObserver(MethodFunctor on_success) explicit OnSuccessObserver(MethodFunctor on_success)
: on_success_(std::move(on_success)) {} : on_success_(std::move(on_success)) {}

View File

@ -610,8 +610,7 @@ TEST_P(PeerConnectionSignalingTest,
TEST_P(PeerConnectionSignalingTest, ImplicitCreateOfferAndShutdown) { TEST_P(PeerConnectionSignalingTest, ImplicitCreateOfferAndShutdown) {
auto caller = CreatePeerConnection(); auto caller = CreatePeerConnection();
rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer( auto observer = rtc::make_ref_counted<FakeSetLocalDescriptionObserver>();
new FakeSetLocalDescriptionObserver());
caller->pc()->SetLocalDescription(observer); caller->pc()->SetLocalDescription(observer);
caller.reset(nullptr); caller.reset(nullptr);
// The new observer gets invoked because it is called immediately. // The new observer gets invoked because it is called immediately.
@ -632,8 +631,7 @@ TEST_P(PeerConnectionSignalingTest,
TEST_P(PeerConnectionSignalingTest, CloseBeforeImplicitCreateOfferAndShutdown) { TEST_P(PeerConnectionSignalingTest, CloseBeforeImplicitCreateOfferAndShutdown) {
auto caller = CreatePeerConnection(); auto caller = CreatePeerConnection();
rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer( auto observer = rtc::make_ref_counted<FakeSetLocalDescriptionObserver>();
new FakeSetLocalDescriptionObserver());
caller->pc()->Close(); caller->pc()->Close();
caller->pc()->SetLocalDescription(observer); caller->pc()->SetLocalDescription(observer);
caller.reset(nullptr); caller.reset(nullptr);
@ -655,8 +653,7 @@ TEST_P(PeerConnectionSignalingTest,
TEST_P(PeerConnectionSignalingTest, CloseAfterImplicitCreateOfferAndShutdown) { TEST_P(PeerConnectionSignalingTest, CloseAfterImplicitCreateOfferAndShutdown) {
auto caller = CreatePeerConnection(); auto caller = CreatePeerConnection();
rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer( auto observer = rtc::make_ref_counted<FakeSetLocalDescriptionObserver>();
new FakeSetLocalDescriptionObserver());
caller->pc()->SetLocalDescription(observer); caller->pc()->SetLocalDescription(observer);
caller->pc()->Close(); caller->pc()->Close();
caller.reset(nullptr); caller.reset(nullptr);
@ -670,8 +667,7 @@ TEST_P(PeerConnectionSignalingTest,
auto caller = CreatePeerConnection(); auto caller = CreatePeerConnection();
auto offer = caller->CreateOffer(RTCOfferAnswerOptions()); auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer( auto observer = rtc::make_ref_counted<FakeSetLocalDescriptionObserver>();
new FakeSetLocalDescriptionObserver());
caller->pc()->SetLocalDescription(std::move(offer), observer); caller->pc()->SetLocalDescription(std::move(offer), observer);
// The new observer is invoked immediately. // The new observer is invoked immediately.
EXPECT_TRUE(observer->called()); EXPECT_TRUE(observer->called());

View File

@ -18,7 +18,7 @@
namespace webrtc { namespace webrtc {
class MockSctpDataChannel : public rtc::RefCountedObject<SctpDataChannel> { class MockSctpDataChannel : public SctpDataChannel {
public: public:
MockSctpDataChannel(int id, DataState state) MockSctpDataChannel(int id, DataState state)
: MockSctpDataChannel(id, : MockSctpDataChannel(id,
@ -41,11 +41,11 @@ class MockSctpDataChannel : public rtc::RefCountedObject<SctpDataChannel> {
const InternalDataChannelInit& config = InternalDataChannelInit(), const InternalDataChannelInit& config = InternalDataChannelInit(),
rtc::Thread* signaling_thread = rtc::Thread::Current(), rtc::Thread* signaling_thread = rtc::Thread::Current(),
rtc::Thread* network_thread = rtc::Thread::Current()) rtc::Thread* network_thread = rtc::Thread::Current())
: rtc::RefCountedObject<SctpDataChannel>(config, : SctpDataChannel(config,
nullptr, nullptr,
label, label,
signaling_thread, signaling_thread,
network_thread) { network_thread) {
EXPECT_CALL(*this, id()).WillRepeatedly(::testing::Return(id)); EXPECT_CALL(*this, id()).WillRepeatedly(::testing::Return(id));
EXPECT_CALL(*this, state()).WillRepeatedly(::testing::Return(state)); EXPECT_CALL(*this, state()).WillRepeatedly(::testing::Return(state));
EXPECT_CALL(*this, protocol()).WillRepeatedly(::testing::Return(protocol)); EXPECT_CALL(*this, protocol()).WillRepeatedly(::testing::Return(protocol));

View File

@ -336,7 +336,7 @@ class MockSetSessionDescriptionObserver
}; };
class FakeSetLocalDescriptionObserver class FakeSetLocalDescriptionObserver
: public rtc::RefCountedObject<SetLocalDescriptionObserverInterface> { : public SetLocalDescriptionObserverInterface {
public: public:
bool called() const { return error_.has_value(); } bool called() const { return error_.has_value(); }
RTCError& error() { RTCError& error() {
@ -355,7 +355,7 @@ class FakeSetLocalDescriptionObserver
}; };
class FakeSetRemoteDescriptionObserver class FakeSetRemoteDescriptionObserver
: public rtc::RefCountedObject<SetRemoteDescriptionObserverInterface> { : public SetRemoteDescriptionObserverInterface {
public: public:
bool called() const { return error_.has_value(); } bool called() const { return error_.has_value(); }
RTCError& error() { RTCError& error() {

View File

@ -142,11 +142,17 @@ class FinalRefCountedObject final : public T {
// Note that in some cases, using RefCountedObject directly may still be what's // Note that in some cases, using RefCountedObject directly may still be what's
// needed. // needed.
// `make_ref_counted` for classes that are convertible to RefCountInterface. // `make_ref_counted` for abstract classes that are convertible to
template <typename T, // RefCountInterface. The is_abstract requirement rejects classes that inherit
typename... Args, // both RefCountInterface and RefCounted object, which is a a discouraged
typename std::enable_if<std::is_convertible_v<T*, RefCountInterface*>, // pattern, and would result in double inheritance of RefCountedObject if this
T>::type* = nullptr> // template was applied.
template <
typename T,
typename... Args,
typename std::enable_if<std::is_convertible_v<T*, RefCountInterface*> &&
std::is_abstract_v<T>,
T>::type* = nullptr>
scoped_refptr<T> make_ref_counted(Args&&... args) { 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)...));
} }