Bug 1027789 - CacheEntry::RememberCallback should unlock before call to InvokeAvailableCallback, r=michal
authorHonza Bambas <honzab.moz@firemni.cz>
Wed, 02 Jul 2014 18:16:21 +0200
changeset 191920 f6284fc84d90da2f059f0f4669b1b8033c5f417e
parent 191919 513955ec7eb05b79739279c792404dd8b8be2560
child 191921 aa9ae5727c97b22b499891df0f7bc241319dbbe6
push id45692
push userhonzab.moz@firemni.cz
push dateWed, 02 Jul 2014 16:16:43 +0000
treeherdermozilla-inbound@6c5c6cbad330 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmichal
bugs1027789
milestone33.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 1027789 - CacheEntry::RememberCallback should unlock before call to InvokeAvailableCallback, r=michal
netwerk/cache2/CacheEntry.cpp
netwerk/cache2/CacheEntry.h
--- a/netwerk/cache2/CacheEntry.cpp
+++ b/netwerk/cache2/CacheEntry.cpp
@@ -269,27 +269,45 @@ void CacheEntry::AsyncOpen(nsICacheEntry
   bool priority = aFlags & nsICacheStorage::OPEN_PRIORITY;
   bool multithread = aFlags & nsICacheStorage::CHECK_MULTITHREADED;
 
   MOZ_ASSERT(!readonly || !truncate, "Bad flags combination");
   MOZ_ASSERT(!(truncate && mState > LOADING), "Must not call truncate on already loaded entry");
 
   Callback callback(this, aCallback, readonly, multithread);
 
+  if (!Open(callback, truncate, priority, bypassIfBusy)) {
+    // We get here when the callback wants to bypass cache when it's busy.
+    LOG(("  writing or revalidating, callback wants to bypass cache"));
+    callback.mNotWanted = true;
+    InvokeAvailableCallback(callback);
+  }
+}
+
+bool CacheEntry::Open(Callback & aCallback, bool aTruncate,
+                      bool aPriority, bool aBypassIfBusy)
+{
   mozilla::MutexAutoLock lock(mLock);
 
-  RememberCallback(callback, bypassIfBusy);
+  // Check state under the lock
+  if (aBypassIfBusy && (mState == WRITING || mState == REVALIDATING)) {
+    return false;
+  }
+
+  RememberCallback(aCallback);
 
   // Load() opens the lock
-  if (Load(truncate, priority)) {
+  if (Load(aTruncate, aPriority)) {
     // Loading is in progress...
-    return;
+    return true;
   }
 
   InvokeCallbacks();
+
+  return true;
 }
 
 bool CacheEntry::Load(bool aTruncate, bool aPriority)
 {
   LOG(("CacheEntry::Load [this=%p, trunc=%d]", this, aTruncate));
 
   mLock.AssertCurrentThreadOwns();
 
@@ -503,30 +521,23 @@ void CacheEntry::TransferCallbacks(Cache
     // Carry the entry reference (unfortunatelly, needs to be done manually...)
     for (uint32_t i = 0; i < callbacksLength; ++i)
       mCallbacks[i].ExchangeEntry(this);
 
     BackgroundOp(Ops::CALLBACKS, true);
   }
 }
 
-void CacheEntry::RememberCallback(Callback & aCallback, bool aBypassIfBusy)
+void CacheEntry::RememberCallback(Callback & aCallback)
 {
   mLock.AssertCurrentThreadOwns();
 
   LOG(("CacheEntry::RememberCallback [this=%p, cb=%p, state=%s]",
     this, aCallback.mCallback.get(), StateString(mState)));
 
-  if (aBypassIfBusy && (mState == WRITING || mState == REVALIDATING)) {
-    LOG(("  writing or revalidating, callback wants to bypass cache"));
-    aCallback.mNotWanted = true;
-    InvokeAvailableCallback(aCallback);
-    return;
-  }
-
   mCallbacks.AppendElement(aCallback);
 }
 
 void CacheEntry::InvokeCallbacksLock()
 {
   mozilla::MutexAutoLock lock(mLock);
   InvokeCallbacks();
 }
--- a/netwerk/cache2/CacheEntry.h
+++ b/netwerk/cache2/CacheEntry.h
@@ -199,21 +199,24 @@ private:
         callback->OnCacheEntryDoomed(mRv);
       return NS_OK;
     }
 
     nsRefPtr<CacheEntry> mEntry;
     nsresult mRv;
   };
 
+  // Starts the load or just invokes the callback, bypasses (when required)
+  // if busy.  Returns true on job done, false on bypass.
+  bool Open(Callback & aCallback, bool aTruncate, bool aPriority, bool aBypassIfBusy);
   // Loads from disk asynchronously
   bool Load(bool aTruncate, bool aPriority);
   void OnLoaded();
 
-  void RememberCallback(Callback & aCallback, bool aBypassIfBusy);
+  void RememberCallback(Callback & aCallback);
   void InvokeCallbacksLock();
   void InvokeCallbacks();
   bool InvokeCallbacks(bool aReadOnly);
   bool InvokeCallback(Callback & aCallback);
   void InvokeAvailableCallback(Callback const & aCallback);
 
   nsresult OpenOutputStreamInternal(int64_t offset, nsIOutputStream * *_retval);