mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-28 11:28:38 +00:00
143 lines
7.6 KiB
C++
143 lines
7.6 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#ifndef nsIPtr_h___
|
|
#define nsIPtr_h___
|
|
|
|
#include "nsISupports.h"
|
|
|
|
/*
|
|
* nsIPtr is an "auto-release pointer" class for nsISupports based interfaces
|
|
*
|
|
* It's intent is to be a "set and forget" pointer to help with managing
|
|
* active references to nsISupports bases objects.
|
|
*
|
|
* The pointer object ensures that the underlying pointer is always
|
|
* released whenever the value is changed or when the object leaves scope.
|
|
*
|
|
* Proper care needs to be taken when assigning pointers to a nsIPtr.
|
|
* When asigning from a C pointer (nsISupports*), the pointer presumes
|
|
* an active reference and subsumes it. When assigning from another nsIPtr,
|
|
* a new reference is established.
|
|
*
|
|
* There are 3 ways to assign a value to a nsIPtr.
|
|
* 1) Direct construction or assignment from a C pointer.
|
|
* 2) Direct construction or assignment form another nsIPtr.
|
|
* 3) Usage of an "out parameter" method.
|
|
* a) AssignRef() releases the underlying pointer and returns a reference to it.
|
|
* Useful for pointer reference out paramaters.
|
|
* b) AssignPtr() releases the underlying pointer and returns a pointer to it.
|
|
* c) Query() releases the underlying pointer and returns a (void**) pointer to it.
|
|
* Useful for calls to QueryInterface()
|
|
* 4) The SetAddRef() method. This is equivalent to an assignment followed by an AddRef().
|
|
*
|
|
* examples:
|
|
*
|
|
* class It {
|
|
* void NS_NewFoo(nsIFoo** aFoo);
|
|
* nsIFoo* GetFoo(void);
|
|
* void GetBar(nsIBar*& aBar);
|
|
* };
|
|
*
|
|
* nsIFooPtr foo = it->GetFoo();
|
|
* nsIBarPtr bar;
|
|
*
|
|
* it->NS_NewFoo(foo.AssignPtr());
|
|
* it->GetBar(bar.AssignRef());
|
|
* it->QueryInterface(kIFooIID, foo.Query());
|
|
* bar.SetAddRef(new Bar());
|
|
*
|
|
* Advantages:
|
|
* Set and forget. Once a pointer is assigned to a nsIPtr, it is impossible
|
|
* to forget to release it.
|
|
* Always pre-initialized. You can't forget to initialize the pointer.
|
|
*
|
|
* Disadvantages:
|
|
* Usage of this class doesn't eliminate the need to think about ref counts
|
|
* and assign values properly, AddRef'ing as needed.
|
|
* The nsIPtr doesn't typecast exactly like a C pointer. In order to achieve
|
|
* typecasting, it may be necessary to first cast to a C pointer of the
|
|
* underlying type.
|
|
*
|
|
*/
|
|
|
|
#define NS_DEF_PTR(cls) \
|
|
class cls##Ptr { \
|
|
public: \
|
|
cls##Ptr(void) : mPtr(0) {} \
|
|
cls##Ptr(const cls##Ptr& aCopy) : mPtr(aCopy.mPtr) \
|
|
{ NS_IF_ADDREF(mPtr); } \
|
|
cls##Ptr(cls* aInterface) : mPtr(aInterface) {} \
|
|
~cls##Ptr(void) { NS_IF_RELEASE(mPtr); } \
|
|
cls##Ptr& operator=(const cls##Ptr& aCopy) \
|
|
{ if(mPtr == aCopy.mPtr) return *this; \
|
|
NS_IF_ADDREF(aCopy.mPtr); \
|
|
NS_IF_RELEASE(mPtr); \
|
|
mPtr = aCopy.mPtr; return *this; } \
|
|
cls##Ptr& operator=(cls* aInterface) \
|
|
{ if(mPtr == aInterface) return *this; \
|
|
NS_IF_RELEASE(mPtr); mPtr = aInterface; \
|
|
return *this; } \
|
|
cls##Ptr& operator=(PRInt32 aInt) \
|
|
{ NS_IF_RELEASE(mPtr); \
|
|
return *this; } \
|
|
void SetAddRef(cls* aInterface) \
|
|
{ if(aInterface == mPtr) return; \
|
|
NS_IF_ADDREF(aInterface); \
|
|
NS_IF_RELEASE(mPtr); mPtr = aInterface; } \
|
|
cls* AddRef(void) { NS_ADDREF(mPtr); return mPtr; } \
|
|
cls* IfAddRef(void) \
|
|
{ NS_IF_ADDREF(mPtr); return mPtr; } \
|
|
cls*& AssignRef(void) \
|
|
{ NS_IF_RELEASE(mPtr); return mPtr; } \
|
|
cls** AssignPtr(void) \
|
|
{ NS_IF_RELEASE(mPtr); return &mPtr; } \
|
|
void** Query(void) \
|
|
{ NS_IF_RELEASE(mPtr); return (void**)&mPtr; } \
|
|
PRBool IsNull() const \
|
|
{ return PRBool(0 == mPtr); } \
|
|
PRBool IsNotNull() const \
|
|
{ return PRBool(0 != mPtr); } \
|
|
PRBool operator==(const cls##Ptr& aCopy) const \
|
|
{ return PRBool(mPtr == aCopy.mPtr); } \
|
|
PRBool operator==(cls* aInterface) const \
|
|
{ return PRBool(mPtr == aInterface); } \
|
|
PRBool operator!=(const cls##Ptr& aCopy) const \
|
|
{ return PRBool(mPtr != aCopy.mPtr); } \
|
|
PRBool operator!=(cls* aInterface) const \
|
|
{ return PRBool(mPtr != aInterface); } \
|
|
cls* operator->(void) { return mPtr; } \
|
|
cls& operator*(void) { return *mPtr; } \
|
|
operator cls*(void) { return mPtr; } \
|
|
const cls* operator->(void) const { return mPtr; } \
|
|
const cls& operator*(void) const { return *mPtr; } \
|
|
operator const cls* (void) const { return mPtr; } \
|
|
private: \
|
|
void* operator new(size_t size) { return 0; } \
|
|
void operator delete(void* aPtr) {} \
|
|
cls* mPtr; \
|
|
public: \
|
|
friend inline PRBool operator==(const cls* aInterface, const cls##Ptr& aPtr) \
|
|
{ return PRBool(aInterface == aPtr.mPtr); } \
|
|
friend inline PRBool operator!=(const cls* aInterface, const cls##Ptr& aPtr) \
|
|
{ return PRBool(aInterface != aPtr.mPtr); } \
|
|
}
|
|
|
|
#endif // nsIPtr_h___
|
|
|