Bug 884061 - Part 2: Add NS_DECL_THREADSAFE_ISUPPORTS, r=jlebar.
authorJoshua Cranmer <Pidgeot18@gmail.com>
Sat, 13 Jul 2013 20:28:54 -0500
changeset 139598 256cf2fd8c6fe01d15ae5ff25fb8d17f2f4efdd4
parent 139597 955975fb2ca768f7d966fd6bfd5766e556aeae10
child 139599 b8a7770098437354bb62bbe8c48e0d655dcb385b
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjlebar
bugs884061
milestone25.0a1
Bug 884061 - Part 2: Add NS_DECL_THREADSAFE_ISUPPORTS, r=jlebar.
xpcom/glue/nsISupportsImpl.h
--- a/xpcom/glue/nsISupportsImpl.h
+++ b/xpcom/glue/nsISupportsImpl.h
@@ -197,20 +197,21 @@ class nsAutoRefCnt {
 
     // only support prefix increment/decrement
     nsrefcnt operator++() { return ++mValue; }
     nsrefcnt operator--() { return --mValue; }
 
     nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); }
     operator nsrefcnt() const { return mValue; }
     nsrefcnt get() const { return mValue; }
+
+    static const bool isThreadSafe = false;
  private:
-    // do not define these to enforce the faster prefix notation
-    nsrefcnt operator++(int);
-    nsrefcnt operator--(int);
+    nsrefcnt operator++(int) MOZ_DELETE;
+    nsrefcnt operator--(int) MOZ_DELETE;
     nsrefcnt mValue;
 };
 
 #ifndef XPCOM_GLUE
 namespace mozilla {
 class ThreadSafeAutoRefCnt {
  public:
     ThreadSafeAutoRefCnt() : mValue(0) {}
@@ -218,25 +219,40 @@ class ThreadSafeAutoRefCnt {
     
     // only support prefix increment/decrement
     MOZ_ALWAYS_INLINE nsrefcnt operator++() { return ++mValue; }
     MOZ_ALWAYS_INLINE nsrefcnt operator--() { return --mValue; }
 
     MOZ_ALWAYS_INLINE nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); }
     MOZ_ALWAYS_INLINE operator nsrefcnt() const { return mValue; }
     MOZ_ALWAYS_INLINE nsrefcnt get() const { return mValue; }
+
+    static const bool isThreadSafe = true;
  private:
     nsrefcnt operator++(int) MOZ_DELETE;
     nsrefcnt operator--(int) MOZ_DELETE;
     // In theory, RelaseAcquire consistency (but no weaker) is sufficient for
     // the counter. Making it weaker could speed up builds on ARM (but not x86),
     // but could break pre-existing code that assumes sequential consistency.
     Atomic<nsrefcnt> mValue;
 };
 }
+
+// Temporary declarations until NS_IMPL_THREADSAFE_ADDREF/RELEASE are deleted.
+inline nsrefcnt
+NS_AtomicIncrementRefcnt(mozilla::ThreadSafeAutoRefCnt &refcnt)
+{
+  return ++refcnt;
+}
+
+inline nsrefcnt
+NS_AtomicDecrementRefcnt(mozilla::ThreadSafeAutoRefCnt &refcnt)
+{
+  return --refcnt;
+}
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
  * Declare the reference count variable and the implementations of the
  * AddRef and QueryInterface methods.
  */
@@ -247,16 +263,27 @@ public:                                 
                             void** aInstancePtr);                             \
   NS_IMETHOD_(nsrefcnt) AddRef(void);                                         \
   NS_IMETHOD_(nsrefcnt) Release(void);                                        \
 protected:                                                                    \
   nsAutoRefCnt mRefCnt;                                                       \
   NS_DECL_OWNINGTHREAD                                                        \
 public:
 
+#define NS_DECL_THREADSAFE_ISUPPORTS                                          \
+public:                                                                       \
+  NS_IMETHOD QueryInterface(REFNSIID aIID,                                    \
+                            void** aInstancePtr);                             \
+  NS_IMETHOD_(nsrefcnt) AddRef(void);                                         \
+  NS_IMETHOD_(nsrefcnt) Release(void);                                        \
+protected:                                                                    \
+  ::mozilla::ThreadSafeAutoRefCnt mRefCnt;                                    \
+  NS_DECL_OWNINGTHREAD                                                        \
+public:
+
 #define NS_DECL_CYCLE_COLLECTING_ISUPPORTS                                    \
 public:                                                                       \
   NS_IMETHOD QueryInterface(REFNSIID aIID,                                    \
                             void** aInstancePtr);                             \
   NS_IMETHOD_(nsrefcnt) AddRef(void);                                         \
   NS_IMETHOD_(nsrefcnt) Release(void);                                        \
   NS_IMETHOD_(void) DeleteCycleCollectable(void);                             \
 protected:                                                                    \
@@ -413,20 +440,21 @@ public:
 /**
  * Use this macro to implement the AddRef method for a given <i>_class</i>
  * @param _class The name of the class implementing the method
  */
 #define NS_IMPL_ADDREF(_class)                                                \
 NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void)                                 \
 {                                                                             \
   MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                        \
-  NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class);                            \
-  ++mRefCnt;                                                                  \
-  NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this));                       \
-  return mRefCnt;                                                             \
+  if (!mRefCnt.isThreadSafe)                                                  \
+    NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class);                          \
+  nsrefcnt count = ++mRefCnt;                                                 \
+  NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                         \
+  return count;                                                               \
 }
 
 /**
  * Use this macro to implement the AddRef method for a given <i>_class</i>
  * implemented as a wholly owned aggregated object intended to implement
  * interface(s) for its owner
  * @param _class The name of the class implementing the method
  * @param _aggregator the owning/containing object
@@ -456,26 +484,28 @@ NS_IMETHODIMP_(nsrefcnt) _class::AddRef(
  * to be invoked when the object's refcount drops to zero. This
  * allows for arbitrary teardown activity to occur (e.g., deallocation
  * of object allocated with placement new).
  */
 #define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy)                        \
 NS_IMETHODIMP_(nsrefcnt) _class::Release(void)                                \
 {                                                                             \
   MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                            \
-  NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class);                            \
-  --mRefCnt;                                                                  \
-  NS_LOG_RELEASE(this, mRefCnt, #_class);                                     \
-  if (mRefCnt == 0) {                                                         \
-    NS_ASSERT_OWNINGTHREAD(_class);                                           \
+  if (!mRefCnt.isThreadSafe)                                                  \
+    NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class);                          \
+  nsrefcnt count = --mRefCnt;                                                 \
+  NS_LOG_RELEASE(this, count, #_class);                                       \
+  if (count == 0) {                                                           \
+    if (!mRefCnt.isThreadSafe)                                                \
+      NS_ASSERT_OWNINGTHREAD(_class);                                         \
     mRefCnt = 1; /* stabilize */                                              \
     _destroy;                                                                 \
     return 0;                                                                 \
   }                                                                           \
-  return mRefCnt;                                                             \
+  return count;                                                               \
 }
 
 /**
  * Use this macro to implement the Release method for a given <i>_class</i>
  * @param _class The name of the class implementing the method
  *
  * A note on the 'stabilization' of the refcnt to one. At that point,
  * the object's refcount will have gone to zero. The object's