dougt's changes from earlier in the week. He was unable to leave them

in at that time because he didn't have my |nsCOMPtr| fixes.  Those went
in last night.  So, on brendans suggestion, I'm reinstating dougt's
previous checkin.
This commit is contained in:
scc%netscape.com 1999-11-08 22:58:14 +00:00
Родитель 34a64c7050
Коммит ace7038d48
6 изменённых файлов: 598 добавлений и 348 удалений

Просмотреть файл

@ -76,18 +76,21 @@ class nsProxyObject : public nsISupports
public:
NS_DECL_ISUPPORTS
NS_DEFINE_STATIC_IID_ACCESSOR(nsCOMTypeInfo<nsISupports>::GetIID())
NS_DEFINE_STATIC_IID_ACCESSOR(nsCOMTypeInfo<nsISupports>::GetIID())
nsProxyObject();
nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject);
nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID);
virtual ~nsProxyObject();
nsresult Post(PRUint32 methodIndex, nsXPTMethodInfo *info,
nsXPTCMiniVariant *params, nsIInterfaceInfo *interfaceInfo);
nsresult Post( PRUint32 methodIndex,
nsXPTMethodInfo * info,
nsXPTCMiniVariant * params,
nsIInterfaceInfo * interfaceInfo);
nsresult NestedEventLoop(nsProxyObjectCallInfo *proxyInfo);
nsISupports* GetRealObject() const { return mRealObject; }
nsresult PostAndWait(nsProxyObjectCallInfo *proxyInfo);
nsISupports* GetRealObject();
nsIEventQueue* GetQueue();
PRInt32 GetProxyType() const { return mProxyType; }
@ -95,6 +98,20 @@ public:
private:
PRInt32 mProxyType;
nsCOMPtr<nsIEventQueue> mDestQueue; /* destination queue */
nsCOMPtr<nsISupports> mRealObject; /* the non-proxy object that this event is referring to.
This is a strong ref. */
nsresult convertMiniVariantToVariant(nsXPTMethodInfo * methodInfo,
nsXPTCMiniVariant * params,
nsXPTCVariant **fullParam,
uint8 *paramCount);
#ifdef AUTOPROXIFICATION
typedef enum
{
@ -108,19 +125,7 @@ private:
nsresult AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMiniVariant * params,
nsIInterfaceInfo *interfaceInfo, AutoProxyConvertTypes convertType);
#endif
nsIEventQueue *mDestQueue; /* destination queue */
nsISupports *mRealObject; /* the non-proxy object that this event is referring to.
This is a strong ref. */
PRBool mRealObjectOwned;
PRInt32 mProxyType;
nsresult convertMiniVariantToVariant(nsXPTMethodInfo *methodInfo, nsXPTCMiniVariant * params,
nsXPTCVariant **fullParam, uint8 *paramCount);
};
};
class NS_EXPORT nsProxyObjectCallInfo
@ -128,6 +133,7 @@ class NS_EXPORT nsProxyObjectCallInfo
public:
nsProxyObjectCallInfo(nsProxyObject* owner,
nsXPTMethodInfo *methodInfo,
PRUint32 methodIndex,
nsXPTCVariant* parameterList,
PRUint32 parameterCount,
@ -141,23 +147,35 @@ public:
PLEvent* GetPLEvent() const { return mEvent; }
nsresult GetResult() const { return mResult; }
nsProxyObject* GetProxyObject() const { return mOwner; }
PRBool GetCompleted();
void SetCompleted();
void PostCompleted();
void SetResult(nsresult rv) {mResult = rv; }
void SetCompleted();
nsIEventQueue* GetCallersQueue();
void SetCallersQueue(nsIEventQueue* queue);
private:
nsresult mResult; /* this is the return result of the called function */
nsXPTMethodInfo *mMethodInfo;
PRUint32 mMethodIndex; /* which method to be called? */
nsXPTCVariant *mParameterList; /* marshalled in parameter buffer */
PRUint32 mParameterCount; /* number of params */
PLEvent *mEvent; /* the current plevent */
PRInt32 mCompleted; /* is true when the method has been called. */
nsCOMPtr<nsProxyObject> mOwner; /* this is the strong referenced nsProxyObject */
nsIEventQueue* mCallersEventQ; /* this is the eventQ that we must post a message back to
when we are done invoking the method (only PROXY_SYNC).
this does not need to be a comptr because it will be
released by the created in PostAndWait()
*/
nsCOMPtr<nsProxyObject> mOwner; /* this is the strong referenced nsProxyObject */
void RefCountInInterfacePointers(PRBool addRef);
};

Просмотреть файл

@ -26,7 +26,7 @@
#include "nsProxyObjectManager.h"
#include "pratom.h"
#include "prmem.h" // for PR_NEW
#include "prmem.h"
#include "xptcall.h"
#include "nsRepository.h"
@ -41,8 +41,11 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static void* EventHandler(PLEvent *self);
static void DestroyHandler(PLEvent *self);
static void* CompletedEventHandler(PLEvent *self);
static void CompletedDestroyHandler(PLEvent *self) ;
nsProxyObjectCallInfo::nsProxyObjectCallInfo(nsProxyObject* owner,
nsProxyObjectCallInfo::nsProxyObjectCallInfo( nsProxyObject* owner,
nsXPTMethodInfo *methodInfo,
PRUint32 methodIndex,
nsXPTCVariant* parameterList,
PRUint32 parameterCount,
@ -54,33 +57,102 @@ nsProxyObjectCallInfo::nsProxyObjectCallInfo(nsProxyObject* owner,
mParameterList = parameterList;
mParameterCount = parameterCount;
mEvent = event;
mMethodInfo = methodInfo;
mCallersEventQ = 0;
RefCountInInterfacePointers(PR_TRUE);
}
nsProxyObjectCallInfo::~nsProxyObjectCallInfo()
{
RefCountInInterfacePointers(PR_FALSE);
// I am worried about order of destruction here.
// do not remove assignments.
mOwner = 0;
mCallersEventQ = 0;
PR_FREEIF(mEvent);
if (mParameterList)
free( (void*) mParameterList);
}
PRBool
void
nsProxyObjectCallInfo::RefCountInInterfacePointers(PRBool addRef)
{
for (PRUint32 i = 0; i < mParameterCount; i++)
{
nsXPTParamInfo paramInfo = mMethodInfo->GetParam(i);
if (paramInfo.GetType().IsInterfacePointer() )
{
nsISupports* anInterface = nsnull;
if (paramInfo.IsIn())
{
anInterface = ((nsISupports*)mParameterList[i].val.p);
if (anInterface)
{
if(addRef)
anInterface->AddRef();
else
anInterface->Release();
}
}
}
}
}
PRBool
nsProxyObjectCallInfo::GetCompleted()
{
return (PRBool)mCompleted;
}
void
void
nsProxyObjectCallInfo::SetCompleted()
{
PR_AtomicSet(&mCompleted, 1);
}
void
nsProxyObjectCallInfo::PostCompleted()
{
if (mCallersEventQ)
{
PLEvent *event = PR_NEW(PLEvent);
PL_InitEvent(event,
this,
CompletedEventHandler,
CompletedDestroyHandler);
mCallersEventQ->PostSynchronousEvent(event, nsnull);
PR_FREEIF(event);
}
else
{
// caller does not have an eventQ? This is an error!
SetCompleted();
}
}
nsIEventQueue*
nsProxyObjectCallInfo::GetCallersQueue()
{
return mCallersEventQ;
}
void
nsProxyObjectCallInfo::SetCallersQueue(nsIEventQueue* queue)
{
mCallersEventQ = queue;
}
#ifdef debug_DOUGT
static PRUint32 totalProxyObjects = 0;
static PRUint32 outstandingProxyObjects = 0;
#endif
NS_IMPL_ISUPPORTS0(nsProxyObject)
@ -90,71 +162,66 @@ nsProxyObject::nsProxyObject()
}
nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject)
{
#ifdef debug_DOUGT
totalProxyObjects++;
outstandingProxyObjects++;
#endif
NS_INIT_REFCNT();
NS_ADDREF_THIS();
mRealObject = realObject;
mDestQueue = do_QueryInterface(destQueue);
mProxyType = proxyType;
mDestQueue = destQueue;
}
nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID)
{
#ifdef debug_DOUGT
totalProxyObjects++;
outstandingProxyObjects++;
#endif
NS_INIT_REFCNT();
NS_ADDREF_THIS();
nsComponentManager::CreateInstance(aClass,
aDelegate,
aIID,
(void**) &mRealObject);
getter_AddRefs(mRealObject));
mDestQueue = do_QueryInterface(destQueue);
mProxyType = proxyType;
mDestQueue = destQueue;
}
nsProxyObject::~nsProxyObject()
{
#ifdef debug_DOUGT
outstandingProxyObjects--;
printf("[proxyobjects] %d total used in system, %d outstading\n", totalProxyObjects, outstandingProxyObjects);
#endif
// I am worried about order of destruction here.
// do not remove assignments.
mRealObject = 0;
mDestQueue = 0;
}
// GetRealObject
// This function must return the real pointer to the object to be proxied.
// It must not be a comptr or be addreffed.
nsISupports*
nsProxyObject::GetRealObject()
{
return mRealObject.get();
}
nsIEventQueue*
nsProxyObject::GetQueue()
{
if (mDestQueue)
NS_ADDREF(mDestQueue);
return mDestQueue;
}
nsresult
nsProxyObject::NestedEventLoop(nsProxyObjectCallInfo *proxyInfo)
nsProxyObject::PostAndWait(nsProxyObjectCallInfo *proxyInfo)
{
if (proxyInfo == nsnull) return NS_ERROR_NULL_POINTER;
PLEvent* event = proxyInfo->GetPLEvent();
PRBool eventLoopCreated = PR_FALSE;
nsresult rv;
//---------------------
//This block of code should be a function of the EventQueueServices
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
nsIEventQueue *eventQ;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
nsCOMPtr<nsIEventQueue> eventQ;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), getter_AddRefs(eventQ));
if (NS_FAILED(rv))
{
rv = eventQService->CreateThreadEventQueue();
@ -162,36 +229,50 @@ nsProxyObject::NestedEventLoop(nsProxyObjectCallInfo *proxyInfo)
if (NS_FAILED(rv))
return rv;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), getter_AddRefs(eventQ));
}
else
{
NS_RELEASE(eventQ);
rv = eventQService->PushThreadEventQueue(&eventQ);
eventQ = 0;
rv = eventQService->PushThreadEventQueue(getter_AddRefs(eventQ));
}
if (NS_FAILED(rv))
return rv;
//---------------------
proxyInfo->SetCallersQueue(eventQ);
PLEvent* event = proxyInfo->GetPLEvent();
if (!event)
return NS_ERROR_NULL_POINTER;
mDestQueue->PostEvent(event);
while (! proxyInfo->GetCompleted())
{
//rv = eventQ->WaitForEvent();
//if (NS_FAILED(rv)) break;
rv = eventQ->GetEvent(&event);
if (NS_FAILED(rv)) break;
eventQ->HandleEvent(event);
PR_Sleep( PR_MillisecondsToInterval(5) );
PR_Sleep(PR_MillisecondsToInterval(100));
}
if (eventLoopCreated)
{
NS_RELEASE(eventQ);
eventQService->DestroyThreadEventQueue();
eventQ = 0;
}
else
{
eventQService->PopThreadEventQueue(eventQ);
nsIEventQueue *dumbAddref = eventQ;
NS_ADDREF(dumbAddref); // PopThreadEventQueue released the nsCOMPtr,
// then we crash while leaving this functions.
eventQService->PopThreadEventQueue(dumbAddref); // this is totally evil
}
return rv;
@ -221,10 +302,7 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi
{
nsresult rv = NS_OK;
if (mDestQueue == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
if (mRealObject == nsnull)
if (! mDestQueue || ! mRealObject)
return NS_ERROR_OUT_OF_MEMORY;
if (methodInfo->IsNotXPCOM())
@ -235,28 +313,38 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi
if (event == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
///////////////////////////////////////////////////////////////////////
// Auto-proxification
///////////////////////////////////////////////////////////////////////
#ifdef AUTOPROXIFICATION
#ifdef AUTOPROXIFICATION
// this should move into the nsProxyObjectCallInfo.
rv = AutoProxyParameterList(methodIndex, methodInfo, params, interfaceInfo, convertInParameters);
#endif
///////////////////////////////////////////////////////////////////////
if (NS_FAILED(rv))
{
delete event;
return rv;
}
#endif
nsXPTCVariant *fullParam;
uint8 paramCount;
rv = convertMiniVariantToVariant(methodInfo, params, &fullParam, &paramCount);
if (NS_FAILED(rv))
{
delete event;
return rv;
}
nsProxyObjectCallInfo *proxyInfo = new nsProxyObjectCallInfo(this, methodIndex, fullParam, paramCount, event);
nsProxyObjectCallInfo *proxyInfo = new nsProxyObjectCallInfo(this,
methodInfo,
methodIndex,
fullParam, // will be deleted by ~()
paramCount,
event); // will be deleted by ~()
if (proxyInfo == nsnull)
{
delete event;
free(fullParam); // allocated with malloc
return NS_ERROR_OUT_OF_MEMORY;
}
@ -273,12 +361,13 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi
if (callDirectly)
{
EventHandler(event);
// there is no need to call the DestroyHandler() because
// there is no need to wake up the nested event loop.
}
else
{
mDestQueue->PostEvent(event);
rv = NestedEventLoop(proxyInfo);
//mDestQueue->PostSynchronousEvent(event, nsnull);
rv = PostAndWait(proxyInfo);
if (NS_FAILED(rv))
return rv;
}
@ -286,14 +375,9 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi
rv = proxyInfo->GetResult();
delete proxyInfo;
///////////////////////////////////////////////////////////////////////
// Auto-proxification
///////////////////////////////////////////////////////////////////////
#ifdef AUTOPROXIFICATION
rv = AutoProxyParameterList(methodIndex, methodInfo, params, interfaceInfo, convertOutParameters);
#endif
///////////////////////////////////////////////////////////////////////
return rv;
}
@ -302,16 +386,70 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi
mDestQueue->PostEvent(event);
return NS_OK;
}
return NS_ERROR_UNEXPECTED;
}
void DestroyHandler(PLEvent *self)
{
nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
nsProxyObject* proxyObject = owner->GetProxyObject();
if (proxyObject == nsnull)
return;
if (proxyObject->GetProxyType() & PROXY_ASYNC)
{
delete owner;
}
else
{
owner->PostCompleted();
}
}
void* EventHandler(PLEvent *self)
{
nsProxyObjectCallInfo *info = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
NS_ASSERTION(info, "No nsProxyObjectCallInfo!");
nsProxyObject *proxyObject = info->GetProxyObject();
if (proxyObject)
{
// invoke the magic of xptc...
nsresult rv = XPTC_InvokeByIndex( proxyObject->GetRealObject(),
info->GetMethodIndex(),
info->GetParameterCount(),
info->GetParameterList());
info->SetResult(rv);
}
else
{
info->SetResult(NS_ERROR_OUT_OF_MEMORY);
}
return NULL;
}
void CompletedDestroyHandler(PLEvent *self)
{
}
void* CompletedEventHandler(PLEvent *self)
{
nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
owner->SetCompleted();
return nsnull;
}
#ifdef AUTOPROXIFICATION
// ssc@netscape.com wishes he could get rid of this instance of |NS_DEFINE_IID|, but |ProxyEventClassIdentity| is not visible from here
static NS_DEFINE_IID(kProxyObject_Identity_Class_IID, NS_PROXYEVENT_IDENTITY_CLASS_IID);
nsresult
nsProxyObject::AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMiniVariant * params,
AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMiniVariant * params,
nsIInterfaceInfo *interfaceInfo, AutoProxyConvertTypes convertType)
{
nsresult rv = NS_OK;
@ -526,45 +664,3 @@ nsProxyObject::AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *met
return rv;
}
#endif
void DestroyHandler(PLEvent *self)
{
nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
nsProxyObject* proxyObject = owner->GetProxyObject();
if (proxyObject->GetProxyType() & PROXY_ASYNC)
{
delete owner;
}
else
{
owner->SetCompleted();
}
}
void* EventHandler(PLEvent *self)
{
nsProxyObjectCallInfo *info = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
if (info != nsnull)
{
nsProxyObject *proxyObject = info->GetProxyObject();
if (proxyObject)
{
// invoke the magic of xptc...
nsresult rv = XPTC_InvokeByIndex( proxyObject->GetRealObject(),
info->GetMethodIndex(),
info->GetParameterCount(),
info->GetParameterList());
info->SetResult(rv);
}
else
{
info->SetResult(NS_ERROR_OUT_OF_MEMORY);
}
}
return NULL;
}

Просмотреть файл

@ -45,9 +45,6 @@ static uint32 zero_methods_descriptor;
//////////////////////////////////////////////////////////////////////////////////////////////////
// nsProxyEventClass
//////////////////////////////////////////////////////////////////////////////////////////////////
static NS_DEFINE_IID(kProxyEventClassIID, NS_PROXYEVENT_CLASS_IID);
NS_IMPL_ISUPPORTS(nsProxyEventClass, kProxyEventClassIID)
// static
@ -64,7 +61,7 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
return nsnull;
}
nsProxyEventClass* clazz = NULL;
nsProxyEventClass* clazz = nsnull;
nsIDKey key(aIID);
if(iidToClassMap->Exists(&key))
@ -74,22 +71,20 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
}
else
{
nsIInterfaceInfoManager* iimgr;
if(NULL != (iimgr = XPTI_GetInterfaceInfoManager()))
nsCOMPtr<nsIInterfaceInfoManager> iimgr = getter_AddRefs(XPTI_GetInterfaceInfoManager());
if(iimgr)
{
nsIInterfaceInfo* info;
if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, &info)))
nsCOMPtr<nsIInterfaceInfo> info;
if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, getter_AddRefs(info))))
{
/*
Check to see if isISupportsDescendent
*/
nsIInterfaceInfo* oldest = info;
nsIInterfaceInfo* parent;
nsCOMPtr<nsIInterfaceInfo> oldest = info;
nsCOMPtr<nsIInterfaceInfo> parent;
NS_ADDREF(oldest);
while(NS_SUCCEEDED(oldest->GetParent(&parent)))
while(NS_SUCCEEDED(oldest->GetParent(getter_AddRefs(parent))))
{
NS_RELEASE(oldest);
oldest = parent;
}
@ -100,8 +95,7 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
isISupportsDescendent = iid->Equals(nsCOMTypeInfo<nsISupports>::GetIID());
nsAllocator::Free(iid);
}
NS_RELEASE(oldest);
NS_VERIFY(isISupportsDescendent,"!isISupportsDescendent");
if (isISupportsDescendent)
@ -110,24 +104,25 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
if(!clazz->mDescriptors)
NS_RELEASE(clazz); // sets clazz to NULL
}
NS_RELEASE(info);
}
NS_RELEASE(iimgr);
}
}
return clazz;
}
nsProxyEventClass::nsProxyEventClass()
{
NS_WARNING("This constructor should never be called");
}
nsProxyEventClass::nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo)
: mInfo(aInfo),
mIID(aIID),
: mIID(aIID),
mDescriptors(NULL)
{
NS_ADDREF(mInfo);
NS_INIT_REFCNT();
NS_ADDREF_THIS();
mInfo = aInfo;
/* add use to the used classes */
nsIDKey key(aIID);
@ -172,8 +167,6 @@ nsProxyEventClass::~nsProxyEventClass()
{
iidToClassMap->Remove(&key);
}
NS_RELEASE(mInfo);
}
nsresult
@ -218,10 +211,9 @@ nsProxyEventClass::CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID
// This 'ProxyEventClassIdentity' class and singleton allow us to figure out if
// any given nsISupports* is implemented by a nsProxy object. This is done
// using a QueryInterface call on the interface pointer with our ID. If
// that call returns NS_OK and the pointer is to our singleton, then the
// interface must be implemented by a nsProxy object. NOTE: the
// 'ProxyEventClassIdentity' object is not a real XPCOM object and should not be
// used for anything else
// that call returns NS_OK and the pointer is to a nsProxyEventObject. It must
// be released when done.
// NS_PROXYEVENT_IDENTITY_CLASS_IID defined in nsProxyEventPrivate.h
class ProxyEventClassIdentity
{
@ -243,24 +235,47 @@ nsProxyEventClass::DelegatedQueryInterface(nsProxyEventObject* self,
REFNSIID aIID,
void** aInstancePtr)
{
if(NULL == aInstancePtr)
{
NS_PRECONDITION(0, "null pointer");
return NS_ERROR_NULL_POINTER;
}
if(aIID.Equals(self->GetIID()))
{
*aInstancePtr = (void*) self;
NS_ADDREF(self);
return NS_OK;
}
if(aIID.Equals(ProxyEventClassIdentity::GetIID()))
{
*aInstancePtr = ProxyEventClassIdentity::GetSingleton();
*aInstancePtr = (void**)self; //todo this should be a static cast
NS_ADDREF(self);
return NS_OK;
}
nsProxyEventObject* sibling;
// This includes checking for nsISupports and the iid of self.
// And it also checks for other wrappers that have been constructed
// for this object.
if(nsnull != (sibling = self->Find(aIID)))
{
NS_ADDREF(sibling);
*aInstancePtr = (void*) sibling;
return NS_OK;
}
// check if asking for an interface that we inherit from
nsCOMPtr<nsIInterfaceInfo> current = GetInterfaceInfo();
nsCOMPtr<nsIInterfaceInfo> parent;
while(NS_SUCCEEDED(current->GetParent(getter_AddRefs(parent))) && parent)
{
current = parent;
nsIID* iid;
if(NS_SUCCEEDED(current->GetIID(&iid)) && iid)
{
PRBool found = aIID.Equals(*iid);
nsAllocator::Free(iid);
if(found)
{
*aInstancePtr = (void*) self;
NS_ADDREF(self);
return NS_OK;
}
}
}
return CallQueryInterfaceOnProxy(self, aIID, (nsProxyEventObject**)aInstancePtr);
}

Просмотреть файл

@ -29,6 +29,76 @@
#include "nsIInterfaceInfoManager.h"
#include "xptcall.h"
static NS_DEFINE_IID(kProxyObject_Identity_Class_IID, NS_PROXYEVENT_IDENTITY_CLASS_IID);
#ifdef DEBUG_dougt
static PRMonitor* mon = nsnull;
static PRUint32 totalProxyObjects = 0;
static PRUint32 outstandingProxyObjects = 0;
void
nsProxyEventObject::DebugDump(const char * message, PRUint32 hashKey)
{
if (mon == nsnull)
{
mon = PR_NewMonitor();
}
PR_EnterMonitor(mon);
if (message)
{
printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-\n");
printf("%s\n", message);
if(strcmp(message, "Create") == 0)
{
totalProxyObjects++;
outstandingProxyObjects++;
}
else if(strcmp(message, "Delete") == 0)
{
outstandingProxyObjects--;
}
}
printf("nsProxyEventObject @ %x with mRefCnt = %d\n", this, mRefCnt);
PRBool isRoot = mRoot == nsnull;
printf("%s wrapper around @ %x\n", isRoot ? "ROOT":"non-root\n", GetRealObject());
if (mHashKey.HashValue()!=0)
printf("Hashkey: %d\n", mHashKey.HashValue());
char* name;
GetClass()->GetInterfaceInfo()->GetName(&name);
printf("interface name is %s\n", name);
if(name)
nsAllocator::Free(name);
char * iid = GetClass()->GetProxiedIID().ToString();
printf("IID number is %s\n", iid);
delete iid;
printf("nsProxyEventClass @ %x\n", mClass);
if(mNext)
{
if(isRoot)
{
printf("Additional wrappers for this object...\n");
}
mNext->DebugDump(nsnull, 0);
}
printf("[proxyobjects] %d total used in system, %d outstading\n", totalProxyObjects, outstandingProxyObjects);
if (message)
printf("-=-=-=-=-=-=-=-=-=-=-=-=-\n");
PR_ExitMonitor(mon);
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////
@ -36,89 +106,112 @@
// nsProxyEventObject
//
//////////////////////////////////////////////////////////////////////////////////////////////////
nsProxyEventObject*
nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue,
PRInt32 proxyType,
nsISupports *aObj,
REFNSIID aIID)
{
nsProxyEventObject* proxy = NULL;
nsProxyEventObject* root = NULL;
nsCOMPtr<nsProxyEventObject> proxy = 0;
nsCOMPtr<nsProxyEventObject> root = 0;
nsProxyEventObject* peo;
nsProxyEventClass* clazz = nsProxyEventClass::GetNewOrUsedClass(aIID);
if(!clazz)
return NULL;
nsISupports* rootObject;
// always find the native root
if(NS_FAILED(aObj->QueryInterface(nsCOMTypeInfo<nsISupports>::GetIID(), (void**)&rootObject)))
return NULL;
/* find in our hash table */
// Get a class for this IID.
nsCOMPtr<nsProxyEventClass> clazz = getter_AddRefs( nsProxyEventClass::GetNewOrUsedClass(aIID) );
if(!clazz) return nsnull;
nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
if (realToProxyMap == nsnull)
// make sure that the object pass in is not a proxy.
nsCOMPtr<nsProxyEventObject> aIdentificationObject;
if (NS_SUCCEEDED(aObj->QueryInterface(kProxyObject_Identity_Class_IID, getter_AddRefs(aIdentificationObject))))
{
if(clazz)
NS_RELEASE(clazz);
return nsnull;
// someone is asking us to create a proxy for a proxy. Lets get
// the real object and build aproxy for that!
aObj = aIdentificationObject->GetRealObject();
aIdentificationObject = 0;
if (aObj == nsnull) return nsnull;
}
nsVoidKey rootkey(rootObject);
// always find the native root if the |real| object.
nsCOMPtr<nsISupports> rootObject;
if(NS_FAILED(aObj->QueryInterface(nsCOMTypeInfo<nsISupports>::GetIID(), getter_AddRefs(rootObject))))
return nsnull;
/* get our hash table */
nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
if (manager == nsnull) return nsnull;
nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
if (realToProxyMap == nsnull) return nsnull;
// we need to do make sure that we addref the passed in object as well as ensure
// that it is of the requested IID;
nsCOMPtr<nsISupports> requestedInterface;
if(NS_FAILED(aObj->QueryInterface(aIID, getter_AddRefs(requestedInterface))))
return nsnull;
// this will be our key in the hash table.
nsVoidKey rootkey( (void*) GetProxyHashKey(rootObject.get(), destQueue, proxyType) );
// find in our hash table
if(realToProxyMap->Exists(&rootkey))
{
root = (nsProxyEventObject*) realToProxyMap->Get(&rootkey);
root = (nsProxyEventObject*) realToProxyMap->Get(&rootkey);
proxy = root->Find(aIID);
if(proxy)
if(proxy)
{
NS_ADDREF(proxy);
goto return_wrapper;
peo = proxy;
NS_ADDREF(peo);
return peo;
}
}
else
{
// build the root proxy
if (aObj == rootObject)
if (aObj == rootObject.get())
{
// the root will do double duty as the interface wrapper
proxy = root = new nsProxyEventObject(destQueue, proxyType, aObj, clazz, nsnull);
if(root)
peo = new nsProxyEventObject(destQueue,
proxyType,
requestedInterface,
clazz,
nsnull,
rootkey.HashValue());
proxy = do_QueryInterface(peo);
if(proxy)
{
nsVoidKey aKey(root);
realToProxyMap->Put(&aKey, root);
NS_ADDREF(proxy); // since we are double duty, we need to make sure that our refCnt
// reflects this.
realToProxyMap->Put(&rootkey, peo);
peo = proxy;
NS_ADDREF(peo);
return peo;
}
goto return_wrapper;
}
else
{
// just a root proxy
nsProxyEventClass* rootClazz = nsProxyEventClass::GetNewOrUsedClass(nsCOMTypeInfo<nsISupports>::GetIID());
if(!rootClazz)
{
goto return_wrapper;
}
root = new nsProxyEventObject(destQueue, proxyType, rootObject, rootClazz, nsnull);
NS_RELEASE(rootClazz);
if(!root)
{
goto return_wrapper;
}
nsCOMPtr<nsProxyEventClass> rootClazz = getter_AddRefs ( nsProxyEventClass::GetNewOrUsedClass(
nsCOMTypeInfo<nsISupports>::GetIID()) );
nsVoidKey aKey(root);
realToProxyMap->Put(&aKey, root);
if (!rootClazz)
return nsnull;
peo = new nsProxyEventObject(destQueue,
proxyType,
rootObject,
rootClazz,
nsnull,
rootkey.HashValue());
if(!peo)
return nsnull;
root = do_QueryInterface(peo);
realToProxyMap->Put(&rootkey, peo);
}
}
// at this point we have a root and may need to build the specific proxy
@ -127,90 +220,89 @@ nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue,
if(!proxy)
{
proxy = new nsProxyEventObject(destQueue, proxyType, aObj, clazz, root);
peo = new nsProxyEventObject(destQueue,
proxyType,
requestedInterface,
clazz,
root,
0);
proxy = do_QueryInterface(peo);
if(!proxy)
{
goto return_wrapper;
}
return nsnull;
}
proxy->mNext = root->mNext;
root->mNext = proxy;
return_wrapper:
peo = proxy;
NS_ADDREF(peo);
return peo;
if(clazz)
NS_RELEASE(clazz);
// Since we do not want to extra references, we will release the rootObject.
//
// There are one or more references to aObj which is passed in. When we create
// a new proxy object via nsProxyEventObject(), that will addRef the aObj. Because
// we QI addref to insure that we have a nsISupports ptr, its refcount goes up by one.
// here we will decrement that.
//
if (rootObject)
NS_RELEASE(rootObject);
return proxy;
}
nsProxyEventObject::nsProxyEventObject()
: mNext(nsnull),
mHashKey((void*)0)
{
NS_WARNING("This constructor should never be called");
}
nsProxyEventObject::nsProxyEventObject(nsIEventQueue *destQueue,
PRInt32 proxyType,
nsISupports* aObj,
nsProxyEventClass* aClass,
nsProxyEventObject* root)
: mClass(aClass),
mNext(NULL)
nsProxyEventObject* root,
PRUint32 hashValue)
: mNext(nsnull),
mHashKey((void*)hashValue)
{
NS_INIT_REFCNT();
NS_ADDREF_THIS();
mProxyObject = new nsProxyObject(destQueue, proxyType, aObj);
mRoot = (root ? root : this);
// if we have a root, lets addref it.
if (root)
NS_ADDREF(mRoot);
mRoot = root;
mClass = aClass;
NS_ADDREF(aClass);
mProxyObject = new nsProxyObject(destQueue, proxyType, aObj);
#ifdef DEBUG_dougt
DebugDump("Create", 0);
#endif
}
nsProxyEventObject::~nsProxyEventObject()
{
NS_IF_RELEASE(mProxyObject);
NS_IF_RELEASE(mClass);
if (mRoot)
#ifdef DEBUG_dougt
DebugDump("Delete", 0);
#endif
if (mRoot != nsnull)
{
if (mRoot != this)
nsProxyEventObject* cur = mRoot;
while(1)
{
mRoot->RootRemoval();
}
else
{
nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
if (realToProxyMap != nsnull)
if(cur->mNext == this)
{
nsVoidKey key(this);
realToProxyMap->Remove(&key);
cur->mNext = mNext;
break;
}
cur = cur->mNext;
NS_ASSERTION(cur, "failed to find wrapper in its own chain");
}
}
else
{
nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
if (realToProxyMap != nsnull && mHashKey.HashValue() != 0)
{
realToProxyMap->Remove(&mHashKey);
}
}
}
nsresult
nsProxyEventObject::RootRemoval()
{
if (--mRefCnt <= 1)
NS_DELETEXPCOM(this);
return NS_OK;
// I am worried about ordering.
// do not remove assignments.
mProxyObject = 0;
mClass = 0;
mRoot = 0;
}
NS_IMPL_ADDREF(nsProxyEventObject);
@ -219,22 +311,44 @@ NS_IMPL_RELEASE(nsProxyEventObject);
NS_IMETHODIMP
nsProxyEventObject::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
// TODO: we need to wrap the object if it is not a proxy.
if( aIID.Equals(GetIID()) )
{
*aInstancePtr = (void*) ( (nsISupports*)this ); //todo should use standard cast.
NS_ADDREF_THIS();
return NS_OK;
}
return mClass->DelegatedQueryInterface(this, aIID, aInstancePtr);
}
PRUint32
nsProxyEventObject::GetProxyHashKey(nsISupports *rootProxy, nsIEventQueue *destQueue, PRInt32 proxyType)
{ // FIX I need to worry about nsCOMPtr for rootProxy, and destQueue!
nsISupports* destQRoot;
if(NS_FAILED(destQueue->QueryInterface(nsCOMTypeInfo<nsISupports>::GetIID(), (void**)&destQRoot)))
return 0;
PRInt32 value = (PRUint32)rootProxy + (PRUint32)destQRoot + proxyType;
NS_RELEASE(destQRoot);
return value;
}
nsProxyEventObject*
nsProxyEventObject::Find(REFNSIID aIID)
{
if(aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
return mRoot;
nsProxyEventObject* cur = (mRoot ? mRoot.get() : this);
if(aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
{
return cur;
}
nsProxyEventObject* cur = mRoot;
do
{
if(aIID.Equals(GetIID()))
if(aIID.Equals(GetClass()->GetProxiedIID()))
{
return cur;
}
} while(NULL != (cur = cur->mNext));
@ -245,11 +359,13 @@ nsProxyEventObject::Find(REFNSIID aIID)
NS_IMETHODIMP
nsProxyEventObject::GetInterfaceInfo(nsIInterfaceInfo** info)
{
NS_ENSURE_ARG_POINTER(info);
NS_ASSERTION(GetClass(), "proxy without class");
NS_ASSERTION(GetClass()->GetInterfaceInfo(), "proxy class without interface");
if(!(*info = GetClass()->GetInterfaceInfo()))
return NS_ERROR_UNEXPECTED;
NS_ADDREF(*info);
return NS_OK;
}
@ -259,7 +375,10 @@ nsProxyEventObject::CallMethod(PRUint16 methodIndex,
const nsXPTMethodInfo* info,
nsXPTCMiniVariant * params)
{
return mProxyObject->Post(methodIndex, (nsXPTMethodInfo*)info, params, GetClass()->GetInterfaceInfo());
if (mProxyObject)
return mProxyObject->Post(methodIndex, (nsXPTMethodInfo*)info, params, GetClass()->GetInterfaceInfo());
return NS_ERROR_NULL_POINTER;
}
@ -278,6 +397,3 @@ nsProxyEventObject::CallMethod(PRUint16 methodIndex,

Просмотреть файл

@ -26,6 +26,7 @@
#include "nscore.h"
#include "nsISupports.h"
#include "nsIFactory.h"
#include "nsHashtable.h"
#include "plevent.h"
#include "xptcall.h" // defines nsXPTCVariant
@ -48,28 +49,44 @@ class nsProxyEventClass;
{ 0xeea90d45, 0xb059, 0x11d2, \
{ 0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33 } }
#define NS_PROXYEVENT_OBJECT_IID \
{ 0xec373590, 0x9164, 0x11d3, \
{0x8c, 0x73, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} }
static NS_DEFINE_IID(kProxyEventClassIID, NS_PROXYEVENT_CLASS_IID);
static NS_DEFINE_IID(kProxyEventObjectIID, NS_PROXYEVENT_OBJECT_IID);
class nsProxyEventClass : public nsISupports
{
public:
// all the interface method declarations...
NS_DECL_ISUPPORTS
NS_IMETHOD DelegatedQueryInterface(nsProxyEventObject* self, REFNSIID aIID, void** aInstancePtr);
static const nsIID& GetIID() {static nsIID iid = kProxyEventClassIID; return iid;}
static nsProxyEventClass* GetNewOrUsedClass(REFNSIID aIID);
NS_IMETHOD DelegatedQueryInterface( nsProxyEventObject* self,
REFNSIID aIID,
void** aInstancePtr);
REFNSIID GetIID() const {return mIID;}
nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
nsresult CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID aIID, nsProxyEventObject** aInstancePtr);
const nsIID& GetProxiedIID() const {return mIID; }
protected:
nsProxyEventClass();
nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo);
virtual ~nsProxyEventClass();
private:
nsIInterfaceInfo* mInfo;
nsIID mIID;
uint32* mDescriptors;
nsIID mIID;
nsCOMPtr<nsIInterfaceInfo> mInfo;
uint32* mDescriptors;
nsresult CallQueryInterfaceOnProxy(nsProxyEventObject* self,
REFNSIID aIID,
nsProxyEventObject** aInstancePtr);
};
@ -79,42 +96,53 @@ class nsProxyEventObject : public nsXPTCStubBase
public:
NS_DECL_ISUPPORTS
NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info);
// call this method and return result
NS_IMETHOD CallMethod(PRUint16 methodIndex, const nsXPTMethodInfo* info, nsXPTCMiniVariant* params);
static const nsIID& GetIID() {static nsIID iid = kProxyEventObjectIID; return iid;}
static nsProxyEventObject* GetNewOrUsedProxy(nsIEventQueue *destQueue,
PRInt32 proxyType,
nsISupports *aObj,
REFNSIID aIID);
static PRUint32 GetProxyHashKey( nsISupports *rootProxy,
nsIEventQueue *destQueue,
PRInt32 proxyType);
NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info);
// call this method and return result
NS_IMETHOD CallMethod(PRUint16 methodIndex, const nsXPTMethodInfo* info, nsXPTCMiniVariant* params);
REFNSIID GetIID() const { return GetClass()->GetIID();}
nsProxyEventClass* GetClass() const { return mClass; }
nsIEventQueue* GetQueue() const { return mProxyObject->GetQueue(); }
nsISupports* GetRealObject() const { return mProxyObject->GetRealObject(); }
nsIEventQueue* GetQueue() const { return (mProxyObject ? mProxyObject->GetQueue() : nsnull);}
nsISupports* GetRealObject() const { return (mProxyObject ? mProxyObject->GetRealObject(): nsnull);}
PRInt32 GetProxyType() const { return (mProxyObject ? mProxyObject->GetProxyType() : nsnull);}
protected:
virtual ~nsProxyEventObject();
nsProxyEventObject();
nsProxyEventObject(nsIEventQueue *destQueue,
PRInt32 proxyType,
nsISupports* aObj,
nsProxyEventClass* aClass,
nsProxyEventObject* root);
nsProxyEventObject* root,
PRUint32 hashValue);
virtual ~nsProxyEventObject();
nsProxyEventObject* Find(REFNSIID aIID);
private:
nsresult RootRemoval();
#ifdef DEBUG_dougt
void DebugDump(const char * message, PRUint32 hashKey);
#endif
nsProxyObject* mProxyObject;
nsProxyEventClass* mClass;
nsProxyEventObject* mRoot;
protected:
nsVoidKey mHashKey;
nsCOMPtr<nsProxyObject> mProxyObject;
nsCOMPtr<nsProxyEventClass> mClass;
nsCOMPtr<nsProxyEventObject> mRoot;
nsProxyEventObject* mNext;
};

Просмотреть файл

@ -81,16 +81,6 @@ NS_IMETHODIMP nsProxyCreateInstance::CreateInstanceByProgID(const char *aProgID,
result);
}
/////////////////////////////////////////////////////////////////////////
// nsProxyObjectManager
/////////////////////////////////////////////////////////////////////////
@ -185,25 +175,12 @@ nsProxyObjectManager::GetProxyObject(nsIEventQueue *destQueue, REFNSIID aIID, ns
}
}
nsISupports* realObject;
// we need to do make sure that we addref the passed in object as well as ensure
// that it is of the requested IID;
rv = aObj->QueryInterface(aIID, (void**)&realObject);
if ( NS_FAILED( rv ) )
return rv;
// check to see if proxy is there or not.
*aProxyObject = nsProxyEventObject::GetNewOrUsedProxy(postQ, proxyType, realObject, aIID);
*aProxyObject = nsProxyEventObject::GetNewOrUsedProxy(postQ, proxyType, aObj, aIID);
if (*aProxyObject == nsnull)
{
NS_RELEASE(aObj);
return NS_ERROR_NO_INTERFACE; //fix error code?
}
return NS_ERROR_NO_INTERFACE; //fix error code?
return NS_OK;
}