Back to index

lightning-sunbird  0.9+nobinonly
SupportsMixin.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the MRJ Carbon OJI Plugin.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corp.
00018  * Portions created by the Initial Developer are Copyright (C) 2001
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Patrick C. Beard <beard@netscape.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039     SupportsMixin.cpp
00040     
00041     Experimental way to implement nsISupports interface.
00042     
00043     by Patrick C. Beard.
00044  */
00045 
00046 #include "SupportsMixin.h"
00047 #include "nsAgg.h"
00048 #include <DriverSynchronization.h>
00049 
00050 // Standard nsISupport method implementations.
00051 
00052 #ifdef SUPPORT_AGGREGATION
00053 
00054 SupportsMixin::SupportsMixin(void* instance, const InterfaceInfo interfaces[], UInt32 interfaceCount, nsISupports* outer)
00055     : mInstance(instance), mRefCount(0), mInterfaces(interfaces), mInterfaceCount(interfaceCount), mOuter(outer)
00056 {
00057     if (mOuter != NULL)
00058         mInner = new Inner(this);
00059 }
00060 
00061 SupportsMixin::~SupportsMixin()
00062 {
00063     if (mRefCount > 0) {
00064         ::DebugStr("\pmRefCount > 0!");
00065     }
00066     if (mInner != NULL)
00067         delete mInner;
00068 }
00069 
00074 nsresult SupportsMixin::OuterQueryInterface(const nsIID& aIID, void** aInstancePtr)
00075 {
00076     // first, see if we really implement this interface.
00077     nsresult result = queryInterface(aIID, aInstancePtr);
00078     // if not, then delegate to the outer object, if any.
00079     if (result != NS_OK && mOuter != NULL)
00080         return mOuter->QueryInterface(aIID, aInstancePtr);
00081     else
00082         return result;
00083 }
00084 
00085 nsrefcnt SupportsMixin::OuterAddRef()
00086 {
00087     nsrefcnt result = addRef();
00088     if (mOuter != NULL)
00089         return mOuter->AddRef();
00090     return result;
00091 }
00092 
00093 nsrefcnt SupportsMixin::OuterRelease()
00094 {
00095     if (mOuter != NULL) {
00096         nsIOuter* outer = NULL;
00097         nsISupports* supports = mOuter;
00098         static NS_DEFINE_IID(kIOuterIID, NS_IOUTER_IID);
00099         if (mRefCount == 1 && supports->QueryInterface(kIOuterIID, &outer) == NS_OK) {
00100             outer->ReleaseInner(mInner);
00101             outer->Release();
00102         } else
00103             release();
00104         return supports->Release();
00105     } else {
00106         return release();
00107     }
00108 }
00109 
00110 #else /* !SUPPORT_AGGREGATION */
00111 
00112 SupportsMixin::SupportsMixin(void* instance, const InterfaceInfo interfaces[], UInt32 interfaceCount, nsISupports* /* outer */)
00113     : mInstance(instance), mRefCount(0), mInterfaces(interfaces), mInterfaceCount(interfaceCount)
00114 {
00115 }
00116 
00117 SupportsMixin::~SupportsMixin()
00118 {
00119     if (mRefCount > 0) {
00120         ::DebugStr("\pmRefCount > 0!");
00121     }
00122 }
00123 
00124 #endif /* !SUPPORT_AGGREGATION */
00125 
00131 NS_IMETHODIMP SupportsMixin::queryInterface(const nsIID& aIID, void** aInstancePtr)
00132 {
00133     if (aInstancePtr == NULL) {
00134         return NS_ERROR_NULL_POINTER;
00135     }
00136     // first check to see if it's one of our known interfaces.
00137     // need to solve the non-left inheritance graph case.
00138     const InterfaceInfo* interfaces = mInterfaces;
00139     UInt32 count = mInterfaceCount;
00140     for (UInt32 i = 0; i < count; i++) {
00141         if (aIID.Equals(interfaces[i].mIID)) {
00142             *aInstancePtr = (void*) (UInt32(mInstance) + interfaces[i].mOffset);
00143             addRef();
00144             return NS_OK;
00145         }
00146     }
00147     // finally, does the interface match nsISupports?
00148     static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
00149     if (aIID.Equals(kISupportsIID)) {
00150         *aInstancePtr = (void*) mInstance;
00151         addRef();
00152         return NS_OK;
00153     }
00154     return NS_NOINTERFACE;
00155 }
00156 
00157 NS_IMETHODIMP_(nsrefcnt) SupportsMixin::addRef()
00158 {
00159     IncrementAtomic((SInt32*)&mRefCount);
00160     return mRefCount;
00161 }
00162 
00163 NS_IMETHODIMP_(nsrefcnt) SupportsMixin::release()
00164 {
00165     // NOTE: IncrementAtomic increments the value by 1 and DecrementAtomic decrements it by 1.
00166     // These functions return the value as it was before the change.
00167     if (DecrementAtomic((SInt32*)&mRefCount) == 1) {
00168         delete this;
00169         return 0;
00170     }
00171     return mRefCount;
00172 }