Bug 1251593 - Add the thread checking of AddRef() and Release() in RefCounted class. r=froydnj
☠☠ backed out by 520292912175 ☠ ☠
authorJerryShih <hshih@mozilla.com>
Thu, 17 Mar 2016 09:07:00 -0400
changeset 289308 516d8328dcb6718d4f0a23d772354ebe2267956a
parent 289307 5cd8db347c4970924362eb156c00d19950d99acb
child 289309 4cde1aabe95e6c8d98a88055797737481e04352f
push id30099
push usercbook@mozilla.com
push dateFri, 18 Mar 2016 14:52:23 +0000
treeherdermozilla-central@9c5d494d0548 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1251593
milestone48.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 1251593 - Add the thread checking of AddRef() and Release() in RefCounted class. r=froydnj
mfbt/RefCounted.h
--- a/mfbt/RefCounted.h
+++ b/mfbt/RefCounted.h
@@ -21,16 +21,25 @@
 #include "nsXPCOM.h"
 #endif
 
 #if defined(MOZILLA_INTERNAL_API) && \
     (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
 #define MOZ_REFCOUNTED_LEAK_CHECKING
 #endif
 
+#if defined(MOZILLA_INTERNAL_API) && \
+    defined(DEBUG)
+#define MOZ_REFCOUNTED_THREAD_CHECKING
+#endif
+
+#ifdef MOZ_REFCOUNTED_THREAD_CHECKING
+#include "nsISupports.h"
+#endif
+
 namespace mozilla {
 
 /**
  * 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.
@@ -92,31 +101,39 @@ class RefCounted
 protected:
   RefCounted() : mRefCnt(0) {}
   ~RefCounted() { MOZ_ASSERT(mRefCnt == detail::DEAD); }
 
 public:
   // Compatibility with nsRefPtr.
   void AddRef() const
   {
+#ifdef MOZ_REFCOUNTED_THREAD_CHECKING
+    RefCountThreadCheck(IntegralConstant<RefCountAtomicity, Atomicity>());
+#endif
+
     // 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
   {
+#ifdef MOZ_REFCOUNTED_THREAD_CHECKING
+    RefCountThreadCheck(IntegralConstant<RefCountAtomicity, Atomicity>());
+#endif
+
     // 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;
@@ -145,16 +162,30 @@ public:
     MOZ_ASSERT(mRefCnt > 0);
     return mRefCnt == 1;
   }
 
 private:
   mutable typename Conditional<Atomicity == AtomicRefCount,
                                Atomic<MozRefCountType>,
                                MozRefCountType>::Type mRefCnt;
+
+#ifdef MOZ_REFCOUNTED_THREAD_CHECKING
+  void RefCountThreadCheck(IntegralConstant<RefCountAtomicity, AtomicRefCount>) const
+  {
+    // no need to check the thread if we use AtomicRefCount.
+  }
+
+  void RefCountThreadCheck(IntegralConstant<RefCountAtomicity, NonAtomicRefCount>) const
+  {
+    NS_ASSERT_OWNINGTHREAD(RefCounted);
+  }
+
+  NS_DECL_OWNINGTHREAD;
+#endif
 };
 
 #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); }