Changes to make observer lists hold only weak references. This code is disabled by default; enabled by the symbol |NS_WEAK_OBSERVERS|. The code will remain disabled until two underlying ownership bugs are fixed: hanging the wallet service from something permanent, and finding the observer someone is registering through XPConnect that does not support weak references. bug#=18682; r=dp

This commit is contained in:
scc%netscape.com 1999-12-08 05:24:14 +00:00
parent ac4e013485
commit 2645d4a68f

View File

@ -26,6 +26,8 @@
#include "nsObserverList.h"
#include "nsString.h"
#include "nsAutoLock.h"
#include "nsCOMPtr.h"
#include "nsIWeakReference.h"
#define NS_AUTOLOCK(__monitor) nsAutoLock __lock(__monitor)
@ -33,6 +35,114 @@
static NS_DEFINE_CID(kObserverListCID, NS_OBSERVERLIST_CID);
class nsObserverListEnumerator : public nsIBidirectionalEnumerator
{
public:
nsObserverListEnumerator( nsISupportsArray* );
NS_DECL_ISUPPORTS
NS_DECL_NSIENUMERATOR
NS_DECL_NSIBIDIRECTIONALENUMERATOR
private:
PRUint32 GetTargetArraySize() const;
nsresult MoveToIndex( PRUint32 );
private:
nsCOMPtr<nsISupportsArray> mTargetArray;
PRUint32 mCurrentItemIndex;
};
NS_IMPL_ISUPPORTS2(nsObserverListEnumerator, nsIBidirectionalEnumerator, nsIEnumerator)
nsObserverListEnumerator::nsObserverListEnumerator( nsISupportsArray* anArray )
: mRefCnt(0),
mTargetArray(anArray),
mCurrentItemIndex(0)
{
// nothing else to do here
}
PRUint32
nsObserverListEnumerator::GetTargetArraySize() const
{
PRUint32 array_size = 0;
mTargetArray->Count(&array_size);
return array_size;
}
nsresult
nsObserverListEnumerator::MoveToIndex( PRUint32 aNewIndex )
{
nsresult status;
if ( aNewIndex < GetTargetArraySize() )
{
mCurrentItemIndex = aNewIndex;
status = NS_OK;
}
else
status = NS_ERROR_FAILURE; // array bounds violation
return status;
}
NS_IMETHODIMP
nsObserverListEnumerator::First()
{
NS_ASSERTION(mTargetArray, "must enumerate over an non-null list");
return MoveToIndex(0);
}
NS_IMETHODIMP
nsObserverListEnumerator::Last()
{
NS_ASSERTION(mTargetArray, "must enumerate over an non-null list");
return MoveToIndex(GetTargetArraySize()-1);
}
NS_IMETHODIMP
nsObserverListEnumerator::Prev()
{
NS_ASSERTION(mTargetArray, "must enumerate over an non-null list");
return MoveToIndex(mCurrentItemIndex-1);
}
NS_IMETHODIMP
nsObserverListEnumerator::Next()
{
NS_ASSERTION(mTargetArray, "must enumerate over an non-null list");
return MoveToIndex(mCurrentItemIndex+1);
}
NS_IMETHODIMP
nsObserverListEnumerator::CurrentItem( nsISupports** aItemPtr )
{
NS_ASSERTION(mTargetArray, "must enumerate over an non-null list");
NS_ASSERTION(aItemPtr, "must supply a place to put the result");
nsWeakPtr weakPtr = getter_AddRefs(NS_REINTERPRET_CAST(nsIWeakReference*, mTargetArray->ElementAt(mCurrentItemIndex)));
if ( !aItemPtr || !weakPtr )
return NS_ERROR_NULL_POINTER;
return weakPtr->QueryReferent(NS_GET_IID(nsIObserver), aItemPtr);
}
NS_IMETHODIMP
nsObserverListEnumerator::IsDone()
{
NS_ASSERTION(mTargetArray, "must enumerate over an non-null list");
return (mCurrentItemIndex == (GetTargetArraySize()-1)) ? NS_OK : NS_ENUMERATOR_FALSE;
}
////////////////////////////////////////////////////////////////////////////////
// nsObserverList Implementation
@ -87,8 +197,14 @@ nsresult nsObserverList::AddObserver(nsIObserver** anObserver)
if (NS_FAILED(rv)) return rv;
}
#if NS_WEAK_OBSERVERS
nsWeakPtr observer_ref = getter_AddRefs(NS_GetWeakReference(*anObserver));
if(observer_ref) {
inserted = mObserverList->AppendElement(observer_ref);
#else
if(*anObserver) {
inserted = mObserverList->AppendElement(*anObserver);
inserted = mObserverList->AppendElement(*anObserver);
#endif
return inserted ? NS_OK : NS_ERROR_FAILURE;
}
@ -110,8 +226,14 @@ nsresult nsObserverList::RemoveObserver(nsIObserver** anObserver)
return NS_ERROR_FAILURE;
}
#if NS_WEAK_OBSERVERS
nsWeakPtr observer_ref = getter_AddRefs(NS_GetWeakReference(*anObserver));
if(observer_ref) {
removed = mObserverList->RemoveElement(observer_ref);
#else
if(*anObserver) {
removed = mObserverList->RemoveElement(*anObserver);
removed = mObserverList->RemoveElement(*anObserver);
#endif
return removed ? NS_OK : NS_ERROR_FAILURE;
}
@ -131,7 +253,15 @@ NS_IMETHODIMP nsObserverList::EnumerateObserverList(nsIEnumerator** anEnumerator
if(!mObserverList) {
return NS_ERROR_FAILURE;
}
return mObserverList->Enumerate(anEnumerator);
#if NS_WEAK_OBSERVERS
nsCOMPtr<nsIBidirectionalEnumerator> enumerator = new nsObserverListEnumerator(mObserverList);
if ( !enumerator )
return NS_ERROR_OUT_OF_MEMORY;
return CallQueryInterface(enumerator, anEnumerator);
#else
return mObserverList->Enumerate(anEnumerator);
#endif
}