forked from mirrors/gecko-dev
		
	NS_GetWeakReference, called from do_GetWeakReference, QI's its argument to nsISupportsWeakReference to determine whether a weak reference can be obtained. If NS_GetWeakReference is already receiving a nsISupportsWeakReference pointer, or something than can be converted to one, then we can skip the QI for a small performance win.
		
			
				
	
	
		
			173 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | 
						|
/* 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"
 | 
						|
#include "nsDebug.h"
 | 
						|
 | 
						|
class nsWeakReference final : public nsIWeakReference
 | 
						|
{
 | 
						|
public:
 | 
						|
  // nsISupports...
 | 
						|
  NS_DECL_ISUPPORTS
 | 
						|
 | 
						|
  // nsIWeakReference...
 | 
						|
  NS_DECL_NSIWEAKREFERENCE
 | 
						|
  size_t SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
 | 
						|
 | 
						|
private:
 | 
						|
  friend class nsSupportsWeakReference;
 | 
						|
 | 
						|
  explicit nsWeakReference(nsSupportsWeakReference* aReferent)
 | 
						|
    : nsIWeakReference(aReferent)
 | 
						|
    // ...I can only be constructed by an |nsSupportsWeakReference|
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  ~nsWeakReference()
 | 
						|
  // ...I will only be destroyed by calling |delete| myself.
 | 
						|
  {
 | 
						|
    MOZ_WEAKREF_ASSERT_OWNINGTHREAD;
 | 
						|
    if (mObject) {
 | 
						|
      static_cast<nsSupportsWeakReference*>(mObject)->NoticeProxyDestruction();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void
 | 
						|
  NoticeReferentDestruction()
 | 
						|
  // ...called (only) by an |nsSupportsWeakReference| from _its_ dtor.
 | 
						|
  {
 | 
						|
    MOZ_WEAKREF_ASSERT_OWNINGTHREAD;
 | 
						|
    mObject = nullptr;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
nsresult
 | 
						|
nsQueryReferent::operator()(const nsIID& aIID, void** aAnswer) const
 | 
						|
{
 | 
						|
  nsresult status;
 | 
						|
  if (mWeakPtr) {
 | 
						|
    if (NS_FAILED(status = mWeakPtr->QueryReferent(aIID, aAnswer))) {
 | 
						|
      *aAnswer = 0;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    status = NS_ERROR_NULL_POINTER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mErrorPtr) {
 | 
						|
    *mErrorPtr = status;
 | 
						|
  }
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
nsIWeakReference*
 | 
						|
NS_GetWeakReference(nsISupportsWeakReference* aInstancePtr, nsresult* aErrorPtr)
 | 
						|
{
 | 
						|
  nsresult status;
 | 
						|
 | 
						|
  nsIWeakReference* result = nullptr;
 | 
						|
 | 
						|
  if (aInstancePtr) {
 | 
						|
    status = aInstancePtr->GetWeakReference(&result);
 | 
						|
  } else {
 | 
						|
    status = NS_ERROR_NULL_POINTER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (aErrorPtr) {
 | 
						|
    *aErrorPtr = status;
 | 
						|
  }
 | 
						|
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
nsIWeakReference*  // or else |already_AddRefed<nsIWeakReference>|
 | 
						|
NS_GetWeakReference(nsISupports* aInstancePtr, nsresult* aErrorPtr)
 | 
						|
{
 | 
						|
  nsresult status;
 | 
						|
 | 
						|
  nsIWeakReference* result = nullptr;
 | 
						|
 | 
						|
  if (aInstancePtr) {
 | 
						|
    nsCOMPtr<nsISupportsWeakReference> 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;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
nsSupportsWeakReference::GetWeakReference(nsIWeakReference** aInstancePtr)
 | 
						|
{
 | 
						|
  if (!aInstancePtr) {
 | 
						|
    return NS_ERROR_NULL_POINTER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!mProxy) {
 | 
						|
    mProxy = new nsWeakReference(this);
 | 
						|
  } else {
 | 
						|
    MOZ_WEAKREF_ASSERT_OWNINGTHREAD_DELEGATED(mProxy);
 | 
						|
  }
 | 
						|
  *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::QueryReferentFromScript(const nsIID& aIID, void** aInstancePtr)
 | 
						|
{
 | 
						|
  return QueryReferent(aIID, aInstancePtr);
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
nsIWeakReference::QueryReferent(const nsIID& aIID, void** aInstancePtr)
 | 
						|
{
 | 
						|
  MOZ_WEAKREF_ASSERT_OWNINGTHREAD;
 | 
						|
 | 
						|
  if (!mObject) {
 | 
						|
    return NS_ERROR_NULL_POINTER;
 | 
						|
  }
 | 
						|
 | 
						|
  return mObject->QueryInterface(aIID, aInstancePtr);
 | 
						|
}
 | 
						|
 | 
						|
size_t
 | 
						|
nsWeakReference::SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const
 | 
						|
{
 | 
						|
  return aMallocSizeOf(this);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
nsSupportsWeakReference::ClearWeakReferences()
 | 
						|
{
 | 
						|
  if (mProxy) {
 | 
						|
    mProxy->NoticeReferentDestruction();
 | 
						|
    mProxy = nullptr;
 | 
						|
  }
 | 
						|
}
 | 
						|
 |