Eliminate duplicate code by combining nsNonOwningRunnableMethod with nsRunnableMethod (part 1/3 of bug 558498). r=dwitte sr=dbaron
authorBen Newman <bnewman@mozilla.com>
Tue, 20 Apr 2010 10:22:04 -0700
changeset 41359 d6c5f8853dcec005bfbc2741546f2f3d7c52f5cc
parent 41358 861f07be1937071488b7fe0d3f4f600b5eb1310d
child 41360 a3733b568431be685ffd2a4d8d76147ee8661705
push idunknown
push userunknown
push dateunknown
reviewersdwitte, dbaron
bugs558498
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
Eliminate duplicate code by combining nsNonOwningRunnableMethod with nsRunnableMethod (part 1/3 of bug 558498). r=dwitte sr=dbaron
content/base/src/nsContentSink.cpp
content/base/src/nsContentSink.h
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/media/nsMediaStream.cpp
content/media/nsMediaStream.h
xpcom/glue/nsThreadUtils.h
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -439,18 +439,18 @@ nsContentSink::ProcessHTTPHeaders(nsICha
   if (NS_SUCCEEDED(rv) && !linkHeader.IsEmpty()) {
     mDocument->SetHeaderData(nsGkAtoms::link,
                              NS_ConvertASCIItoUTF16(linkHeader));
 
     NS_ASSERTION(!mProcessLinkHeaderEvent.get(),
                  "Already dispatched an event?");
 
     mProcessLinkHeaderEvent =
-      new nsNonOwningRunnableMethod<nsContentSink>(this,
-                                           &nsContentSink::DoProcessLinkHeader);
+      new nsRunnableMethod<nsContentSink, void, false>(this,
+        &nsContentSink::DoProcessLinkHeader);
     rv = NS_DispatchToCurrentThread(mProcessLinkHeaderEvent.get());
     if (NS_FAILED(rv)) {
       mProcessLinkHeaderEvent.Forget();
     }
   }
   
   return NS_OK;
 }
--- a/content/base/src/nsContentSink.h
+++ b/content/base/src/nsContentSink.h
@@ -395,17 +395,17 @@ protected:
 
   PRInt32 mInMonolithicContainer;
 
   PRInt32 mInNotification;
   PRUint32 mUpdatesInNotification;
 
   PRUint32 mPendingSheetCount;
 
-  nsRevocableEventPtr<nsNonOwningRunnableMethod<nsContentSink> >
+  nsRevocableEventPtr<nsRunnableMethod<nsContentSink, void, false> >
     mProcessLinkHeaderEvent;
 };
 
 // sanitizing content sink whitelists
 extern PRBool IsAttrURI(nsIAtom *aName);
 extern nsIAtom** const kDefaultAllowedTags [];
 extern nsIAtom** const kDefaultAllowedAttributes [];
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -5154,19 +5154,19 @@ void
 nsDocument::NotifyPossibleTitleChange(PRBool aBoundTitleElement)
 {
   if (aBoundTitleElement) {
     mMayHaveTitleElement = PR_TRUE;
   }
   if (mPendingTitleChangeEvent.IsPending())
     return;
 
-  nsRefPtr<nsNonOwningRunnableMethod<nsDocument> > event =
-      new nsNonOwningRunnableMethod<nsDocument>(this,
-            &nsDocument::DoNotifyPossibleTitleChange);
+  nsRefPtr<nsRunnableMethod<nsDocument, void, false> > event =
+    new nsRunnableMethod<nsDocument, void, false>(this,
+      &nsDocument::DoNotifyPossibleTitleChange);
   nsresult rv = NS_DispatchToCurrentThread(event);
   if (NS_SUCCEEDED(rv)) {
     mPendingTitleChangeEvent = event;
   }
 }
 
 void
 nsDocument::DoNotifyPossibleTitleChange()
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1189,17 +1189,17 @@ private:
 
   // Member to store out last-selected stylesheet set.
   nsString mLastStyleSheetSet;
 
   nsTArray<nsRefPtr<nsFrameLoader> > mInitializableFrameLoaders;
   nsTArray<nsRefPtr<nsFrameLoader> > mFinalizableFrameLoaders;
   nsRefPtr<nsRunnableMethod<nsDocument> > mFrameLoaderRunner;
 
-  nsRevocableEventPtr<nsNonOwningRunnableMethod<nsDocument> >
+  nsRevocableEventPtr<nsRunnableMethod<nsDocument, void, false> >
     mPendingTitleChangeEvent;
 
   nsExternalResourceMap mExternalResourceMap;
 
   // All images in process of being preloaded
   nsCOMArray<imgIRequest> mPreloadingImages;
 
   nsCOMPtr<nsIDOMDOMImplementation> mDOMImplementation;
--- a/content/media/nsMediaStream.cpp
+++ b/content/media/nsMediaStream.cpp
@@ -668,17 +668,17 @@ nsMediaChannelStream::CacheClientNotifyD
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
   // NOTE: this can be called with the media cache lock held, so don't
   // block or do anything which might try to acquire a lock!
 
   if (mDataReceivedEvent.IsPending())
     return;
 
   mDataReceivedEvent =
-    new nsNonOwningRunnableMethod<nsMediaChannelStream>(this, &nsMediaChannelStream::DoNotifyDataReceived);
+    new nsRunnableMethod<nsMediaChannelStream, void, false>(this, &nsMediaChannelStream::DoNotifyDataReceived);
   NS_DispatchToMainThread(mDataReceivedEvent.get(), NS_DISPATCH_NORMAL);
 }
 
 class DataEnded : public nsRunnable {
 public:
   DataEnded(nsMediaDecoder* aDecoder, nsresult aStatus) :
     mDecoder(aDecoder), mStatus(aStatus) {}
   NS_IMETHOD Run() {
--- a/content/media/nsMediaStream.h
+++ b/content/media/nsMediaStream.h
@@ -406,17 +406,17 @@ protected:
                                       PRUint32 aCount,
                                       PRUint32 *aWriteCount);
 
   // Main thread access only
   PRInt64            mOffset;
   nsRefPtr<Listener> mListener;
   // A data received event for the decoder that has been dispatched but has
   // not yet been processed.
-  nsRevocableEventPtr<nsNonOwningRunnableMethod<nsMediaChannelStream> > mDataReceivedEvent;
+  nsRevocableEventPtr<nsRunnableMethod<nsMediaChannelStream, void, false> > mDataReceivedEvent;
   PRUint32           mSuspendCount;
   // When this flag is set, if we get a network error we should silently
   // reopen the stream.
   PRPackedBool       mReopenOnError;
   // When this flag is set, we should not report the next close of the
   // channel.
   PRPackedBool       mIgnoreClose;
 
--- a/xpcom/glue/nsThreadUtils.h
+++ b/xpcom/glue/nsThreadUtils.h
@@ -257,39 +257,56 @@ public:
 protected:
   virtual ~nsRunnable() {
   }
 };
 
 #undef  IMETHOD_VISIBILITY
 #define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
 
+template <class ClassType, bool Owning>
+struct RunnableMethodReceiver {
+  ClassType *mObj;
+  RunnableMethodReceiver(ClassType *obj) : mObj(obj) { NS_IF_ADDREF(mObj); }
+ ~RunnableMethodReceiver() { Revoke(); }
+  void Revoke() { NS_IF_RELEASE(mObj); }
+};
+
+template <class ClassType>
+struct RunnableMethodReceiver<ClassType, false> {
+  ClassType *mObj;
+  RunnableMethodReceiver(ClassType *obj) : mObj(obj) {}
+  void Revoke() { mObj = nsnull; }
+};
+
 // An event that can be used to call a method on a class.  The class type must
 // support reference counting. This event supports Revoke for use
 // with nsRevocableEventPtr.
-template <class ClassType, typename ReturnType = void>
+template <class ClassType,
+          typename ReturnType = void,
+          bool Owning = true>
 class nsRunnableMethod : public nsRunnable
 {
 public:
   typedef ReturnType (ClassType::*Method)();
 
   nsRunnableMethod(ClassType *obj, Method method)
-    : mObj(obj), mMethod(method) {
-    NS_ADDREF(mObj);
-  }
+    : mReceiver(obj)
+    , mMethod(method)
+  {}
 
   NS_IMETHOD Run() {
-    if (!mObj)
+    if (!mReceiver.mObj)
       return NS_OK;
-    (mObj->*mMethod)();
+    (mReceiver.mObj->*mMethod)();
     return NS_OK;
   }
 
   void Revoke() {
-    NS_IF_RELEASE(mObj);
+    mReceiver.Revoke();
   }
 
   // These ReturnTypeEnforcer classes set up a blacklist for return types that
   // we know are not safe. The default ReturnTypeEnforcer compiles just fine but
   // already_AddRefed will not.
   template <typename OtherReturnType>
   class ReturnTypeEnforcer
   {
@@ -303,21 +320,21 @@ public:
     // No ReturnTypeIsSafe makes this illegal!
   };
 
   // Make sure this return type is safe.
   typedef typename ReturnTypeEnforcer<ReturnType>::ReturnTypeIsSafe check;
 
 protected:
   virtual ~nsRunnableMethod() {
-    NS_IF_RELEASE(mObj);
+    Revoke();
   }
 
 private:
-  ClassType* mObj;
+  RunnableMethodReceiver<ClassType, Owning> mReceiver;
   Method mMethod;
 };
 
 // Use this helper macro like so:
 //
 //   nsCOMPtr<nsIRunnable> event =
 //       NS_NEW_RUNNABLE_METHOD(MyClass, myObject, HandleEvent);
 //   NS_DispatchToCurrentThread(event);
@@ -334,70 +351,16 @@ private:
 
 template<class ClassType, typename ReturnType>
 nsRunnableMethod<ClassType, ReturnType>*
 ns_new_runnable_method(ClassType* obj, ReturnType (ClassType::*method)())
 {
   return new nsRunnableMethod<ClassType, ReturnType>(obj, method);
 }
 
-// An event that can be used to call a method on a class, but holds only
-// a raw pointer to the object on which the method will be called.  This
-// event supports Revoke for use with nsRevocableEventPtr and should
-// almost always be used with it.
-template <class ClassType, typename ReturnType = void>
-class nsNonOwningRunnableMethod : public nsRunnable
-{
-public:
-  typedef ReturnType (ClassType::*Method)();
-
-  nsNonOwningRunnableMethod(ClassType *obj, Method method)
-    : mObj(obj), mMethod(method) {
-  }
-
-  NS_IMETHOD Run() {
-    if (!mObj)
-      return NS_OK;
-    (mObj->*mMethod)();
-    return NS_OK;
-  }
-
-  void Revoke() {
-    mObj = nsnull;
-  }
-
-  // These ReturnTypeEnforcer classes set up a blacklist for return types that
-  // we know are not safe. The default ReturnTypeEnforcer compiles just fine but
-  // already_AddRefed will not.
-  template <typename OtherReturnType>
-  class ReturnTypeEnforcer
-  {
-  public:
-    typedef int ReturnTypeIsSafe;
-  };
-
-  template <class T>
-  class ReturnTypeEnforcer<already_AddRefed<T> >
-  {
-    // No ReturnTypeIsSafe makes this illegal!
-  };
-
-  // Make sure this return type is safe.
-  typedef typename ReturnTypeEnforcer<ReturnType>::ReturnTypeIsSafe check;
-
-protected:
-  virtual ~nsNonOwningRunnableMethod() {
-  }
-
-private:
-  ClassType* mObj;
-  Method mMethod;
-};
-
-
 #endif  // XPCOM_GLUE_AVOID_NSPR
 
 // This class is designed to be used when you have an event class E that has a
 // pointer back to resource class R.  If R goes away while E is still pending,
 // then it is important to "revoke" E so that it does not try use R after R has
 // been destroyed.  nsRevocableEventPtr makes it easy for R to manage such
 // situations:
 //