Bug 1758702 - Allow ThreadSafeWeakPtr<IncompleteType> to work. r=glandium

This will be used to avoid problematic includes from WorkerPrivate.h,
and it matches the behavior of RefPtr<> and WeakPtr<>.

Differential Revision: https://phabricator.services.mozilla.com/D140658
This commit is contained in:
Emilio Cobos Álvarez 2022-03-17 12:15:20 +00:00
parent d7c65853a6
commit 370bce32dc
9 changed files with 50 additions and 74 deletions

View File

@ -77,7 +77,6 @@ class MediaFormatReader final
typedef MozPromise<bool, MediaResult, IsExclusive> NotifyDataArrivedPromise;
public:
MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(MediaFormatReader)
MOZ_DECLARE_REFCOUNTED_TYPENAME(MediaFormatReader)
using TrackSet = EnumSet<TrackInfo::TrackType>;

View File

@ -227,7 +227,6 @@ class SmartMockCubebStream
: public MockCubebStream,
public SupportsThreadSafeWeakPtr<SmartMockCubebStream> {
public:
MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(SmartMockCubebStream)
MOZ_DECLARE_REFCOUNTED_TYPENAME(SmartMockCubebStream)
SmartMockCubebStream(cubeb* aContext, cubeb_devid aInputDevice,
cubeb_stream_params* aInputStreamParams,

View File

@ -49,8 +49,6 @@ class RemoteWorkerChild final
friend class ServiceWorkerOp;
public:
MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(RemoteWorkerChild)
MOZ_DECLARE_REFCOUNTED_TYPENAME(RemoteWorkerChild)
explicit RemoteWorkerChild(const RemoteWorkerData& aData);

View File

@ -1009,7 +1009,6 @@ class SharedFTFace : public external::AtomicRefCounted<SharedFTFace> {
class UnscaledFont : public SupportsThreadSafeWeakPtr<UnscaledFont> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFont)
MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(UnscaledFont)
virtual ~UnscaledFont();
@ -1061,7 +1060,6 @@ class UnscaledFont : public SupportsThreadSafeWeakPtr<UnscaledFont> {
class ScaledFont : public SupportsThreadSafeWeakPtr<ScaledFont> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont)
MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(ScaledFont)
virtual ~ScaledFont();

View File

@ -87,7 +87,6 @@ class AndroidHardwareBufferApi final {
class AndroidHardwareBuffer
: public SupportsThreadSafeWeakPtr<AndroidHardwareBuffer> {
public:
MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(AndroidHardwareBuffer)
MOZ_DECLARE_REFCOUNTED_TYPENAME(AndroidHardwareBuffer)
static already_AddRefed<AndroidHardwareBuffer> Create(

View File

@ -281,7 +281,6 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
friend class ImageContainerChild;
public:
MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(ImageContainer)
MOZ_DECLARE_REFCOUNTED_TYPENAME(ImageContainer)
enum Mode { SYNCHRONOUS = 0x0, ASYNCHRONOUS = 0x01 };

View File

@ -21,7 +21,6 @@
* multiple threads, you can just use WeakPtr instead.
*
* When deriving from SupportsThreadSafeWeakPtr, you should add
* MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(ClassName) and
* MOZ_DECLARE_REFCOUNTED_TYPENAME(ClassName) to the public section of your
* class, where ClassName is the name of your class.
*
@ -30,7 +29,6 @@
* class C : public SupportsThreadSafeWeakPtr<C>
* {
* public:
* MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(C)
* MOZ_DECLARE_REFCOUNTED_TYPENAME(C)
* void doStuff();
* };
@ -65,59 +63,34 @@ namespace mozilla {
template <typename T>
class ThreadSafeWeakPtr;
template <typename T>
class SupportsThreadSafeWeakPtr;
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
# define MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(T) \
static const char* threadSafeWeakReferenceTypeName() { \
return "ThreadSafeWeakReference<" #T ">"; \
}
#else
# define MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(T)
#endif
namespace detail {
class SupportsThreadSafeWeakPtrBase {};
// A shared weak reference that is used to track a SupportsThreadSafeWeakPtr
// object. This object owns the reference count for the tracked object, and can
// perform atomic refcount upgrades.
template <typename T>
class ThreadSafeWeakReference
: public external::AtomicRefCounted<ThreadSafeWeakReference<T>> {
: public external::AtomicRefCounted<ThreadSafeWeakReference> {
public:
typedef T ElementType;
explicit ThreadSafeWeakReference(T* aPtr) : mPtr(aPtr) {}
explicit ThreadSafeWeakReference(SupportsThreadSafeWeakPtrBase* aPtr)
: mPtr(aPtr) {}
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
const char* typeName() const {
// The first time this is called mPtr is null, so don't
// invoke any methods on mPtr.
return T::threadSafeWeakReferenceTypeName();
}
const char* typeName() const { return "ThreadSafeWeakReference"; }
size_t typeSize() const { return sizeof(*this); }
#endif
private:
friend class mozilla::SupportsThreadSafeWeakPtr<T>;
template <typename U>
friend class mozilla::SupportsThreadSafeWeakPtr;
template <typename U>
friend class mozilla::ThreadSafeWeakPtr;
// Creates a new RefPtr to the tracked object.
already_AddRefed<T> getRefPtr() {
// Increment our strong reference count only if it is nonzero, meaning that
// the object is still alive.
MozRefCountType cnt = mStrongCnt.IncrementIfNonzero();
if (cnt == 0) {
return nullptr;
}
RefPtr<T> result{already_AddRefed(mPtr)};
detail::RefCountLogger::logAddRef(result.get(), cnt);
return result.forget();
}
// Number of strong references to the underlying data structure.
//
// Other than the initial strong `AddRef` call incrementing this value to 1,
@ -126,8 +99,8 @@ class ThreadSafeWeakReference
RC<MozRefCountType, AtomicRefCount> mStrongCnt{0};
// Raw pointer to the tracked object. It is never valid to read this value
// outside of `getRefPtr()`.
T* MOZ_NON_OWNING_REF mPtr;
// outside of `ThreadSafeWeakPtr::getRefPtr()`.
SupportsThreadSafeWeakPtrBase* MOZ_NON_OWNING_REF mPtr;
};
} // namespace detail
@ -143,20 +116,20 @@ class ThreadSafeWeakReference
// Which will result in the following layout:
//
// +--------------------+
// | MyType | <========================================+
// | MyType | <===============================================+
// +--------------------+ I
// | RefPtr mWeakRef o===========> +-------------------------+ I
// | RefPtr mWeakRef o======> +-------------------------------------+ I
// | uint32_t mMyData | | ThreadSafeWeakReference | I
// +--------------------+ +-------------------------+ I
// +--------------------+ +-------------------------------------+ I
// | RC mRefCount | I
// | RC mStrongCount | I
// | MyType* mPtr o======+
// +-------------------------+
// | SupportsThreadSafeWeakPtrBase* mPtr o====+
// +-------------------------------------+
//
// The mRefCount inherited from AtomicRefCounted<ThreadSafeWeakReference<T>> is
// the weak count. This means MyType implicitly holds a weak reference, so if
// the weak count ever hits 0, we know all strong *and* weak references are
// gone, and it's safe to free the ThreadSafeWeakReference. MyType's AddRef and
// The mRefCount inherited from AtomicRefCounted<ThreadSafeWeakReference> is the
// weak count. This means MyType implicitly holds a weak reference, so if the
// weak count ever hits 0, we know all strong *and* weak references are gone,
// and it's safe to free the ThreadSafeWeakReference. MyType's AddRef and
// Release implementations otherwise only manipulate mStrongCount.
//
// It's necessary to keep the counts in a separate allocation because we need
@ -164,17 +137,16 @@ class ThreadSafeWeakReference
// that weak references can still access all the state necessary to check if
// they can be upgraded (mStrongCount).
template <typename T>
class SupportsThreadSafeWeakPtr {
class SupportsThreadSafeWeakPtr : public detail::SupportsThreadSafeWeakPtrBase {
protected:
typedef detail::ThreadSafeWeakReference<T> ThreadSafeWeakReference;
using ThreadSafeWeakReference = detail::ThreadSafeWeakReference;
// The `this` pointer will not have subclasses initialized yet, but it will
// also not be read until a weak pointer is upgraded, which should be after
// this point.
SupportsThreadSafeWeakPtr()
: mWeakRef(new ThreadSafeWeakReference(static_cast<T*>(this))) {
static_assert(std::is_base_of_v<SupportsThreadSafeWeakPtr<T>, T>,
"T must derive from SupportsThreadSafeWeakPtr<T>");
SupportsThreadSafeWeakPtr() : mWeakRef(new ThreadSafeWeakReference(this)) {
static_assert(std::is_base_of_v<SupportsThreadSafeWeakPtr, T>,
"T must derive from SupportsThreadSafeWeakPtr");
}
public:
@ -225,9 +197,7 @@ class SupportsThreadSafeWeakPtr {
// A thread-safe variant of a weak pointer
template <typename T>
class ThreadSafeWeakPtr {
// Be careful to use the weak reference type T in the
// SupportsThreadSafeWeakPtr<T> definition.
typedef typename T::ThreadSafeWeakReference ThreadSafeWeakReference;
using ThreadSafeWeakReference = detail::ThreadSafeWeakReference;
public:
ThreadSafeWeakPtr() = default;
@ -295,10 +265,19 @@ class ThreadSafeWeakPtr {
private:
// Gets a new strong reference of the proper type T to the tracked object.
already_AddRefed<T> getRefPtr() const {
static_assert(std::is_base_of<typename ThreadSafeWeakReference::ElementType,
T>::value,
"T must derive from ThreadSafeWeakReference::ElementType");
return mRef ? mRef->getRefPtr().template downcast<T>() : nullptr;
if (!mRef) {
return nullptr;
}
// Increment our strong reference count only if it is nonzero, meaning that
// the object is still alive.
MozRefCountType cnt = mRef->mStrongCnt.IncrementIfNonzero();
if (cnt == 0) {
return nullptr;
}
RefPtr<T> ptr = already_AddRefed<T>(static_cast<T*>(mRef->mPtr));
detail::RefCountLogger::logAddRef(ptr.get(), cnt);
return ptr.forget();
}
// A shared weak reference to an object. Note that this may be null so as to

View File

@ -14,7 +14,6 @@ using mozilla::ThreadSafeWeakPtr;
// SupportsThreadSafeWeakPtr<C>.
class C : public SupportsThreadSafeWeakPtr<C> {
public:
MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(C)
MOZ_DECLARE_REFCOUNTED_TYPENAME(C)
int mNum;
@ -30,6 +29,13 @@ class C : public SupportsThreadSafeWeakPtr<C> {
void act() {}
};
// Test that declaring a ThreadSafeWeakPtr pointing to an incomplete type
// builds.
class Incomplete;
class D {
ThreadSafeWeakPtr<Incomplete> mMember;
};
int main() {
RefPtr<C> c1 = new C;
MOZ_RELEASE_ASSERT(c1->mNum == 0);

View File

@ -25,7 +25,6 @@ class AndroidVsyncSupport;
*/
class AndroidVsync final : public SupportsThreadSafeWeakPtr<AndroidVsync> {
public:
MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(AndroidVsync)
MOZ_DECLARE_REFCOUNTED_TYPENAME(AndroidVsync)
static RefPtr<AndroidVsync> GetInstance();