mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
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:
parent
ac4e013485
commit
2645d4a68f
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user