diff -r 000000000000 -r 6474c204b198 xpcom/glue/nsWeakReference.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xpcom/glue/nsWeakReference.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// nsWeakReference.cpp + +#include "mozilla/Attributes.h" + +#include "nsWeakReference.h" +#include "nsCOMPtr.h" + +class nsWeakReference MOZ_FINAL : public nsIWeakReference + { + public: + // nsISupports... + NS_DECL_ISUPPORTS + + // nsIWeakReference... + NS_DECL_NSIWEAKREFERENCE + + private: + friend class nsSupportsWeakReference; + + nsWeakReference( nsSupportsWeakReference* referent ) + : mReferent(referent) + // ...I can only be constructed by an |nsSupportsWeakReference| + { + // nothing else to do here + } + + ~nsWeakReference() + // ...I will only be destroyed by calling |delete| myself. + { + if ( mReferent ) + mReferent->NoticeProxyDestruction(); + } + + void + NoticeReferentDestruction() + // ...called (only) by an |nsSupportsWeakReference| from _its_ dtor. + { + mReferent = 0; + } + + nsSupportsWeakReference* mReferent; + }; + +nsresult +nsQueryReferent::operator()( const nsIID& aIID, void** answer ) const + { + nsresult status; + if ( mWeakPtr ) + { + if ( NS_FAILED(status = mWeakPtr->QueryReferent(aIID, answer)) ) + *answer = 0; + } + else + status = NS_ERROR_NULL_POINTER; + + if ( mErrorPtr ) + *mErrorPtr = status; + return status; + } + +NS_COM_GLUE nsIWeakReference* // or else |already_AddRefed| +NS_GetWeakReference( nsISupports* aInstancePtr, nsresult* aErrorPtr ) + { + nsresult status; + + nsIWeakReference* result = nullptr; + + if ( aInstancePtr ) + { + nsCOMPtr factoryPtr = do_QueryInterface(aInstancePtr, &status); + if ( factoryPtr ) + { + status = factoryPtr->GetWeakReference(&result); + } + // else, |status| has already been set by |do_QueryInterface| + } + else + status = NS_ERROR_NULL_POINTER; + + if ( aErrorPtr ) + *aErrorPtr = status; + return result; + } + +NS_COM_GLUE nsresult +nsSupportsWeakReference::GetWeakReference( nsIWeakReference** aInstancePtr ) + { + if ( !aInstancePtr ) + return NS_ERROR_NULL_POINTER; + + if ( !mProxy ) + mProxy = new nsWeakReference(this); + *aInstancePtr = mProxy; + + nsresult status; + if ( !*aInstancePtr ) + status = NS_ERROR_OUT_OF_MEMORY; + else + { + NS_ADDREF(*aInstancePtr); + status = NS_OK; + } + + return status; + } + +NS_IMPL_ISUPPORTS(nsWeakReference, nsIWeakReference) + +NS_IMETHODIMP +nsWeakReference::QueryReferent( const nsIID& aIID, void** aInstancePtr ) + { + return mReferent ? mReferent->QueryInterface(aIID, aInstancePtr) : NS_ERROR_NULL_POINTER; + } + +void +nsSupportsWeakReference::ClearWeakReferences() + { + if ( mProxy ) + { + mProxy->NoticeReferentDestruction(); + mProxy = 0; + } + } +