Main Page   Compound List   File List   Compound Members   File Members  

TclXPCOMStub.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * The contents of this file are subject to the Mozilla Public License Version
00004  * 1.1 (the "License"); you may not use this file except in compliance with
00005  * the License. You may obtain a copy of the License at
00006  * http://www.mozilla.org/MPL/
00007  *
00008  * Software distributed under the License is distributed on an "AS IS" basis,
00009  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00010  * for the specific language governing rights and limitations under the
00011  * License.
00012  *
00013  * The Original Code is TclXPCOM.
00014  * 
00015  * The Initial Developer of the Original Code is Mark Follett.
00016  * Portions created by Mark Follett are Copyright (C) 2001-2002
00017  * Mark Follett.  All Rights Reserved.
00018  * 
00019  * Contributor(s):
00020  *     Mark Follett <mef123@myrealbox.com> (Original Author)
00021  *
00022  * Alternatively, the contents of this file may be used under the terms of
00023  * either the GNU General Public License Version 2 or later (the "GPL"), or
00024  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00025  * in which case the provisions of the GPL or the LGPL are applicable instead
00026  * of those above. If you wish to allow use of your version of this file only
00027  * under the terms of either the GPL or the LGPL, and not to allow others to
00028  * use your version of this file under the terms of the MPL, indicate your
00029  * decision by deleting the provisions above and replace them with the notice
00030  * and other provisions required by the GPL or the LGPL. If you do not delete
00031  * the provisions above, a recipient may use your version of this file under
00032  * the terms of any one of the MPL, the GPL or the LGPL.
00033  */
00034 
00035 #include "TclXPCOMPrivate.h"
00036 
00037 
00038 nsIID nsisupportsweakreference_iid = NS_ISUPPORTSWEAKREFERENCE_IID;
00039 
00045 TclXPCOMStub::TclXPCOMStub(
00046     nsIInterfaceInfo *interfaceinfo 
00047 )
00048 {
00049     PRUint16 methodcount;
00050     
00051     NS_PRECONDITION(interfaceinfo, "null pointer");
00052 
00053     info = interfaceinfo;
00054     NS_ADDREF(info);
00055     
00056     info->GetMethodCount(&methodcount);
00057 
00058     if (methodcount)
00059     {
00060         bindings = (Tcl_Obj **)memmgr->Alloc(sizeof(Tcl_Obj *) * methodcount);
00061         memset(bindings, 0, sizeof(Tcl_Obj *) * methodcount);
00062     } else
00063     {
00064         bindings = NULL;
00065     }
00066 }
00067 
00068 
00072 TclXPCOMStub::~TclXPCOMStub(void)
00073 {
00074     PRUint16 methodcount, i;
00075     
00076     info->GetMethodCount(&methodcount);
00077     
00078     for (i = 0; i < methodcount; i++)
00079     {
00080         UnsetBinding(i);
00081     }
00082     
00083     if (bindings)
00084     {
00085         memmgr->Free(bindings);
00086     }
00087     
00088     NS_RELEASE(info);
00089 }
00090 
00091 
00097 void
00098 TclXPCOMStub::SetBinding(
00099     PRUint16 methodindex, 
00100     Tcl_Obj *script       
00101 )
00102 {
00103     NS_PRECONDITION(script, "null pointer");
00104 
00105     if (bindings[methodindex])
00106     {
00107         UnsetBinding(methodindex);
00108     }
00109     
00110     bindings[methodindex] = script;
00111     Tcl_IncrRefCount(script);
00112 }
00113 
00114 
00118 void
00119 TclXPCOMStub::UnsetBinding(
00120     PRUint16 methodindex 
00121 )
00122 {
00123     if (bindings[methodindex])
00124     {
00125         Tcl_DecrRefCount(bindings[methodindex]);
00126         bindings[methodindex] = NULL;
00127     }
00128 }
00129 
00130 
00136 Tcl_Obj *
00137 TclXPCOMStub::GetBinding(
00138     PRUint16 methodindex 
00139 )
00140 {
00141     return bindings[methodindex];
00142 }
00143 
00144 
00150 NS_IMETHODIMP
00151 TclXPCOMStub::GetInterfaceInfo(
00152     nsIInterfaceInfo **interfaceinfo 
00153 )
00154 {
00155     NS_PRECONDITION(interfaceinfo, "null pointer");
00156 
00157     NS_ADDREF(info);
00158     *interfaceinfo = info;
00159     return NS_OK;
00160 }
00161 
00162 
00168 NS_IMETHODIMP
00169 TclXPCOMStub::CallMethod(
00170     PRUint16               methodIndex,
00171     const nsXPTMethodInfo *info,       
00172     nsXPTCMiniVariant     *params      
00173 )
00174 {
00175     // no precondition on methodIndex
00176     NS_PRECONDITION(info, "null pointer");
00177     NS_PRECONDITION(params, "null pointer");
00178 
00179     if (!component->interp)
00180     {
00181         // if the interpreter that runs this component is killed,
00182         // any method invocations will just return an error
00183         printf("Stub invocation failed cuz the interp is dead!\n");
00184         return NS_ERROR_FAILURE;
00185     }
00186 
00187     if (bindings[methodIndex])
00188     {
00189         // XXX TODO: make this threadsafe
00190         NS_ASSERTION((component->thread == Tcl_GetCurrentThread()), "attempt to invoke a component from the wrong thread");
00191         //--- thread check,  if on different thread,  post an event & wait for return
00192         return TclXPCOM_CallMethod(component->interp, params, (nsISupports *)(nsXPTCStubBase *)this, this->info, methodIndex, bindings[methodIndex]);
00193     } else
00194     {
00195         return NS_ERROR_NOT_IMPLEMENTED;
00196     }
00197 }
00198 
00199 
00205 NS_IMETHODIMP
00206 TclXPCOMStub::QueryInterface(
00207     REFNSIID   aIID,        
00208     void     **aInstancePtr 
00209 )
00210 {
00211     int i;
00212     nsresult res;
00213     nsISupports *isupports;
00214     nsXPTCMiniVariant params[2];
00215 
00216     // no precondition on aIID
00217     // aInstancePtr checked later
00218 
00219     if (!aInstancePtr)
00220     {
00221         return NS_ERROR_NULL_POINTER;
00222     }
00223 
00224     if (bindings[0] && component->interp && !component->nesting)
00225     {
00226         params[0].val.p = (void *)&aIID;
00227         params[1].val.p = aInstancePtr;
00228 
00229         // XXX TODO: make this threadsafe
00230         NS_ASSERTION((component->thread == Tcl_GetCurrentThread()), "attempt to invoke a component from the wrong thread");
00231         //--- thread check,  if on different thread,  post an event & wait for return
00232         component->nesting = 1;
00233         res = TclXPCOM_CallMethod(component->interp, params, (nsISupports *)(nsXPTCStubBase *)this, this->info, 0, bindings[0]);
00234         component->nesting = 0;
00235         return res;
00236     }
00237 
00238     for (i = 0; i < component->cinfo->signature.infocount; i++)
00239     {
00240         if (isInInterface(component->stubs[i]->info, (nsIID *)&aIID))
00241         {
00242             isupports = (nsISupports *)(nsXPTCStubBase *)component->stubs[i];
00243             NS_ADDREF(isupports);
00244             *aInstancePtr = isupports;
00245             return NS_OK;
00246         }
00247     }
00248 
00249     // nsISupportsWeakReference is supported by default
00250     if (aIID.Equals(nsisupportsweakreference_iid))
00251     {
00252         isupports = NS_STATIC_CAST(nsISupportsWeakReference*, this);
00253         NS_ADDREF(isupports);
00254         *aInstancePtr = isupports;
00255         return NS_OK;
00256     }
00257 
00258     *aInstancePtr = NULL;
00259     return NS_ERROR_NO_INTERFACE;
00260 }
00261 
00262 
00268 NS_IMETHODIMP_(nsrefcnt)
00269 TclXPCOMStub::AddRef(void)
00270 {
00271     nsrefcnt count;
00272 
00273     NS_PRECONDITION(PRInt32(component->refcount) >= 0, "illegal refcnt");
00274     
00275     count = PR_AtomicIncrement((PRInt32*)&component->refcount);
00276     NS_LOG_ADDREF(this, count, "TclXPCOMStub", sizeof(*this));
00277 
00278     char str[128];
00279     sprintf(str, "Addrefing Component %p, Refcount: %d", component, count);
00280     NS_WARNING(str);
00281 
00282     return count;
00283 }
00284 
00285 
00291 NS_IMETHODIMP_(nsrefcnt)
00292 TclXPCOMStub::Release(void)
00293 {
00294     int rv;
00295     nsrefcnt count;
00296     Tcl_SavedResult savedresult;
00297 
00298     NS_PRECONDITION(0 != component->refcount, "dup release");
00299  
00300     count = PR_AtomicDecrement((PRInt32 *)&component->refcount);
00301     NS_LOG_RELEASE(this, count, "TclXPCOMStub");
00302 
00303     char str[128];
00304     sprintf(str, "Releasing Component %p, Refcount: %d", component, count);
00305     NS_WARNING(str);
00306 
00307     if (0 == count) {
00308         component->refcount = 1; /* stabilize */
00309         /* enable this to find non-threadsafe destructors: */
00310         /* NS_ASSERT_OWNINGTHREAD(_class); */
00311         
00312         // tcl destructor script should be called in the release function
00313         // a destructor script may save [xpcom this] and thus prevent the
00314         // component from being deleted
00315         if (component->destructor && component->interp)
00316         {
00317             // XXX warn if component->interp == NULL
00318             // XXX TODO: make this threadsafe
00319             NS_ASSERTION((component->thread == Tcl_GetCurrentThread()), "attempt to invoke a component from the wrong thread");
00320             Tcl_Preserve(component->interp);
00321             Tcl_SaveResult(component->interp, &savedresult);
00322             rv = Tcl_EvalObjEx(component->interp, component->destructor, TCL_EVAL_GLOBAL);
00323             if (rv != TCL_OK)
00324             {
00325                 Tcl_AddObjErrorInfo(component->interp, "\nwhile executing component destructor:\n\"", -1);
00326                 Tcl_AddObjErrorInfo(component->interp, Tcl_GetString(component->destructor), -1);
00327                 Tcl_AddObjErrorInfo(component->interp, "\"", -1);
00328                 TclXPCOM_BackgroundError(component->interp);
00329             }
00330             
00331             Tcl_RestoreResult(component->interp, &savedresult);
00332             Tcl_Release(component->interp);
00333         }
00334         
00335         if (component->refcount == 1)
00336         {
00337             sprintf(str, "Destroyed Component %p", component);
00338             NS_WARNING(str);
00339 
00340             FreeTclXPCOMComponent(component);
00341 
00342             return 0;
00343         } else
00344         {
00345             component->refcount--;
00346             return component->refcount;
00347         }
00348     }
00349     return count;
00350 }
00351 
00352 

Generated on Fri Jun 14 23:25:51 2002 for TclXPCOM by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002