Bug 1207245 - part 1 - move RefCounted<T> to its own file
authorNathan Froyd <froydnj@mozilla.com>
Tue, 22 Sep 2015 21:27:34 -0400
changeset 264237 a4ee8cbe5e73b70a0bdbb3700703536af55d3529
parent 264236 86cd8c6a23d14792c9c4daebcefb9298f0b77822
child 264238 86fb8a462b04823fe06d93c8d2f62cd7c32b0da9
push id29431
push userkwierso@gmail.com
push dateThu, 24 Sep 2015 23:46:41 +0000
treeherderautoland@eee426604698 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1207245
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1207245 - part 1 - move RefCounted<T> to its own file Various bits depend on RefPtr.h to provide RefCounted<T> and RefPtr<T>. It will be easier to manage an automatic conversion from RefPtr<T> to nsRefPtr<T> if we split out the dependency on RefCounted<T> first.
devtools/shared/heapsnapshot/HeapSnapshot.h
gfx/2d/GenericRefCounted.h
image/SourceBuffer.h
memory/volatile/VolatileBuffer.h
mfbt/RefCounted.h
mfbt/RefPtr.h
mfbt/WeakPtr.h
mfbt/moz.build
mfbt/tests/TestRefPtr.cpp
tools/profiler/core/ProfileBuffer.h
--- a/devtools/shared/heapsnapshot/HeapSnapshot.h
+++ b/devtools/shared/heapsnapshot/HeapSnapshot.h
@@ -7,16 +7,17 @@
 #define mozilla_devtools_HeapSnapshot__
 
 #include "js/HashTable.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/devtools/DeserializedNode.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/Maybe.h"
+#include "mozilla/RefCounted.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
 
 #include "CoreDump.pb.h"
 #include "nsCOMPtr.h"
 #include "nsCRTGlue.h"
 #include "nsCycleCollectionParticipant.h"
--- a/gfx/2d/GenericRefCounted.h
+++ b/gfx/2d/GenericRefCounted.h
@@ -6,16 +6,17 @@
 // This header provides virtual, non-templated alternatives to MFBT's RefCounted<T>.
 // It intentionally uses MFBT coding style with the intention of moving there
 // should there be other use cases for it.
 
 #ifndef MOZILLA_GENERICREFCOUNTED_H_
 #define MOZILLA_GENERICREFCOUNTED_H_
 
 #include "mozilla/RefPtr.h"
+#include "mozilla/RefCounted.h"
 
 namespace mozilla {
 
 /**
  * Common base class for GenericRefCounted and GenericAtomicRefCounted.
  *
  * Having this shared base class, common to both the atomic and non-atomic
  * cases, allows to have RefPtr's that don't care about whether the
--- a/image/SourceBuffer.h
+++ b/image/SourceBuffer.h
@@ -12,16 +12,17 @@
 #define mozilla_image_sourcebuffer_h
 
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Move.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/RefCounted.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/nsRefPtr.h"
 #include "nsTArray.h"
 
 class nsIInputStream;
 
 namespace mozilla {
 namespace image {
--- a/memory/volatile/VolatileBuffer.h
+++ b/memory/volatile/VolatileBuffer.h
@@ -4,16 +4,17 @@
 
 #ifndef mozalloc_VolatileBuffer_h
 #define mozalloc_VolatileBuffer_h
 
 #include "mozilla/mozalloc.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/RefCounted.h"
 
 /* VolatileBuffer
  *
  * This class represents a piece of memory that can potentially be reclaimed
  * by the OS when not in use. As long as there are one or more
  * VolatileBufferPtrs holding on to a VolatileBuffer, the memory will remain
  * available. However, when there are no VolatileBufferPtrs holding a
  * VolatileBuffer, the OS can purge the pages if it wants to. The OS can make
new file mode 100644
--- /dev/null
+++ b/mfbt/RefCounted.h
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* CRTP refcounting templates.  Do not use unless you are an Expert. */
+
+#ifndef mozilla_RefCounted_h
+#define mozilla_RefCounted_h
+
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/Atomics.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Move.h"
+#include "mozilla/RefCountType.h"
+#include "mozilla/TypeTraits.h"
+
+#if defined(MOZILLA_INTERNAL_API)
+#include "nsXPCOM.h"
+#endif
+
+#if defined(MOZILLA_INTERNAL_API) && \
+    !defined(MOZILLA_XPCOMRT_API) && \
+    (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
+#define MOZ_REFCOUNTED_LEAK_CHECKING
+#endif
+
+namespace mozilla {
+
+template<typename T> class RefPtr;
+
+/**
+ * RefCounted<T> is a sort of a "mixin" for a class T.  RefCounted
+ * manages, well, refcounting for T, and because RefCounted is
+ * parameterized on T, RefCounted<T> can call T's destructor directly.
+ * This means T doesn't need to have a virtual dtor and so doesn't
+ * need a vtable.
+ *
+ * RefCounted<T> is created with refcount == 0.  Newly-allocated
+ * RefCounted<T> must immediately be assigned to a RefPtr to make the
+ * refcount > 0.  It's an error to allocate and free a bare
+ * RefCounted<T>, i.e. outside of the RefPtr machinery.  Attempts to
+ * do so will abort DEBUG builds.
+ *
+ * Live RefCounted<T> have refcount > 0.  The lifetime (refcounts) of
+ * live RefCounted<T> are controlled by nsRefPtr<T> and
+ * nsRefPtr<super/subclass of T>.  Upon a transition from refcounted==1
+ * to 0, the RefCounted<T> "dies" and is destroyed.  The "destroyed"
+ * state is represented in DEBUG builds by refcount==0xffffdead.  This
+ * state distinguishes use-before-ref (refcount==0) from
+ * use-after-destroy (refcount==0xffffdead).
+ *
+ * Note that when deriving from RefCounted or AtomicRefCounted, you
+ * should add MOZ_DECLARE_REFCOUNTED_TYPENAME(ClassName) to the public
+ * section of your class, where ClassName is the name of your class.
+ */
+namespace detail {
+const MozRefCountType DEAD = 0xffffdead;
+
+// When building code that gets compiled into Gecko, try to use the
+// trace-refcount leak logging facilities.
+#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
+class RefCountLogger
+{
+public:
+  static void logAddRef(const void* aPointer, MozRefCountType aRefCount,
+                        const char* aTypeName, uint32_t aInstanceSize)
+  {
+    MOZ_ASSERT(aRefCount != DEAD);
+    NS_LogAddRef(const_cast<void*>(aPointer), aRefCount, aTypeName,
+                 aInstanceSize);
+  }
+
+  static void logRelease(const void* aPointer, MozRefCountType aRefCount,
+                         const char* aTypeName)
+  {
+    MOZ_ASSERT(aRefCount != DEAD);
+    NS_LogRelease(const_cast<void*>(aPointer), aRefCount, aTypeName);
+  }
+};
+#endif
+
+// This is used WeakPtr.h as well as this file.
+enum RefCountAtomicity
+{
+  AtomicRefCount,
+  NonAtomicRefCount
+};
+
+template<typename T, RefCountAtomicity Atomicity>
+class RefCounted
+{
+  friend class RefPtr<T>;
+
+protected:
+  RefCounted() : mRefCnt(0) {}
+  ~RefCounted() { MOZ_ASSERT(mRefCnt == detail::DEAD); }
+
+public:
+  // Compatibility with nsRefPtr.
+  void AddRef() const
+  {
+    // Note: this method must be thread safe for AtomicRefCounted.
+    MOZ_ASSERT(int32_t(mRefCnt) >= 0);
+#ifndef MOZ_REFCOUNTED_LEAK_CHECKING
+    ++mRefCnt;
+#else
+    const char* type = static_cast<const T*>(this)->typeName();
+    uint32_t size = static_cast<const T*>(this)->typeSize();
+    const void* ptr = static_cast<const T*>(this);
+    MozRefCountType cnt = ++mRefCnt;
+    detail::RefCountLogger::logAddRef(ptr, cnt, type, size);
+#endif
+  }
+
+  void Release() const
+  {
+    // Note: this method must be thread safe for AtomicRefCounted.
+    MOZ_ASSERT(int32_t(mRefCnt) > 0);
+#ifndef MOZ_REFCOUNTED_LEAK_CHECKING
+    MozRefCountType cnt = --mRefCnt;
+#else
+    const char* type = static_cast<const T*>(this)->typeName();
+    const void* ptr = static_cast<const T*>(this);
+    MozRefCountType cnt = --mRefCnt;
+    // Note: it's not safe to touch |this| after decrementing the refcount,
+    // except for below.
+    detail::RefCountLogger::logRelease(ptr, cnt, type);
+#endif
+    if (0 == cnt) {
+      // Because we have atomically decremented the refcount above, only
+      // one thread can get a 0 count here, so as long as we can assume that
+      // everything else in the system is accessing this object through
+      // RefPtrs, it's safe to access |this| here.
+#ifdef DEBUG
+      mRefCnt = detail::DEAD;
+#endif
+      delete static_cast<const T*>(this);
+    }
+  }
+
+  // Compatibility with wtf::RefPtr.
+  void ref() { AddRef(); }
+  void deref() { Release(); }
+  MozRefCountType refCount() const { return mRefCnt; }
+  bool hasOneRef() const
+  {
+    MOZ_ASSERT(mRefCnt > 0);
+    return mRefCnt == 1;
+  }
+
+private:
+  mutable typename Conditional<Atomicity == AtomicRefCount,
+                               Atomic<MozRefCountType>,
+                               MozRefCountType>::Type mRefCnt;
+};
+
+#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
+// Passing override for the optional argument marks the typeName and
+// typeSize functions defined by this macro as overrides.
+#define MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(T, ...) \
+  virtual const char* typeName() const __VA_ARGS__ { return #T; } \
+  virtual size_t typeSize() const __VA_ARGS__ { return sizeof(*this); }
+#else
+#define MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(T, ...)
+#endif
+
+// Note that this macro is expanded unconditionally because it declares only
+// two small inline functions which will hopefully get eliminated by the linker
+// in non-leak-checking builds.
+#define MOZ_DECLARE_REFCOUNTED_TYPENAME(T) \
+  const char* typeName() const { return #T; } \
+  size_t typeSize() const { return sizeof(*this); }
+
+} // namespace detail
+
+template<typename T>
+class RefCounted : public detail::RefCounted<T, detail::NonAtomicRefCount>
+{
+public:
+  ~RefCounted()
+  {
+    static_assert(IsBaseOf<RefCounted, T>::value,
+                  "T must derive from RefCounted<T>");
+  }
+};
+
+namespace external {
+
+/**
+ * AtomicRefCounted<T> is like RefCounted<T>, with an atomically updated
+ * reference counter.
+ *
+ * NOTE: Please do not use this class, use NS_INLINE_DECL_THREADSAFE_REFCOUNTING
+ * instead.
+ */
+template<typename T>
+class AtomicRefCounted :
+  public mozilla::detail::RefCounted<T, mozilla::detail::AtomicRefCount>
+{
+public:
+  ~AtomicRefCounted()
+  {
+    static_assert(IsBaseOf<AtomicRefCounted, T>::value,
+                  "T must derive from AtomicRefCounted<T>");
+  }
+};
+
+} // namespace external
+
+} // namespace mozilla
+
+#endif // mozilla_RefCounted_h
--- a/mfbt/RefPtr.h
+++ b/mfbt/RefPtr.h
@@ -9,216 +9,36 @@
 #ifndef mozilla_RefPtr_h
 #define mozilla_RefPtr_h
 
 #include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Move.h"
+#include "mozilla/RefCounted.h"
 #include "mozilla/RefCountType.h"
 #include "mozilla/nsRefPtr.h"
 #include "mozilla/TypeTraits.h"
 #if defined(MOZILLA_INTERNAL_API)
 #include "nsXPCOM.h"
 #endif
 
 #if defined(MOZILLA_INTERNAL_API) && \
     !defined(MOZILLA_XPCOMRT_API) && \
     (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
 #define MOZ_REFCOUNTED_LEAK_CHECKING
 #endif
 
 namespace mozilla {
 
-template<typename T> class RefCounted;
-template<typename T> class RefPtr;
 template<typename T> class OutParamRef;
 template<typename T> OutParamRef<T> byRef(RefPtr<T>&);
 
 /**
- * RefCounted<T> is a sort of a "mixin" for a class T.  RefCounted
- * manages, well, refcounting for T, and because RefCounted is
- * parameterized on T, RefCounted<T> can call T's destructor directly.
- * This means T doesn't need to have a virtual dtor and so doesn't
- * need a vtable.
- *
- * RefCounted<T> is created with refcount == 0.  Newly-allocated
- * RefCounted<T> must immediately be assigned to a RefPtr to make the
- * refcount > 0.  It's an error to allocate and free a bare
- * RefCounted<T>, i.e. outside of the RefPtr machinery.  Attempts to
- * do so will abort DEBUG builds.
- *
- * Live RefCounted<T> have refcount > 0.  The lifetime (refcounts) of
- * live RefCounted<T> are controlled by RefPtr<T> and
- * RefPtr<super/subclass of T>.  Upon a transition from refcounted==1
- * to 0, the RefCounted<T> "dies" and is destroyed.  The "destroyed"
- * state is represented in DEBUG builds by refcount==0xffffdead.  This
- * state distinguishes use-before-ref (refcount==0) from
- * use-after-destroy (refcount==0xffffdead).
- *
- * Note that when deriving from RefCounted or AtomicRefCounted, you
- * should add MOZ_DECLARE_REFCOUNTED_TYPENAME(ClassName) to the public
- * section of your class, where ClassName is the name of your class.
- */
-namespace detail {
-const MozRefCountType DEAD = 0xffffdead;
-
-// When building code that gets compiled into Gecko, try to use the
-// trace-refcount leak logging facilities.
-#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
-class RefCountLogger
-{
-public:
-  static void logAddRef(const void* aPointer, MozRefCountType aRefCount,
-                        const char* aTypeName, uint32_t aInstanceSize)
-  {
-    MOZ_ASSERT(aRefCount != DEAD);
-    NS_LogAddRef(const_cast<void*>(aPointer), aRefCount, aTypeName,
-                 aInstanceSize);
-  }
-
-  static void logRelease(const void* aPointer, MozRefCountType aRefCount,
-                         const char* aTypeName)
-  {
-    MOZ_ASSERT(aRefCount != DEAD);
-    NS_LogRelease(const_cast<void*>(aPointer), aRefCount, aTypeName);
-  }
-};
-#endif
-
-// This is used WeakPtr.h as well as this file.
-enum RefCountAtomicity
-{
-  AtomicRefCount,
-  NonAtomicRefCount
-};
-
-template<typename T, RefCountAtomicity Atomicity>
-class RefCounted
-{
-  friend class RefPtr<T>;
-
-protected:
-  RefCounted() : mRefCnt(0) {}
-  ~RefCounted() { MOZ_ASSERT(mRefCnt == detail::DEAD); }
-
-public:
-  // Compatibility with nsRefPtr.
-  void AddRef() const
-  {
-    // Note: this method must be thread safe for AtomicRefCounted.
-    MOZ_ASSERT(int32_t(mRefCnt) >= 0);
-#ifndef MOZ_REFCOUNTED_LEAK_CHECKING
-    ++mRefCnt;
-#else
-    const char* type = static_cast<const T*>(this)->typeName();
-    uint32_t size = static_cast<const T*>(this)->typeSize();
-    const void* ptr = static_cast<const T*>(this);
-    MozRefCountType cnt = ++mRefCnt;
-    detail::RefCountLogger::logAddRef(ptr, cnt, type, size);
-#endif
-  }
-
-  void Release() const
-  {
-    // Note: this method must be thread safe for AtomicRefCounted.
-    MOZ_ASSERT(int32_t(mRefCnt) > 0);
-#ifndef MOZ_REFCOUNTED_LEAK_CHECKING
-    MozRefCountType cnt = --mRefCnt;
-#else
-    const char* type = static_cast<const T*>(this)->typeName();
-    const void* ptr = static_cast<const T*>(this);
-    MozRefCountType cnt = --mRefCnt;
-    // Note: it's not safe to touch |this| after decrementing the refcount,
-    // except for below.
-    detail::RefCountLogger::logRelease(ptr, cnt, type);
-#endif
-    if (0 == cnt) {
-      // Because we have atomically decremented the refcount above, only
-      // one thread can get a 0 count here, so as long as we can assume that
-      // everything else in the system is accessing this object through
-      // RefPtrs, it's safe to access |this| here.
-#ifdef DEBUG
-      mRefCnt = detail::DEAD;
-#endif
-      delete static_cast<const T*>(this);
-    }
-  }
-
-  // Compatibility with wtf::RefPtr.
-  void ref() { AddRef(); }
-  void deref() { Release(); }
-  MozRefCountType refCount() const { return mRefCnt; }
-  bool hasOneRef() const
-  {
-    MOZ_ASSERT(mRefCnt > 0);
-    return mRefCnt == 1;
-  }
-
-private:
-  mutable typename Conditional<Atomicity == AtomicRefCount,
-                               Atomic<MozRefCountType>,
-                               MozRefCountType>::Type mRefCnt;
-};
-
-#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
-// Passing override for the optional argument marks the typeName and
-// typeSize functions defined by this macro as overrides.
-#define MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(T, ...) \
-  virtual const char* typeName() const __VA_ARGS__ { return #T; } \
-  virtual size_t typeSize() const __VA_ARGS__ { return sizeof(*this); }
-#else
-#define MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(T, ...)
-#endif
-
-// Note that this macro is expanded unconditionally because it declares only
-// two small inline functions which will hopefully get eliminated by the linker
-// in non-leak-checking builds.
-#define MOZ_DECLARE_REFCOUNTED_TYPENAME(T) \
-  const char* typeName() const { return #T; } \
-  size_t typeSize() const { return sizeof(*this); }
-
-} // namespace detail
-
-template<typename T>
-class RefCounted : public detail::RefCounted<T, detail::NonAtomicRefCount>
-{
-public:
-  ~RefCounted()
-  {
-    static_assert(IsBaseOf<RefCounted, T>::value,
-                  "T must derive from RefCounted<T>");
-  }
-};
-
-namespace external {
-
-/**
- * AtomicRefCounted<T> is like RefCounted<T>, with an atomically updated
- * reference counter.
- *
- * NOTE: Please do not use this class, use NS_INLINE_DECL_THREADSAFE_REFCOUNTING
- * instead.
- */
-template<typename T>
-class AtomicRefCounted :
-  public mozilla::detail::RefCounted<T, mozilla::detail::AtomicRefCount>
-{
-public:
-  ~AtomicRefCounted()
-  {
-    static_assert(IsBaseOf<AtomicRefCounted, T>::value,
-                  "T must derive from AtomicRefCounted<T>");
-  }
-};
-
-} // namespace external
-
-/**
  * RefPtr points to a refcounted thing that has AddRef and Release
  * methods to increase/decrease the refcount, respectively.  After a
  * RefPtr<T> is assigned a T*, the T* can be used through the RefPtr
  * as if it were a T*.
  *
  * A RefPtr can forget its underlying T*, which results in the T*
  * being wrapped in a temporary object until the T* is either
  * re-adopted from or released by the temporary.
--- a/mfbt/WeakPtr.h
+++ b/mfbt/WeakPtr.h
@@ -65,16 +65,17 @@
  */
 
 #ifndef mozilla_WeakPtr_h
 #define mozilla_WeakPtr_h
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/RefCounted.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/TypeTraits.h"
 
 #include <string.h>
 
 namespace mozilla {
 
 template <typename T> class WeakPtr;
--- a/mfbt/moz.build
+++ b/mfbt/moz.build
@@ -62,16 +62,17 @@ EXPORTS.mozilla = [
     'NullPtr.h',
     'NumericLimits.h',
     'Pair.h',
     'PodOperations.h',
     'Poison.h',
     'Range.h',
     'RangedArray.h',
     'RangedPtr.h',
+    'RefCounted.h',
     'RefCountType.h',
     'ReentrancyGuard.h',
     'RefPtr.h',
     'ReverseIterator.h',
     'RollingMean.h',
     'Scoped.h',
     'ScopeExit.h',
     'SegmentedVector.h',
--- a/mfbt/tests/TestRefPtr.cpp
+++ b/mfbt/tests/TestRefPtr.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/RefPtr.h"
+#include "mozilla/RefCounted.h"
 
 using mozilla::RefCounted;
 using mozilla::RefPtr;
 
 class Foo : public RefCounted<Foo>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_TYPENAME(Foo)
--- a/tools/profiler/core/ProfileBuffer.h
+++ b/tools/profiler/core/ProfileBuffer.h
@@ -5,16 +5,17 @@
 
 #ifndef MOZ_PROFILE_BUFFER_H
 #define MOZ_PROFILE_BUFFER_H
 
 #include "ProfileEntry.h"
 #include "platform.h"
 #include "ProfileJSONWriter.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/RefCounted.h"
 
 class ProfileBuffer : public mozilla::RefCounted<ProfileBuffer> {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ProfileBuffer)
 
   explicit ProfileBuffer(int aEntrySize);
 
   virtual ~ProfileBuffer();