Bug 1738106 - Part 2: Allow XPCOM classes to use SupportsThreadSafeWeakPtr, r=glandium,xpcom-reviewers

Due to how this type of threadsafe refcounting is implemented, it needs to be
implemented using a MFBT-style refcounting base class, somewhat similar to
`SupportsWeakPtr`.

This patch makes NS_IMPL_{ADDREF,RELEASE}_INHERITED intelligently not add
refcount logging for types inheriting from SupportsThreadSafeWeakPtr, as the
default behaviour would break due to weak pointer upgrades not calling through
`AddRef` or `Release`.

In MFBT, the return value of `AddRef` and `Release` on
SupportsThreadSafeWeakPtr is changed to be compatible with nsISupports, so that
this type can be used to implement nsISupports refcounting.

Differential Revision: https://phabricator.services.mozilla.com/D142603
This commit is contained in:
Nika Layzell 2022-05-02 20:37:34 +00:00
Родитель 2f853cadea
Коммит 18f7866fc2
2 изменённых файлов: 28 добавлений и 13 удалений

Просмотреть файл

@ -56,6 +56,7 @@
#define mozilla_ThreadSafeWeakPtr_h
#include "mozilla/Assertions.h"
#include "mozilla/RefCountType.h"
#include "mozilla/RefCounted.h"
#include "mozilla/RefPtr.h"
@ -151,14 +152,15 @@ class SupportsThreadSafeWeakPtr : public detail::SupportsThreadSafeWeakPtrBase {
public:
// Compatibility with RefPtr
void AddRef() const {
MozExternalRefCountType AddRef() const {
auto& refCnt = mWeakRef->mStrongCnt;
MOZ_ASSERT(int32_t(refCnt) >= 0);
MozRefCountType cnt = ++refCnt;
detail::RefCountLogger::logAddRef(static_cast<const T*>(this), cnt);
return cnt;
}
void Release() const {
MozExternalRefCountType Release() const {
auto& refCnt = mWeakRef->mStrongCnt;
MOZ_ASSERT(int32_t(refCnt) > 0);
detail::RefCountLogger::ReleaseLogger logger(static_cast<const T*>(this));
@ -176,6 +178,7 @@ class SupportsThreadSafeWeakPtr : public detail::SupportsThreadSafeWeakPtrBase {
// it may still be read by mWeakRef.
delete static_cast<const T*>(this);
}
return cnt;
}
// Compatibility with wtf::RefPtr

Просмотреть файл

@ -1354,14 +1354,26 @@ nsresult NS_FASTCALL NS_TableDrivenQI(void* aThis, REFNSIID aIID,
namespace mozilla {
class Runnable;
namespace detail {
class SupportsThreadSafeWeakPtrBase;
// Don't NS_LOG_{ADDREF,RELEASE} when inheriting from `Runnable*` or types with
// thread safe weak references, as it will generate incorrect refcnt logs due to
// the thread-safe `Upgrade()` call's refcount modifications not calling through
// the derived class' `AddRef()` and `Release()` methods.
template <typename T>
constexpr bool ShouldLogInheritedRefcnt =
!std::is_convertible_v<T*, Runnable*> &&
!std::is_base_of_v<SupportsThreadSafeWeakPtrBase, T>;
}
} // namespace mozilla
#define NS_IMPL_ADDREF_INHERITED_GUTS(Class, Super) \
MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(Class) \
nsrefcnt r = Super::AddRef(); \
if (!std::is_convertible_v<Class*, mozilla::Runnable*>) { \
NS_LOG_ADDREF(this, r, #Class, sizeof(*this)); \
} \
#define NS_IMPL_ADDREF_INHERITED_GUTS(Class, Super) \
MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(Class) \
nsrefcnt r = Super::AddRef(); \
if constexpr (::mozilla::detail::ShouldLogInheritedRefcnt<Class>) { \
NS_LOG_ADDREF(this, r, #Class, sizeof(*this)); \
} \
return r /* Purposefully no trailing semicolon */
#define NS_IMPL_ADDREF_INHERITED(Class, Super) \
@ -1369,11 +1381,11 @@ class Runnable;
NS_IMPL_ADDREF_INHERITED_GUTS(Class, Super); \
}
#define NS_IMPL_RELEASE_INHERITED_GUTS(Class, Super) \
nsrefcnt r = Super::Release(); \
if (!std::is_convertible_v<Class*, mozilla::Runnable*>) { \
NS_LOG_RELEASE(this, r, #Class); \
} \
#define NS_IMPL_RELEASE_INHERITED_GUTS(Class, Super) \
nsrefcnt r = Super::Release(); \
if constexpr (::mozilla::detail::ShouldLogInheritedRefcnt<Class>) { \
NS_LOG_RELEASE(this, r, #Class); \
} \
return r /* Purposefully no trailing semicolon */
#define NS_IMPL_RELEASE_INHERITED(Class, Super) \