Bug 803439 - Add removeFrom() that takes a list and asserts the element is initially present in it. r=jlebar
authorJeff Walden <jwalden@mit.edu>
Tue, 23 Oct 2012 17:43:23 -0700
changeset 112351 5bd42ae5efd23bb82e6891055bbab7f74b5708ea
parent 112350 dfe6972056d658a674394f4d28b81dc020447b1f
child 112352 5c5e4097dd20b5fc8b8dbcd6a0bdae83ee9142cd
push idunknown
push userunknown
push dateunknown
reviewersjlebar
bugs803439
milestone19.0a1
Bug 803439 - Add removeFrom() that takes a list and asserts the element is initially present in it. r=jlebar
content/base/src/nsCrossSiteListenerProxy.cpp
content/canvas/src/WebGLContext.h
image/src/RasterImage.cpp
mfbt/LinkedList.h
parser/html/nsHtml5TreeOpExecutor.cpp
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -184,17 +184,17 @@ nsPreflightCache::GetEntry(nsIURI* aURI,
   }
 
   CacheEntry* entry;
 
   if (mTable.Get(key, &entry)) {
     // Entry already existed so just return it. Also update the LRU list.
 
     // Move to the head of the list.
-    entry->remove();
+    entry->removeFrom(mList);
     mList.insertFront(entry);
 
     return entry;
   }
 
   if (!aCreate) {
     return nullptr;
   }
@@ -238,23 +238,23 @@ nsPreflightCache::GetEntry(nsIURI* aURI,
 
 void
 nsPreflightCache::RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal)
 {
   CacheEntry* entry;
   nsCString key;
   if (GetCacheKey(aURI, aPrincipal, true, key) &&
       mTable.Get(key, &entry)) {
-    entry->remove();
+    entry->removeFrom(mList);
     mTable.Remove(key);
   }
 
   if (GetCacheKey(aURI, aPrincipal, false, key) &&
       mTable.Get(key, &entry)) {
-    entry->remove();
+    entry->removeFrom(mList);
     mTable.Remove(key);
   }
 }
 
 void
 nsPreflightCache::Clear()
 {
   mList.clear();
@@ -268,17 +268,17 @@ nsPreflightCache::RemoveExpiredEntries(c
 {
   PRTime* now = static_cast<PRTime*>(aUserData);
   
   aValue->PurgeExpired(*now);
   
   if (aValue->mHeaders.IsEmpty() &&
       aValue->mMethods.IsEmpty()) {
     // Expired, remove from the list as well as the hash table.
-    aValue->remove();
+    aValue->removeFrom(sPreflightCache->mList);
     return PL_DHASH_REMOVE;
   }
   
   return PL_DHASH_NEXT;
 }
 
 /* static */ bool
 nsPreflightCache::GetCacheKey(nsIURI* aURI,
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -1557,17 +1557,17 @@ public:
         DeleteOnce();
     }
 
     void Delete() {
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteBuffers(1, &mGLName);
         mByteLength = 0;
         mCache = nullptr;
-        LinkedListElement<WebGLBuffer>::remove(); // remove from mContext->mBuffers
+        LinkedListElement<WebGLBuffer>::removeFrom(mContext->mBuffers);
     }
 
     size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
         size_t sizeOfCache = mCache ? mCache->SizeOfIncludingThis(aMallocSizeOf) : 0;
         return aMallocSizeOf(this) + sizeOfCache;
     }
 
     bool HasEverBeenBound() { return mHasEverBeenBound; }
@@ -1650,17 +1650,17 @@ public:
     ~WebGLTexture() {
         DeleteOnce();
     }
 
     void Delete() {
         mImageInfos.Clear();
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteTextures(1, &mGLName);
-        LinkedListElement<WebGLTexture>::remove(); // remove from mContext->mTextures
+        LinkedListElement<WebGLTexture>::removeFrom(mContext->mTextures);
     }
 
     bool HasEverBeenBound() { return mHasEverBeenBound; }
     void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
     WebGLuint GLName() { return mGLName; }
     GLenum Target() const { return mTarget; }
 
     WebGLContext *GetParentObject() const {
@@ -2168,17 +2168,17 @@ public:
                mTranslationLog.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
     }
 
     void Delete() {
         mSource.Truncate();
         mTranslationLog.Truncate();
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteShader(mGLName);
-        LinkedListElement<WebGLShader>::remove(); // remove from mContext->mShaders
+        LinkedListElement<WebGLShader>::removeFrom(mContext->mShaders);
     }
 
     WebGLuint GLName() { return mGLName; }
     WebGLenum ShaderType() { return mType; }
 
     void SetSource(const nsAString& src) {
         // XXX do some quick gzip here maybe -- getting this will be very rare
         mSource.Assign(src);
@@ -2290,17 +2290,17 @@ public:
     ~WebGLProgram() {
         DeleteOnce();
     }
 
     void Delete() {
         DetachShaders();
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteProgram(mGLName);
-        LinkedListElement<WebGLProgram>::remove(); // remove from mContext->mPrograms
+        LinkedListElement<WebGLProgram>::removeFrom(mContext->mPrograms);
     }
 
     void DetachShaders() {
         mAttachedShaders.Clear();
     }
 
     WebGLuint GLName() { return mGLName; }
     const nsTArray<WebGLRefPtr<WebGLShader> >& AttachedShaders() const { return mAttachedShaders; }
@@ -2573,17 +2573,17 @@ public:
 
     ~WebGLRenderbuffer() {
         DeleteOnce();
     }
 
     void Delete() {
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteRenderbuffers(1, &mGLName);
-        LinkedListElement<WebGLRenderbuffer>::remove(); // remove from mContext->mRenderbuffers
+        LinkedListElement<WebGLRenderbuffer>::removeFrom(mContext->mRenderbuffers);
     }
 
     bool HasEverBeenBound() { return mHasEverBeenBound; }
     void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
     WebGLuint GLName() const { return mGLName; }
 
     bool Initialized() const { return mInitialized; }
     void SetInitialized(bool aInitialized) { mInitialized = aInitialized; }
@@ -2818,17 +2818,17 @@ public:
 
     void Delete() {
         mColorAttachment.Reset();
         mDepthAttachment.Reset();
         mStencilAttachment.Reset();
         mDepthStencilAttachment.Reset();
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteFramebuffers(1, &mGLName);
-        LinkedListElement<WebGLFramebuffer>::remove(); // remove from mContext->mFramebuffers
+        LinkedListElement<WebGLFramebuffer>::removeFrom(mContext->mFramebuffers);
     }
 
     bool HasEverBeenBound() { return mHasEverBeenBound; }
     void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
     WebGLuint GLName() { return mGLName; }
 
     void FramebufferRenderbuffer(WebGLenum target,
                                  WebGLenum attachment,
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -3271,17 +3271,17 @@ RasterImage::DecodeWorker::MarkAsASAP(Ra
   }
 
   request->mIsASAP = true;
 
   if (request->isInList()) {
     // If the decode request is in a list, it must be in the normal decode
     // requests list -- if it had been in the ASAP list, then mIsASAP would
     // have been true above.  Move the request to the ASAP list.
-    request->remove();
+    request->removeFrom(mNormalDecodeRequests);
     mASAPDecodeRequests.insertBack(request);
 
     // Since request is in a list, one of the decode worker's lists is
     // non-empty, so the worker should be pending in the event loop.
     //
     // (Note that this invariant only holds while we are not in Run(), because
     // DecodeSomeOfImage adds requests to the decode worker using
     // AddDecodeRequest, not RequestDecode, and AddDecodeRequest does not call
--- a/mfbt/LinkedList.h
+++ b/mfbt/LinkedList.h
@@ -35,16 +35,18 @@
  *       void addObserver(Observer* observer) {
  *         // Will assert if |observer| is part of another list.
  *         list.insertBack(observer);
  *       }
  *
  *       void removeObserver(Observer* observer) {
  *         // Will assert if |observer| is not part of some list.
  *         observer.remove();
+ *         // Or, will assert if |observer| is not part of |list| specifically.
+ *         // observer.removeFrom(list);
  *       }
  *
  *       void notifyObservers(char* topic) {
  *         for (Observer* o = list.getFirst(); o != NULL; o = o->getNext())
  *           o->Observe(topic);
  *       }
  *   };
  *
@@ -169,16 +171,25 @@ class LinkedListElement
 
       prev->next = next;
       next->prev = prev;
       next = this;
       prev = this;
     }
 
     /*
+     * Identical to remove(), but also asserts in debug builds that this element
+     * is in list.
+     */
+    void removeFrom(const LinkedList<T>& list) {
+      list.assertContains(asT());
+      remove();
+    }
+
+    /*
      * Return true if |this| part is of a linked list, and false otherwise.
      */
     bool isInList() const {
       MOZ_ASSERT((next == this) == (prev == this));
       return next != this;
     }
 
   private:
@@ -388,16 +399,31 @@ class LinkedList
 
           prev = cur;
           cur = cur->next;
       } while (cur != sentinel);
 #endif /* ifdef DEBUG */
     }
 
   private:
+    friend class LinkedListElement<T>;
+
+    void assertContains(const T* t) const {
+#ifdef DEBUG
+      for (const T* elem = getFirst();
+           elem;
+           elem = elem->getNext())
+      {
+        if (elem == t)
+          return;
+      }
+      MOZ_NOT_REACHED("element wasn't found in this list!");
+#endif
+    }
+
     LinkedList& operator=(const LinkedList<T>& other) MOZ_DELETE;
     LinkedList(const LinkedList<T>& other) MOZ_DELETE;
 };
 
 } /* namespace mozilla */
 
 #endif /* ifdef __cplusplus */
 #endif /* ifdef mozilla_LinkedList_h_ */
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -78,17 +78,17 @@ nsHtml5TreeOpExecutor::nsHtml5TreeOpExec
   mPreloadedURLs.Init(23); // Mean # of preloadable resources per page on dmoz
   // zeroing operator new for everything else
 }
 
 nsHtml5TreeOpExecutor::~nsHtml5TreeOpExecutor()
 {
   if (gBackgroundFlushList && isInList()) {
     mOpQueue.Clear();
-    remove();
+    removeFrom(*gBackgroundFlushList);
     if (gBackgroundFlushList->isEmpty()) {
       delete gBackgroundFlushList;
       gBackgroundFlushList = nullptr;
       if (gFlushTimer) {
         gFlushTimer->Cancel();
         NS_RELEASE(gFlushTimer);
       }
     }