From fc96d0299bd7be95ce5e9fcac4f698d63e142caf Mon Sep 17 00:00:00 2001 From: "dwitte%stanford.edu" Date: Wed, 19 Dec 2007 06:03:06 +0000 Subject: [PATCH] reland nsTObserverArray changes only. --- content/base/public/nsIDocument.h | 2 +- content/base/public/nsINode.h | 2 +- content/base/public/nsPresShellIterator.h | 6 +- content/base/src/nsDocument.cpp | 12 +- content/base/src/nsDocument.h | 2 +- content/base/src/nsGenericElement.cpp | 4 +- content/events/src/nsEventListenerManager.cpp | 50 +-- content/events/src/nsEventListenerManager.h | 15 +- layout/style/nsCSSLoader.cpp | 9 +- layout/style/nsCSSLoader.h | 2 +- modules/libpr0n/src/imgRequest.cpp | 84 ++-- modules/libpr0n/src/imgRequest.h | 2 +- xpcom/build/dlldeps.cpp | 4 +- xpcom/glue/nsTArray.h | 28 ++ xpcom/glue/nsTObserverArray.cpp | 13 +- xpcom/glue/nsTObserverArray.h | 394 +++++++++++------- 16 files changed, 369 insertions(+), 260 deletions(-) diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 7ba22f2437c..981c1049ece 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -996,7 +996,7 @@ protected: // won't be collected PRUint32 mMarkedCCGeneration; - nsTObserverArray mPresShells; + nsTObserverArray mPresShells; nsCOMArray mSubtreeModifiedTargets; PRUint32 mSubtreeModifiedDepth; diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index 83a042e9ef5..6ba22d70e7a 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -564,7 +564,7 @@ public: /** * A list of mutation observers */ - nsTObserverArray mMutationObservers; + nsTObserverArray mMutationObservers; /** * An object implementing nsIDOMNodeList for this content (childNodes) diff --git a/content/base/public/nsPresShellIterator.h b/content/base/public/nsPresShellIterator.h index 00822b9ca4e..03615f14b30 100644 --- a/content/base/public/nsPresShellIterator.h +++ b/content/base/public/nsPresShellIterator.h @@ -42,17 +42,17 @@ #include "nsIDocument.h" class nsPresShellIterator : - private nsTObserverArray::ForwardIterator + private nsTObserverArray::ForwardIterator { public: nsPresShellIterator(nsIDocument* aDoc) - : nsTObserverArray::ForwardIterator(aDoc->mPresShells), + : nsTObserverArray::ForwardIterator(aDoc->mPresShells), mDoc(aDoc) {} already_AddRefed GetNextShell() { nsIPresShell* shell = nsnull; - if (!mDoc->ShellsAreHidden()) { + if (!mDoc->ShellsAreHidden() && HasMore()) { shell = GetNext(); NS_IF_ADDREF(shell); } diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 4005e04b936..dad7fef72d7 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1126,7 +1126,7 @@ nsDocument::Init() // subclasses currently do, other don't). This is because the code in // nsNodeUtils always notifies the first observer first, expecting the // first observer to be the document. - NS_ENSURE_TRUE(slots->mMutationObservers.PrependObserver(this), + NS_ENSURE_TRUE(slots->mMutationObservers.PrependElementUnlessExists(this), NS_ERROR_OUT_OF_MEMORY); @@ -2045,7 +2045,7 @@ nsDocument::doCreateShell(nsPresContext* aContext, NS_ENSURE_SUCCESS(rv, rv); // Note: we don't hold a ref to the shell (it holds a ref to us) - NS_ENSURE_TRUE(mPresShells.AppendObserverUnlessExists(shell), + NS_ENSURE_TRUE(mPresShells.AppendElementUnlessExists(shell), NS_ERROR_OUT_OF_MEMORY); shell.swap(*aInstancePtrResult); @@ -2055,14 +2055,14 @@ nsDocument::doCreateShell(nsPresContext* aContext, PRBool nsDocument::DeleteShell(nsIPresShell* aShell) { - return mPresShells.RemoveObserver(aShell); + return mPresShells.RemoveElement(aShell); } nsIPresShell * nsDocument::GetPrimaryShell() const { - return mShellsAreHidden ? nsnull : mPresShells.SafeObserverAt(0); + return mShellsAreHidden ? nsnull : mPresShells.SafeElementAt(0, nsnull); } PR_STATIC_CALLBACK(void) @@ -2654,7 +2654,7 @@ void nsDocument::AddObserver(nsIDocumentObserver* aObserver) { // The array makes sure the observer isn't already in the list - mObservers.AppendObserverUnlessExists(aObserver); + mObservers.AppendElementUnlessExists(aObserver); AddMutationObserver(aObserver); } @@ -2667,7 +2667,7 @@ nsDocument::RemoveObserver(nsIDocumentObserver* aObserver) // don't hold a live reference to the observers. if (!mInDestructor) { RemoveMutationObserver(aObserver); - return mObservers.RemoveObserver(aObserver); + return mObservers.RemoveElement(aObserver); } return mObservers.Contains(aObserver); diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 2fb15774275..15997c3c12f 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -741,7 +741,7 @@ protected: nsCOMArray mCatalogSheets; // Array of observers - nsTObserverArray mObservers; + nsTObserverArray mObservers; // The document's script global object, the object from which the // document can get its script context and scope. This is the diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 27423115e79..aa25c2a44ee 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -320,7 +320,7 @@ nsINode::AddMutationObserver(nsIMutationObserver* aMutationObserver) { nsSlots* slots = GetSlots(); if (slots) { - slots->mMutationObservers.AppendObserverUnlessExists(aMutationObserver); + slots->mMutationObservers.AppendElementUnlessExists(aMutationObserver); } } @@ -329,7 +329,7 @@ nsINode::RemoveMutationObserver(nsIMutationObserver* aMutationObserver) { nsSlots* slots = GetExistingSlots(); if (slots) { - slots->mMutationObservers.RemoveObserver(aMutationObserver); + slots->mMutationObservers.RemoveElement(aMutationObserver); } } diff --git a/content/events/src/nsEventListenerManager.cpp b/content/events/src/nsEventListenerManager.cpp index cbe65aa0a29..1e0d0e23a8f 100644 --- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -369,9 +369,9 @@ nsEventListenerManager::~nsEventListenerManager() nsresult nsEventListenerManager::RemoveAllListeners() { - PRInt32 count = mListeners.Count(); + PRInt32 count = mListeners.Length(); for (PRInt32 i = 0; i < count; i++) { - delete mListeners.FastObserverAt(i); + delete mListeners.ElementAt(i); } mListeners.Clear(); return NS_OK; @@ -397,9 +397,9 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsEventListenerManager, nsIEventListen NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsEventListenerManager, nsIEventListenerManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEventListenerManager) - PRInt32 i, count = tmp->mListeners.Count(); + PRInt32 i, count = tmp->mListeners.Length(); for (i = 0; i < count; i++) { - cb.NoteXPCOMChild(tmp->mListeners.FastObserverAt(i)->mListener.get()); + cb.NoteXPCOMChild(tmp->mListeners.ElementAt(i)->mListener.get()); } NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END @@ -477,9 +477,9 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener, } nsListenerStruct* ls = nsnull; - PRInt32 count = mListeners.Count(); + PRInt32 count = mListeners.Length(); for (PRInt32 i = 0; i < count; i++) { - ls = mListeners.FastObserverAt(i); + ls = mListeners.ElementAt(i); if (ls->mListener == aListener && ls->mFlags == aFlags && ls->mGroupFlags == group && (EVENT_TYPE_EQUALS(ls, aType, aTypeAtom) || @@ -501,7 +501,7 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener, ls->mGroupFlags = group; ls->mHandlerIsString = PR_FALSE; ls->mTypeData = aTypeData; - mListeners.AppendObserver(ls); + mListeners.AppendElement(ls); // For mutation listeners, we need to update the global bit on the DOM window. // Otherwise we won't actually fire the mutation event. @@ -563,16 +563,16 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, nsListenerStruct* ls = nsnull; aFlags &= ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED; - PRInt32 count = mListeners.Count(); + PRInt32 count = mListeners.Length(); for (PRInt32 i = 0; i < count; ++i) { - ls = mListeners.FastObserverAt(i); + ls = mListeners.ElementAt(i); if (ls->mListener == aListener && ls->mGroupFlags == group && ((ls->mFlags & ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED) == aFlags) && (EVENT_TYPE_EQUALS(ls, aType, aUserType) || (!(ls->mEventType) && EVENT_TYPE_DATA_EQUALS(ls->mTypeData, aTypeData)))) { - mListeners.RemoveObserverAt(i); + mListeners.RemoveElementAt(i); delete ls; mNoListenerForEvent = NS_EVENT_TYPE_NULL; mNoListenerForEventAtom = nsnull; @@ -645,9 +645,9 @@ nsEventListenerManager::FindJSEventListener(PRUint32 aEventType, // Run through the listeners for this type and see if a script // listener is registered nsListenerStruct *ls; - PRInt32 count = mListeners.Count(); + PRInt32 count = mListeners.Length(); for (PRInt32 i = 0; i < count; ++i) { - ls = mListeners.FastObserverAt(i); + ls = mListeners.ElementAt(i); if (EVENT_TYPE_EQUALS(ls, aEventType, aTypeAtom) && ls->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) { return ls; @@ -843,7 +843,7 @@ nsEventListenerManager::RemoveScriptEventListener(nsIAtom* aName) nsListenerStruct* ls = FindJSEventListener(eventType, aName); if (ls) { - mListeners.RemoveObserver(ls); + mListeners.RemoveElement(ls); delete ls; mNoListenerForEvent = NS_EVENT_TYPE_NULL; mNoListenerForEventAtom = nsnull; @@ -1106,7 +1106,7 @@ nsEventListenerManager::HandleEvent(nsPresContext* aPresContext, PRUint32 aFlags, nsEventStatus* aEventStatus) { - if (mListeners.Count() == 0 || aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) { + if (mListeners.IsEmpty() || aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) { return NS_OK; } @@ -1157,11 +1157,11 @@ nsEventListenerManager::HandleEvent(nsPresContext* aPresContext, found: - nsTObserverArray::EndLimitedIterator iter(mListeners); + nsTObserverArray::EndLimitedIterator iter(mListeners); nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent)); PRBool hasListener = PR_FALSE; - nsListenerStruct* ls; - while ((ls = iter.GetNext())) { + while (iter.HasMore()) { + nsListenerStruct* ls = iter.GetNext(); PRBool useTypeInterface = EVENT_TYPE_DATA_EQUALS(ls->mTypeData, typeData); PRBool useGenericInterface = @@ -1682,9 +1682,9 @@ nsEventListenerManager::HasMutationListeners(PRBool* aListener) { *aListener = PR_FALSE; if (mMayHaveMutationListeners) { - PRInt32 count = mListeners.Count(); + PRInt32 count = mListeners.Length(); for (PRInt32 i = 0; i < count; ++i) { - nsListenerStruct* ls = mListeners.FastObserverAt(i); + nsListenerStruct* ls = mListeners.ElementAt(i); if (ls->mEventType >= NS_MUTATION_START && ls->mEventType <= NS_MUTATION_END) { *aListener = PR_TRUE; @@ -1701,9 +1701,9 @@ nsEventListenerManager::MutationListenerBits() { PRUint32 bits = 0; if (mMayHaveMutationListeners) { - PRInt32 i, count = mListeners.Count(); + PRInt32 i, count = mListeners.Length(); for (i = 0; i < count; ++i) { - nsListenerStruct* ls = mListeners.FastObserverAt(i); + nsListenerStruct* ls = mListeners.ElementAt(i); if (ls->mEventType >= NS_MUTATION_START && ls->mEventType <= NS_MUTATION_END) { if (ls->mEventType == NS_MUTATION_SUBTREEMODIFIED) { @@ -1739,9 +1739,9 @@ nsEventListenerManager::HasListenersFor(const nsAString& aEventName) } found: - PRInt32 i, count = mListeners.Count(); + PRInt32 i, count = mListeners.Length(); for (i = 0; i < count; ++i) { - nsListenerStruct* ls = mListeners.FastObserverAt(i); + nsListenerStruct* ls = mListeners.ElementAt(i); if (ls->mTypeAtom == atom || EVENT_TYPE_DATA_EQUALS(ls->mTypeData, typeData)) { return PR_TRUE; @@ -1753,9 +1753,9 @@ found: PRBool nsEventListenerManager::HasUnloadListeners() { - PRInt32 count = mListeners.Count(); + PRInt32 count = mListeners.Length(); for (PRInt32 i = 0; i < count; ++i) { - nsListenerStruct* ls = mListeners.FastObserverAt(i); + nsListenerStruct* ls = mListeners.ElementAt(i); if (ls->mEventType == NS_PAGE_UNLOAD || ls->mEventType == NS_BEFORE_PAGE_UNLOAD || (ls->mTypeData && ls->mTypeData->iid && diff --git a/content/events/src/nsEventListenerManager.h b/content/events/src/nsEventListenerManager.h index 82c1b9eec6d..4f58e031b02 100644 --- a/content/events/src/nsEventListenerManager.h +++ b/content/events/src/nsEventListenerManager.h @@ -49,7 +49,6 @@ #include "nsCycleCollectionParticipant.h" class nsIDOMEvent; -class nsVoidArray; class nsIAtom; struct EventTypeData; @@ -189,17 +188,17 @@ protected: nsresult GetDOM2EventGroup(nsIDOMEventGroup** aGroup); PRBool ListenerCanHandle(nsListenerStruct* aLs, nsEvent* aEvent); - nsTObserverArray mListeners; - nsISupports* mTarget; //WEAK - PRUint32 mMayHaveMutationListeners : 1; + nsTObserverArray mListeners; + nsISupports* mTarget; //WEAK + PRUint32 mMayHaveMutationListeners : 1; // These two member variables are used to cache the information // about the last event which was handled but for which event listener manager // didn't have event listeners. - PRUint32 mNoListenerForEvent : 31; - nsCOMPtr mNoListenerForEventAtom; + PRUint32 mNoListenerForEvent : 31; + nsCOMPtr mNoListenerForEventAtom; - static PRUint32 mInstanceCount; - static jsval sAddListenerID; + static PRUint32 mInstanceCount; + static jsval sAddListenerID; }; #endif // nsEventListenerManager_h__ diff --git a/layout/style/nsCSSLoader.cpp b/layout/style/nsCSSLoader.cpp index 1188cdcff9d..a496ae95165 100644 --- a/layout/style/nsCSSLoader.cpp +++ b/layout/style/nsCSSLoader.cpp @@ -1575,9 +1575,10 @@ CSSLoaderImpl::SheetComplete(SheetLoadData* aLoadData, nsresult aStatus) aStatus); } - nsTObserverArray::ForwardIterator iter(mObservers); + nsTObserverArray::ForwardIterator iter(mObservers); nsCOMPtr obs; - while ((obs = iter.GetNext())) { + while (iter.HasMore()) { + obs = iter.GetNext(); LOG((" Notifying global observer 0x%x for data 0x%s. wasAlternate: %d", obs.get(), data, data->mWasAlternate)); obs->StyleSheetLoaded(data->mSheet, data->mWasAlternate, aStatus); @@ -2325,7 +2326,7 @@ NS_IMETHODIMP CSSLoaderImpl::AddObserver(nsICSSLoaderObserver* aObserver) { NS_PRECONDITION(aObserver, "Must have observer"); - if (mObservers.AppendObserverUnlessExists(aObserver)) { + if (mObservers.AppendElementUnlessExists(aObserver)) { NS_ADDREF(aObserver); return NS_OK; } @@ -2336,7 +2337,7 @@ CSSLoaderImpl::AddObserver(nsICSSLoaderObserver* aObserver) NS_IMETHODIMP_(void) CSSLoaderImpl::RemoveObserver(nsICSSLoaderObserver* aObserver) { - if (mObservers.RemoveObserver(aObserver)) { + if (mObservers.RemoveElement(aObserver)) { NS_RELEASE(aObserver); } } diff --git a/layout/style/nsCSSLoader.h b/layout/style/nsCSSLoader.h index f3419635781..f5e26400db6 100644 --- a/layout/style/nsCSSLoader.h +++ b/layout/style/nsCSSLoader.h @@ -505,7 +505,7 @@ private: PRUint32 mDatasToNotifyOn; // Our array of "global" observers - nsTObserverArray mObservers; + nsTObserverArray mObservers; }; #endif // nsCSSLoader_h__ diff --git a/modules/libpr0n/src/imgRequest.cpp b/modules/libpr0n/src/imgRequest.cpp index c0e5dfe5430..c0a62b75d85 100644 --- a/modules/libpr0n/src/imgRequest.cpp +++ b/modules/libpr0n/src/imgRequest.cpp @@ -130,7 +130,7 @@ nsresult imgRequest::AddProxy(imgRequestProxy *proxy) NS_PRECONDITION(proxy, "null imgRequestProxy passed in"); LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::AddProxy", "proxy", proxy); - return mObservers.AppendObserverUnlessExists(proxy) ? + return mObservers.AppendElementUnlessExists(proxy) ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } @@ -138,7 +138,7 @@ nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, PRBoo { LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy", "proxy", proxy); - mObservers.RemoveObserver(proxy); + mObservers.RemoveElement(proxy); /* Check mState below before we potentially call Cancel() below. Since Cancel() may result in OnStopRequest being called back before Cancel() @@ -333,9 +333,10 @@ void imgRequest::RemoveFromCache() PRBool imgRequest::HaveProxyWithObserver(imgRequestProxy* aProxyToIgnore) const { - nsTObserverArray::ForwardIterator iter(mObservers); + nsTObserverArray::ForwardIterator iter(mObservers); imgRequestProxy* proxy; - while ((proxy = iter.GetNext())) { + while (iter.HasMore()) { + proxy = iter.GetNext(); if (proxy == aProxyToIgnore) { continue; } @@ -366,7 +367,7 @@ void imgRequest::AdjustPriority(imgRequestProxy *proxy, PRInt32 delta) // concern though is that image loads remain lower priority than other pieces // of content such as link clicks, CSS, and JS. // - if (mObservers.SafeObserverAt(0) != proxy) + if (mObservers.SafeElementAt(0, nsnull) != proxy) return; nsCOMPtr p = do_QueryInterface(mRequest); @@ -412,10 +413,9 @@ NS_IMETHODIMP imgRequest::FrameChanged(imgIContainer *container, { LOG_SCOPE(gImgLog, "imgRequest::FrameChanged"); - nsTObserverArray::ForwardIterator iter(mObservers); - imgRequestProxy* proxy; - while ((proxy = iter.GetNext())) { - proxy->FrameChanged(container, newframe, dirtyRect); + nsTObserverArray::ForwardIterator iter(mObservers); + while (iter.HasMore()) { + iter.GetNext()->FrameChanged(container, newframe, dirtyRect); } return NS_OK; @@ -430,10 +430,9 @@ NS_IMETHODIMP imgRequest::OnStartDecode(imgIRequest *request) mState |= onStartDecode; - nsTObserverArray::ForwardIterator iter(mObservers); - imgRequestProxy* proxy; - while ((proxy = iter.GetNext())) { - proxy->OnStartDecode(); + nsTObserverArray::ForwardIterator iter(mObservers); + while (iter.HasMore()) { + iter.GetNext()->OnStartDecode(); } /* In the case of streaming jpegs, it is possible to get multiple OnStartDecodes which @@ -465,10 +464,9 @@ NS_IMETHODIMP imgRequest::OnStartContainer(imgIRequest *request, imgIContainer * mImageStatus |= imgIRequest::STATUS_SIZE_AVAILABLE; - nsTObserverArray::ForwardIterator iter(mObservers); - imgRequestProxy* proxy; - while ((proxy = iter.GetNext())) { - proxy->OnStartContainer(image); + nsTObserverArray::ForwardIterator iter(mObservers); + while (iter.HasMore()) { + iter.GetNext()->OnStartContainer(image); } return NS_OK; @@ -480,10 +478,9 @@ NS_IMETHODIMP imgRequest::OnStartFrame(imgIRequest *request, { LOG_SCOPE(gImgLog, "imgRequest::OnStartFrame"); - nsTObserverArray::ForwardIterator iter(mObservers); - imgRequestProxy* proxy; - while ((proxy = iter.GetNext())) { - proxy->OnStartFrame(frame); + nsTObserverArray::ForwardIterator iter(mObservers); + while (iter.HasMore()) { + iter.GetNext()->OnStartFrame(frame); } return NS_OK; @@ -496,10 +493,9 @@ NS_IMETHODIMP imgRequest::OnDataAvailable(imgIRequest *request, { LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable"); - nsTObserverArray::ForwardIterator iter(mObservers); - imgRequestProxy* proxy; - while ((proxy = iter.GetNext())) { - proxy->OnDataAvailable(frame, rect); + nsTObserverArray::ForwardIterator iter(mObservers); + while (iter.HasMore()) { + iter.GetNext()->OnDataAvailable(frame, rect); } return NS_OK; @@ -526,10 +522,9 @@ NS_IMETHODIMP imgRequest::OnStopFrame(imgIRequest *request, mCacheEntry->SetDataSize(cacheSize + imageSize); } - nsTObserverArray::ForwardIterator iter(mObservers); - imgRequestProxy* proxy; - while ((proxy = iter.GetNext())) { - proxy->OnStopFrame(frame); + nsTObserverArray::ForwardIterator iter(mObservers); + while (iter.HasMore()) { + iter.GetNext()->OnStopFrame(frame); } return NS_OK; @@ -543,10 +538,9 @@ NS_IMETHODIMP imgRequest::OnStopContainer(imgIRequest *request, mState |= onStopContainer; - nsTObserverArray::ForwardIterator iter(mObservers); - imgRequestProxy* proxy; - while ((proxy = iter.GetNext())) { - proxy->OnStopContainer(image); + nsTObserverArray::ForwardIterator iter(mObservers); + while (iter.HasMore()) { + iter.GetNext()->OnStopContainer(image); } return NS_OK; @@ -567,10 +561,9 @@ NS_IMETHODIMP imgRequest::OnStopDecode(imgIRequest *aRequest, mImageStatus |= imgIRequest::STATUS_ERROR; } - nsTObserverArray::ForwardIterator iter(mObservers); - imgRequestProxy* proxy; - while ((proxy = iter.GetNext())) { - proxy->OnStopDecode(GetResultFromImageStatus(mImageStatus), aStatusArg); + nsTObserverArray::ForwardIterator iter(mObservers); + while (iter.HasMore()) { + iter.GetNext()->OnStopDecode(GetResultFromImageStatus(mImageStatus), aStatusArg); } return NS_OK; @@ -607,10 +600,9 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt mLoading = PR_TRUE; /* notify our kids */ - nsTObserverArray::ForwardIterator iter(mObservers); - imgRequestProxy* proxy; - while ((proxy = iter.GetNext())) { - proxy->OnStartRequest(aRequest, ctxt); + nsTObserverArray::ForwardIterator iter(mObservers); + while (iter.HasMore()) { + iter.GetNext()->OnStartRequest(aRequest, ctxt); } /* Get our principal */ @@ -739,13 +731,9 @@ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, } /* notify the kids */ - nsTObserverArray::ForwardIterator iter(mObservers); - imgRequestProxy* proxy; - while ((proxy = iter.GetNext())) { - /* calling OnStopRequest may result in the death of |proxy| so don't use the - pointer after this call. - */ - proxy->OnStopRequest(aRequest, ctxt, status, mHadLastPart); + nsTObserverArray::ForwardIterator iter(mObservers); + while (iter.HasMore()) { + iter.GetNext()->OnStopRequest(aRequest, ctxt, status, mHadLastPart); } return NS_OK; diff --git a/modules/libpr0n/src/imgRequest.h b/modules/libpr0n/src/imgRequest.h index 67fbf833d17..d45de097def 100644 --- a/modules/libpr0n/src/imgRequest.h +++ b/modules/libpr0n/src/imgRequest.h @@ -158,7 +158,7 @@ private: nsCOMPtr mDecoder; nsCOMPtr mProperties; - nsTObserverArray mObservers; + nsTObserverArray mObservers; PRPackedBool mLoading; PRPackedBool mProcessing; diff --git a/xpcom/build/dlldeps.cpp b/xpcom/build/dlldeps.cpp index 8ac72684966..34c7b9b39e6 100644 --- a/xpcom/build/dlldeps.cpp +++ b/xpcom/build/dlldeps.cpp @@ -127,8 +127,8 @@ void XXXNeverCalled() { nsTObserverArray dummyObserverArray; PRBool a = PR_FALSE; - dummyObserverArray.AppendObserver(&a); - dummyObserverArray.RemoveObserver(&a); + dummyObserverArray.AppendElement(a); + dummyObserverArray.RemoveElement(a); dummyObserverArray.Clear(); } nsStringHashSet(); diff --git a/xpcom/glue/nsTArray.h b/xpcom/glue/nsTArray.h index e6b4516eae5..c86f054dbb7 100644 --- a/xpcom/glue/nsTArray.h +++ b/xpcom/glue/nsTArray.h @@ -359,6 +359,26 @@ class nsTArray : public nsTArray_base { // Search methods // + // This method searches for the first element in this array that is equal + // to the given element. + // @param item The item to search for. + // @param comp The Comparator used to determine element equality. + // @return PR_TRUE if the element was found. + template + PRBool Contains(const Item& item, const Comparator& comp) const { + return IndexOf(item, 0, comp) != NoIndex; + } + + // This method searches for the first element in this array that is equal + // to the given element. This method assumes that 'operator==' is defined + // for elem_type. + // @param item The item to search for. + // @return PR_TRUE if the element was found. + template + PRBool Contains(const Item& item) const { + return IndexOf(item) != NoIndex; + } + // This method searches for the offset of the first element in this // array that is equal to the given element. // @param item The item to search for. @@ -735,4 +755,12 @@ class nsAutoTArray : public nsTArray { char mAutoBuf[sizeof(Header) + N * sizeof(elem_type)]; }; +// specialization for N = 0. this makes the inheritance model easier for +// templated users of nsAutoTArray. +template +class nsAutoTArray : public nsTArray { + public: + nsAutoTArray() {} +}; + #endif // nsTArray_h__ diff --git a/xpcom/glue/nsTObserverArray.cpp b/xpcom/glue/nsTObserverArray.cpp index c243067ca94..aa135f5d5b7 100644 --- a/xpcom/glue/nsTObserverArray.cpp +++ b/xpcom/glue/nsTObserverArray.cpp @@ -20,6 +20,7 @@ * * Contributor(s): * Jonas Sicking (Original Author) + * Daniel Witte * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -38,15 +39,13 @@ #include "nsTObserverArray.h" void -nsTObserverArray_base::AdjustIterators(PRInt32 aModPos, - PRInt32 aAdjustment) +nsTObserverArray_base::AdjustIterators(index_type aModPos, + diff_type aAdjustment) { NS_PRECONDITION(aAdjustment == -1 || aAdjustment == 1, "invalid adjustment"); Iterator_base* iter = mIterators; while (iter) { - NS_ASSERTION(&(iter->mArray) == this, "wrong array"); - if (iter->mPosition > aModPos) { iter->mPosition += aAdjustment; } @@ -55,14 +54,10 @@ nsTObserverArray_base::AdjustIterators(PRInt32 aModPos, } void -nsTObserverArray_base::Clear() +nsTObserverArray_base::ClearIterators() { - mObservers.Clear(); - Iterator_base* iter = mIterators; while (iter) { - NS_ASSERTION(&(iter->mArray) == this, "wrong array"); - iter->mPosition = 0; iter = iter->mNext; } diff --git a/xpcom/glue/nsTObserverArray.h b/xpcom/glue/nsTObserverArray.h index 46370f855e5..75d183689a9 100644 --- a/xpcom/glue/nsTObserverArray.h +++ b/xpcom/glue/nsTObserverArray.h @@ -20,6 +20,7 @@ * * Contributor(s): * Jonas Sicking (Original Author) + * Daniel Witte * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -38,62 +39,31 @@ #ifndef nsTObserverArray_h___ #define nsTObserverArray_h___ -#include "nsVoidArray.h" +#include "nsTArray.h" class NS_COM_GLUE nsTObserverArray_base { - public: - class Iterator_base; - friend class Iterator_base; + protected: + typedef PRUint32 index_type; + typedef PRUint32 size_type; + typedef PRInt32 diff_type; class Iterator_base { protected: friend class nsTObserverArray_base; - Iterator_base(PRInt32 aPosition, const nsTObserverArray_base& aArray) + Iterator_base(index_type aPosition, Iterator_base* aNext) : mPosition(aPosition), - mNext(aArray.mIterators), - mArray(aArray) { - aArray.mIterators = this; + mNext(aNext) { } - ~Iterator_base() { - NS_ASSERTION(mArray.mIterators == this, - "Iterators must currently be destroyed in opposite order " - "from the construction order. It is suggested that you " - "simply put them on the stack"); - mArray.mIterators = mNext; - } - - // These functions exists solely to avoid having to make the - // subclasses into friends of nsTObserverArray_base - void* GetSafeElementAt(PRInt32 aIndex) { - return mArray.mObservers.SafeElementAt(aIndex); - } - void* FastElementAt(PRInt32 aIndex) { - return mArray.mObservers.FastElementAt(aIndex); - } - - // The current position of the iterator. It's exact meaning differs - // depending on if the array is iterated forwards or backwards. See - // nsTObserverArray::ForwardIterator and - // nsTObserverArray::ReverseIterator - PRInt32 mPosition; + // The current position of the iterator. Its exact meaning differs + // depending on iterator. See nsTObserverArray::ForwardIterator. + index_type mPosition; // The next iterator currently iterating the same array Iterator_base* mNext; - - // The array we're iterating - const nsTObserverArray_base& mArray; }; - /** - * Removes all observers and collapses all iterators to the beginning of - * the array. The result is that forward iterators will see all elements - * in the array, and backward iterators will not see any more elements. - */ - void Clear(); - - protected: nsTObserverArray_base() : mIterators(nsnull) { } @@ -105,173 +75,301 @@ class NS_COM_GLUE nsTObserverArray_base { * @param adjustment -1 if an element was removed, 1 if an element was * added. */ - void AdjustIterators(PRInt32 aModPos, PRInt32 aAdjustment); + void AdjustIterators(index_type aModPos, diff_type aAdjustment); + + /** + * Clears iterators when the array is destroyed. + */ + void ClearIterators(); mutable Iterator_base* mIterators; - nsVoidArray mObservers; }; /** * An array of observers. Like a normal array, but supports iterators that are * stable even if the array is modified during iteration. - * The template parameter is the type of observer the array will hold pointers - * to. + * The template parameter T is the observer type the array will hold; + * N is the number of built-in storage slots that come with the array. + * NOTE: You probably want to use nsTObserverArray, unless you specifically + * want built-in storage. See below. + * @see nsTObserverArray, nsTArray */ -template -class nsTObserverArray : public nsTObserverArray_base { +template +class nsAutoTObserverArray : protected nsTObserverArray_base { public: + typedef T elem_type; + typedef nsTArray array_type; - PRUint32 Count() const { - return mObservers.Count(); + nsAutoTObserverArray() { } - /** - * Adds an observer to the beginning of the array - * @param aObserver Observer to add - */ - PRBool PrependObserver(T* aObserver) { - NS_PRECONDITION(!Contains(aObserver), - "Don't prepend if the observer is already in the list"); + // + // Accessor methods + // - PRBool res = mObservers.InsertElementAt(aObserver, 0); - if (res) { - AdjustIterators(0, 1); - } - return res; + // @return The number of elements in the array. + size_type Length() const { + return mArray.Length(); } - /** - * Adds an observer to the end of the array unless it already exists in - * the array. - * @param aObserver Observer to add - * @return True on success, false otherwise - */ - PRBool AppendObserverUnlessExists(T* aObserver) { - return Contains(aObserver) || mObservers.AppendElement(aObserver); + // @return True if the array is empty or false otherwise. + PRBool IsEmpty() const { + return mArray.IsEmpty(); } - /** - * Adds an observer to the end of the array. - * @param aObserver Observer to add - * @return True on success, false otherwise - */ - PRBool AppendObserver(T* aObserver) { - return mObservers.AppendElement(aObserver); + // This method provides direct access to the i'th element of the array. + // The given index must be within the array bounds. + // @param i The index of an element in the array. + // @return A reference to the i'th element of the array. + elem_type& ElementAt(index_type i) { + return mArray.ElementAt(i); } - /** - * Removes an observer from the array - * @param aObserver Observer to remove - * @return True if observer was found and removed, false otherwise - */ - PRBool RemoveObserver(T* aObserver) { - PRInt32 index = mObservers.IndexOf(aObserver); - if (index < 0) { - return PR_FALSE; - } + // Same as above, but readonly. + const elem_type& ElementAt(index_type i) const { + return mArray.ElementAt(i); + } - mObservers.RemoveElementAt(index); + // This method provides direct access to the i'th element of the array in + // a bounds safe manner. If the requested index is out of bounds the + // provided default value is returned. + // @param i The index of an element in the array. + // @param def The value to return if the index is out of bounds. + elem_type& SafeElementAt(index_type i, elem_type& def) { + return mArray.SafeElementAt(i, def); + } + + // Same as above, but readonly. + const elem_type& SafeElementAt(index_type i, const elem_type& def) const { + return mArray.SafeElementAt(i, def); + } + + // + // Search methods + // + + // This method searches, starting from the beginning of the array, + // for the first element in this array that is equal to the given element. + // 'operator==' must be defined for elem_type. + // @param item The item to search for. + // @return PR_TRUE if the element was found. + template + PRBool Contains(const Item& item) const { + return IndexOf(item) != array_type::NoIndex; + } + + // This method searches for the offset of the first element in this + // array that is equal to the given element. + // 'operator==' must be defined for elem_type. + // @param item The item to search for. + // @param start The index to start from. + // @return The index of the found element or NoIndex if not found. + template + index_type IndexOf(const Item& item, index_type start = 0) const { + return mArray.IndexOf(item, start); + } + + // + // Mutation methods + // + + // Prepend an element to the array unless it already exists in the array. + // 'operator==' must be defined for elem_type. + // @param item The item to prepend. + // @return PR_TRUE if the element was found, or inserted successfully. + template + PRBool PrependElementUnlessExists(const Item& item) { + return Contains(item) || mArray.InsertElementAt(0, item) != nsnull; + } + + // Append an element to the array. + // @param item The item to append. + // @return A pointer to the newly appended element, or null on OOM. + template + elem_type* AppendElement(const Item& item) { + return mArray.AppendElement(item); + } + + // Same as above, but without copy-constructing. This is useful to avoid + // temporaries. + elem_type* AppendElement() { + return mArray.AppendElement(); + } + + // Append an element to the array unless it already exists in the array. + // 'operator==' must be defined for elem_type. + // @param item The item to append. + // @return PR_TRUE if the element was found, or inserted successfully. + template + PRBool AppendElementUnlessExists(const Item& item) { + return Contains(item) || AppendElement(item) != nsnull; + } + + // Remove an element from the array. + // @param index The index of the item to remove. + void RemoveElementAt(index_type index) { + NS_ASSERTION(index < mArray.Length(), "invalid index"); + mArray.RemoveElementAt(index); AdjustIterators(index, -1); + } + // This helper function combines IndexOf with RemoveElementAt to "search + // and destroy" the first element that is equal to the given element. + // 'operator==' must be defined for elem_type. + // @param item The item to search for. + // @return PR_TRUE if the element was found and removed. + template + PRBool RemoveElement(const Item& item) { + index_type index = mArray.IndexOf(item, 0); + if (index == array_type::NoIndex) + return PR_FALSE; + + mArray.RemoveElementAt(index); + AdjustIterators(index, -1); return PR_TRUE; } - /** - * Removes an observer from the array - * @param aIndex Index of observer to remove - */ - void RemoveObserverAt(PRUint32 aIndex) { - if (aIndex < (PRUint32)mObservers.Count()) { - mObservers.RemoveElementAt(aIndex); - AdjustIterators(aIndex, -1); - } + // Removes all observers and collapses all iterators to the beginning of + // the array. The result is that forward iterators will see all elements + // in the array. + void Clear() { + mArray.Clear(); + ClearIterators(); } - PRBool Contains(T* aObserver) const { - return mObservers.IndexOf(aObserver) >= 0; - } + // + // Iterators + // - PRBool IsEmpty() const { - return mObservers.Count() == 0; - } + // Base class for iterators. Do not use this directly. + class Iterator : public Iterator_base { + protected: + friend class nsAutoTObserverArray; + typedef nsAutoTObserverArray array_type; - T* SafeObserverAt(PRInt32 aIndex) const { - return static_cast(mObservers.SafeElementAt(aIndex)); - } + Iterator(index_type aPosition, const array_type& aArray) + : Iterator_base(aPosition, aArray.mIterators), + mArray(const_cast(aArray)) { + aArray.mIterators = this; + } - T* FastObserverAt(PRInt32 aIndex) const { - return static_cast(mObservers.FastElementAt(aIndex)); - } + ~Iterator() { + NS_ASSERTION(mArray.mIterators == this, + "Iterators must currently be destroyed in opposite order " + "from the construction order. It is suggested that you " + "simply put them on the stack"); + mArray.mIterators = mNext; + } - /** - * Iterators - */ + // The array we're iterating + array_type& mArray; + }; - // Iterates the array forward from beginning to end. - // mPosition points to the element that will be returned on next call - // to GetNext - class ForwardIterator : public nsTObserverArray_base::Iterator_base { + // Iterates the array forward from beginning to end. mPosition points + // to the element that will be returned on next call to GetNext. + // Elements: + // - prepended to the array during iteration *will not* be traversed + // - appended during iteration *will* be traversed + // - removed during iteration *will not* be traversed. + // @see EndLimitedIterator + class ForwardIterator : protected Iterator { public: - ForwardIterator(const nsTObserverArray& aArray) - : Iterator_base(0, aArray) { - } - ForwardIterator(const nsTObserverArray& aArray, PRInt32 aPos) - : Iterator_base(aPos, aArray) { + typedef nsAutoTObserverArray array_type; + typedef Iterator base_type; + + ForwardIterator(const array_type& aArray) + : Iterator(0, aArray) { } - PRBool operator <(const ForwardIterator& aOther) { - NS_ASSERTION(&mArray == &aOther.mArray, + ForwardIterator(const array_type& aArray, index_type aPos) + : Iterator(aPos, aArray) { + } + + PRBool operator <(const ForwardIterator& aOther) const { + NS_ASSERTION(&this->mArray == &aOther.mArray, "not iterating the same array"); - return mPosition < aOther.mPosition; + return base_type::mPosition < aOther.mPosition; } - /** - * Returns the next element and steps one step. - * Returns null if there are no more observers. Once null is returned - * the iterator becomes invalid and GetNext must not be called any more. - * @return The next observer. - */ - T* GetNext() { - return static_cast(GetSafeElementAt(mPosition++)); + // Returns PR_TRUE if there are more elements to iterate. + // This must precede a call to GetNext(). If PR_FALSE is + // returned, GetNext() must not be called. + PRBool HasMore() const { + return base_type::mPosition < base_type::mArray.Length(); + } + + // Returns the next element and steps one step. This must + // be preceded by a call to HasMore(). + // @return The next observer. + elem_type& GetNext() { + NS_ASSERTION(HasMore(), "iterating beyond end of array"); + return base_type::mArray.ElementAt(base_type::mPosition++); } }; // EndLimitedIterator works like ForwardIterator, but will not iterate new - // observers added to the array after the iterator was created. - class EndLimitedIterator : private ForwardIterator { + // observers appended to the array after the iterator was created. + class EndLimitedIterator : protected ForwardIterator { public: - typedef typename nsTObserverArray::ForwardIterator base_type; + typedef nsAutoTObserverArray array_type; + typedef Iterator base_type; - EndLimitedIterator(const nsTObserverArray& aArray) + EndLimitedIterator(const array_type& aArray) : ForwardIterator(aArray), - mEnd(aArray, aArray.Count()) { + mEnd(aArray, aArray.Length()) { } - /** - * Returns the next element and steps one step. - * Returns null if there are no more observers. Once null is returned - * the iterator becomes invalid and GetNext must not be called any more. - * @return The next observer. - */ - T* GetNext() { - return (*this < mEnd) ? - static_cast(FastElementAt(base_type::mPosition++)) : - nsnull; + // Returns PR_TRUE if there are more elements to iterate. + // This must precede a call to GetNext(). If PR_FALSE is + // returned, GetNext() must not be called. + PRBool HasMore() const { + return *this < mEnd; + } + + // Returns the next element and steps one step. This must + // be preceded by a call to HasMore(). + // @return The next observer. + elem_type& GetNext() { + NS_ASSERTION(HasMore(), "iterating beyond end of array"); + return base_type::mArray.ElementAt(base_type::mPosition++); } private: ForwardIterator mEnd; }; + + protected: + nsAutoTArray mArray; +}; + +template +class nsTObserverArray : public nsAutoTObserverArray { + public: + typedef nsAutoTObserverArray base_type; + typedef nsTObserverArray_base::size_type size_type; + + // + // Initialization methods + // + + nsTObserverArray() {} + + // Initialize this array and pre-allocate some number of elements. + explicit nsTObserverArray(size_type capacity) { + base_type::mArray.SetCapacity(capacity); + } }; // XXXbz I wish I didn't have to pass in the observer type, but I // don't see a way to get it out of array_. +// Note that this macro only works if the array holds pointers to XPCOM objects. #define NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(array_, obstype_, func_, params_) \ PR_BEGIN_MACRO \ - nsTObserverArray::ForwardIterator iter_(array_); \ + nsTObserverArray::ForwardIterator iter_(array_); \ nsCOMPtr obs_; \ - while ((obs_ = iter_.GetNext())) { \ + while (iter_.HasMore()) { \ + obs_ = iter_.GetNext(); \ obs_ -> func_ params_ ; \ } \ PR_END_MACRO