Bug 580313 - Use deque instead of manual queue im nsPrefetchService. r=smaug
authorDragana Damjanovic dd.mozilla@gmail.com
Mon, 22 Feb 2016 10:29:00 +0100
changeset 285805 ef1fb285a58d19d1aa8874d0fd9ce3e4bb554e40
parent 285804 346a7684fde5373adf47175a61d312d536e833c5
child 285806 c4d101e34585cb7950189fc1f4aa0bf99dec8041
push id30036
push usercbook@mozilla.com
push dateMon, 29 Feb 2016 10:35:59 +0000
treeherdermozilla-central@9da51cb4974e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs580313
milestone47.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 580313 - Use deque instead of manual queue im nsPrefetchService. r=smaug
uriloader/prefetch/nsPrefetchService.cpp
uriloader/prefetch/nsPrefetchService.h
--- a/uriloader/prefetch/nsPrefetchService.cpp
+++ b/uriloader/prefetch/nsPrefetchService.cpp
@@ -71,18 +71,17 @@ PRTimeToSeconds(PRTime t_usec)
 //-----------------------------------------------------------------------------
 // nsPrefetchNode <public>
 //-----------------------------------------------------------------------------
 
 nsPrefetchNode::nsPrefetchNode(nsPrefetchService *aService,
                                nsIURI *aURI,
                                nsIURI *aReferrerURI,
                                nsIDOMNode *aSource)
-    : mNext(nullptr)
-    , mURI(aURI)
+    : mURI(aURI)
     , mReferrerURI(aReferrerURI)
     , mService(aService)
     , mChannel(nullptr)
     , mBytesRead(0)
 {
     mSource = do_GetWeakReference(aSource);
 }
 
@@ -307,19 +306,17 @@ nsPrefetchNode::OnRedirectResult(bool pr
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsPrefetchService <public>
 //-----------------------------------------------------------------------------
 
 nsPrefetchService::nsPrefetchService()
-    : mQueueHead(nullptr)
-    , mQueueTail(nullptr)
-    , mMaxParallelism(6)
+    : mMaxParallelism(6)
     , mStopCount(0)
     , mHaveProcessed(false)
     , mDisabled(true)
 {
 }
 
 nsPrefetchService::~nsPrefetchService()
 {
@@ -375,20 +372,21 @@ nsPrefetchService::ProcessNextURI(nsPref
 
     if (mCurrentNodes.Length() >= static_cast<uint32_t>(mMaxParallelism)) {
         // We already have enough prefetches going on, so hold off
         // for now.
         return;
     }
 
     do {
-        RefPtr<nsPrefetchNode> node;
-        rv = DequeueNode(getter_AddRefs(node));
-
-        if (NS_FAILED(rv)) break;
+        if (mQueue.empty()) {
+          break;
+        }
+        RefPtr<nsPrefetchNode> node = mQueue.front().forget();
+        mQueue.pop_front();
 
         if (LOG_ENABLED()) {
             nsAutoCString spec;
             node->mURI->GetSpec(spec);
             LOG(("ProcessNextURI [%s]\n", spec.get()));
         }
 
         //
@@ -446,72 +444,34 @@ nsPrefetchService::RemoveProgressListene
     // Register as an observer for the document loader  
     nsCOMPtr<nsIWebProgress> progress =
         do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
     if (progress)
         progress->RemoveProgressListener(this);
 }
 
 nsresult
-nsPrefetchService::EnqueueNode(nsPrefetchNode *aNode)
-{
-    NS_ADDREF(aNode);
-
-    if (!mQueueTail) {
-        mQueueHead = aNode;
-        mQueueTail = aNode;
-    }
-    else {
-        mQueueTail->mNext = aNode;
-        mQueueTail = aNode;
-    }
-
-    return NS_OK;
-}
-
-nsresult
 nsPrefetchService::EnqueueURI(nsIURI *aURI,
                               nsIURI *aReferrerURI,
                               nsIDOMNode *aSource,
                               nsPrefetchNode **aNode)
 {
-    nsPrefetchNode *node = new nsPrefetchNode(this, aURI, aReferrerURI,
-                                              aSource);
-    if (!node)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    NS_ADDREF(*aNode = node);
-
-    return EnqueueNode(node);
-}
-
-nsresult
-nsPrefetchService::DequeueNode(nsPrefetchNode **node)
-{
-    if (!mQueueHead)
-        return NS_ERROR_NOT_AVAILABLE;
-
-    // give the ref to the caller
-    *node = mQueueHead;
-    mQueueHead = mQueueHead->mNext;
-    (*node)->mNext = nullptr;
-
-    if (!mQueueHead)
-        mQueueTail = nullptr;
-
+    RefPtr<nsPrefetchNode> node = new nsPrefetchNode(this, aURI, aReferrerURI,
+                                                     aSource);
+    mQueue.push_back(node);
+    node.forget(aNode);
     return NS_OK;
 }
 
 void
 nsPrefetchService::EmptyQueue()
 {
-    do {
-        RefPtr<nsPrefetchNode> node;
-        DequeueNode(getter_AddRefs(node));
-    } while (mQueueHead);
+    while (!mQueue.empty()) {
+        mQueue.pop_back();
+    }
 }
 
 void
 nsPrefetchService::StartPrefetching()
 {
     //
     // at initialization time we might miss the first DOCUMENT START
     // notification, so we have to be careful to avoid letting our
@@ -522,17 +482,17 @@ nsPrefetchService::StartPrefetching()
 
     LOG(("StartPrefetching [stopcount=%d]\n", mStopCount));
 
     // only start prefetching after we've received enough DOCUMENT
     // STOP notifications.  we do this inorder to defer prefetching
     // until after all sub-frames have finished loading.
     if (!mStopCount) {
         mHaveProcessed = true;
-        while (mQueueHead && mCurrentNodes.Length() < static_cast<uint32_t>(mMaxParallelism)) {
+        while (!mQueue.empty() && mCurrentNodes.Length() < static_cast<uint32_t>(mMaxParallelism)) {
             ProcessNextURI(nullptr);
         }
     }
 }
 
 void
 nsPrefetchService::StopPrefetching()
 {
@@ -643,20 +603,20 @@ nsPrefetchService::Prefetch(nsIURI *aURI
             LOG(("rejected: URL is already being prefetched\n"));
             return NS_ERROR_ABORT;
         }
     }
 
     //
     // cancel if already on the prefetch queue
     //
-    nsPrefetchNode *node = mQueueHead;
-    for (; node; node = node->mNext) {
+    for (std::deque<RefPtr<nsPrefetchNode>>::iterator node = mQueue.begin();
+         node != mQueue.end(); node++) {
         bool equals;
-        if (NS_SUCCEEDED(node->mURI->Equals(aURI, &equals)) && equals) {
+        if (NS_SUCCEEDED(node->get()->mURI->Equals(aURI, &equals)) && equals) {
             LOG(("rejected: URL is already on prefetch queue\n"));
             return NS_ERROR_ABORT;
         }
     }
 
     RefPtr<nsPrefetchNode> enqueuedNode;
     rv = EnqueueURI(aURI, aReferrerURI, aSource,
                     getter_AddRefs(enqueuedNode));
@@ -679,17 +639,17 @@ nsPrefetchService::PrefetchURI(nsIURI *a
                                bool aExplicit)
 {
     return Prefetch(aURI, aReferrerURI, aSource, aExplicit);
 }
 
 NS_IMETHODIMP
 nsPrefetchService::HasMoreElements(bool *aHasMore)
 {
-    *aHasMore = (mCurrentNodes.Length() || mQueueHead);
+    *aHasMore = (mCurrentNodes.Length() || !mQueue.empty());
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsPrefetchService::nsIWebProgressListener
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
@@ -788,17 +748,17 @@ nsPrefetchService::Observe(nsISupports  
             mMaxParallelism = Preferences::GetInt(PARALLELISM_PREF, mMaxParallelism);
             if (mMaxParallelism < 1) {
                 mMaxParallelism = 1;
             }
             // If our parallelism has increased, go ahead and kick off enough
             // prefetches to fill up our allowance. If we're now over our
             // allowance, we'll just silently let some of them finish to get
             // back below our limit.
-            while (mQueueHead && mCurrentNodes.Length() < static_cast<uint32_t>(mMaxParallelism)) {
+            while (!mQueue.empty() && mCurrentNodes.Length() < static_cast<uint32_t>(mMaxParallelism)) {
                 ProcessNextURI(nullptr);
             }
         }
     }
 
     return NS_OK;
 }
 
--- a/uriloader/prefetch/nsPrefetchService.h
+++ b/uriloader/prefetch/nsPrefetchService.h
@@ -13,16 +13,17 @@
 #include "nsIWebProgressListener.h"
 #include "nsIStreamListener.h"
 #include "nsIChannel.h"
 #include "nsIURI.h"
 #include "nsWeakReference.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "mozilla/Attributes.h"
+#include <deque>
 
 class nsPrefetchService;
 class nsPrefetchNode;
 
 //-----------------------------------------------------------------------------
 // nsPrefetchService
 //-----------------------------------------------------------------------------
 
@@ -52,31 +53,28 @@ private:
                       nsIURI *aReferrerURI,
                       nsIDOMNode *aSource,
                       bool aExplicit);
 
     void     AddProgressListener();
     void     RemoveProgressListener();
     nsresult EnqueueURI(nsIURI *aURI, nsIURI *aReferrerURI,
                         nsIDOMNode *aSource, nsPrefetchNode **node);
-    nsresult EnqueueNode(nsPrefetchNode *node);
-    nsresult DequeueNode(nsPrefetchNode **node);
     void     EmptyQueue();
 
     void     StartPrefetching();
     void     StopPrefetching();
 
-    nsPrefetchNode                   *mQueueHead;
-    nsPrefetchNode                   *mQueueTail;
-    nsTArray<RefPtr<nsPrefetchNode>> mCurrentNodes;
-    int32_t                           mMaxParallelism;
-    int32_t                           mStopCount;
+    std::deque<RefPtr<nsPrefetchNode>> mQueue;
+    nsTArray<RefPtr<nsPrefetchNode>>   mCurrentNodes;
+    int32_t                            mMaxParallelism;
+    int32_t                            mStopCount;
     // true if pending document loads have ever reached zero.
-    int32_t                           mHaveProcessed;
-    bool                              mDisabled;
+    int32_t                            mHaveProcessed;
+    bool                               mDisabled;
 };
 
 //-----------------------------------------------------------------------------
 // nsPrefetchNode
 //-----------------------------------------------------------------------------
 
 class nsPrefetchNode final : public nsIStreamListener
                            , public nsIInterfaceRequestor
@@ -94,23 +92,22 @@ public:
     nsPrefetchNode(nsPrefetchService *aPrefetchService,
                    nsIURI *aURI,
                    nsIURI *aReferrerURI,
                    nsIDOMNode *aSource);
 
     nsresult OpenChannel();
     nsresult CancelChannel(nsresult error);
 
-    nsPrefetchNode             *mNext;
     nsCOMPtr<nsIURI>            mURI;
     nsCOMPtr<nsIURI>            mReferrerURI;
     nsCOMPtr<nsIWeakReference>  mSource;
 
 private:
     ~nsPrefetchNode() {}
 
-    RefPtr<nsPrefetchService> mService;
+    RefPtr<nsPrefetchService>   mService;
     nsCOMPtr<nsIChannel>        mChannel;
     nsCOMPtr<nsIChannel>        mRedirectChannel;
     int64_t                     mBytesRead;
 };
 
 #endif // !nsPrefetchService_h__