diff --git a/xpcom/proxy/public/nsProxyEvent.h b/xpcom/proxy/public/nsProxyEvent.h index 146221bc23e6..cad46d198637 100644 --- a/xpcom/proxy/public/nsProxyEvent.h +++ b/xpcom/proxy/public/nsProxyEvent.h @@ -26,13 +26,35 @@ #include "plevent.h" #include "xptcall.h" + +typedef enum +{ + PROXY_SYNC = 0, // act just like a function call. + PROXY_ASYNC // fire and forget. This will return immediately and you will lose all return information. -class NS_EXPORT nsProxyObject +} ProxyType; + + + +// Using the ISupports interface just for addrefing. + +#define NS_PROXYOBJECT_CID \ +{ 0xeea90d40, \ + 0xb09f, \ + 0x11d2, \ + {0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33}\ +} + + +class nsProxyObject : public nsISupports { public: + + NS_DECL_ISUPPORTS + nsProxyObject(); - nsProxyObject(PLEventQueue *destQueue, nsISupports *realObject); - nsProxyObject(PLEventQueue *destQueue, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID); + nsProxyObject(PLEventQueue *destQueue, ProxyType proxyType, nsISupports *realObject); + nsProxyObject(PLEventQueue *destQueue, ProxyType proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID); virtual ~nsProxyObject(); @@ -42,33 +64,53 @@ class NS_EXPORT nsProxyObject nsXPTCVariant *params); - nsresult GetLastResult() const { return mResult; } nsISupports* GetRealObject() const { return mRealObject; } - PRUint32 GetMethodIndex() const { return mMethodIndex; } - PRUint32 GetParameterCount() const { return mParameterCount; } - nsXPTCVariant* GetParameterList() const { return mParameterList; } PLEventQueue* GetQueue() const { return mDestQueue; } - - - - // These are called from PLEvent. They must be public. You should not use them. + ProxyType GetProxyType() const { return mProxyType; } - static void* EventHandler(PLEvent *self); - static void DestroyHandler(PLEvent *self); - void InvokeMethod(void); private: PLEventQueue *mDestQueue; /* destination queue */ nsISupports *mRealObject; /* the non-proxy object that this event is referring to */ + PRBool mRealObjectOwned; + ProxyType mProxyType; + + }; + + +class NS_EXPORT nsProxyObjectCallInfo +{ +public: + + nsProxyObjectCallInfo(nsProxyObject* owner, + PRUint32 methodIndex, + nsXPTCVariant* parameterList, + PRUint32 parameterCount, + PLEvent *event); + + virtual ~nsProxyObjectCallInfo(); + + PRUint32 GetMethodIndex() const { return mMethodIndex; } + + nsXPTCVariant* GetParameterList() const { return mParameterList; } + PRUint32 GetParameterCount() const { return mParameterCount; } + PLEvent* GetPLEvent() const { return mEvent; } + nsresult GetResult() const { return mResult; } + nsProxyObject* GetProxyObject() const { return mOwner; } + void SetResult(nsresult rv) {mResult = rv; } + +private: + + nsProxyObject *mOwner; + nsresult mResult; /* this is the return result of the called function */ + PRUint32 mMethodIndex; /* which method to be called? */ + nsXPTCVariant *mParameterList; /* marshalled in parameter buffer */ + PRUint32 mParameterCount; /* number of params */ + PLEvent *mEvent; /* the current plevent */ - PRUint32 mMethodIndex; /* which method to be called? */ - nsresult mResult; /* this is the return result of the called function */ - PRUint32 mParameterCount; /* number of params */ - nsXPTCVariant *mParameterList; /* marshalled in parameter buffer */ }; - #define NS_DECL_PROXY(_class, _interface) \ public: \ _class(PLEventQueue *, _interface *); \ diff --git a/xpcom/proxy/public/nsProxyObjectManager.h b/xpcom/proxy/public/nsProxyObjectManager.h index 7b8d13627a58..89391139e04e 100644 --- a/xpcom/proxy/public/nsProxyObjectManager.h +++ b/xpcom/proxy/public/nsProxyObjectManager.h @@ -54,7 +54,8 @@ } - +#define NS_XPCOMPROXY_PROGID "component://netscape/xpcomproxy" +#define NS_XPCOMPROXY_CLASSNAME "XPCom Proxy" //////////////////////////////////////////////////////////////////////////////// // nsProxyEventFactory: @@ -89,12 +90,14 @@ public: NS_IMETHOD GetProxyObject(PLEventQueue *destQueue, REFNSIID aIID, nsISupports* aObj, + ProxyType proxyType, void** aProxyObject) = 0; NS_IMETHOD GetProxyObject(PLEventQueue *destQueue, const nsCID &aClass, nsISupports *aDelegate, - const nsIID &aIID, + const nsIID &aIID, + ProxyType proxyType, void** aProxyObject) = 0; }; diff --git a/xpcom/proxy/src/nsProxyEvent.cpp b/xpcom/proxy/src/nsProxyEvent.cpp index b1b5d61201ee..d72495ff71df 100644 --- a/xpcom/proxy/src/nsProxyEvent.cpp +++ b/xpcom/proxy/src/nsProxyEvent.cpp @@ -23,28 +23,71 @@ #include "nsRepository.h" -nsProxyObject::nsProxyObject() + +static void* EventHandler(PLEvent *self); +static void DestroyHandler(PLEvent *self); + +nsProxyObjectCallInfo::nsProxyObjectCallInfo(nsProxyObject* owner, + PRUint32 methodIndex, + nsXPTCVariant* parameterList, + PRUint32 parameterCount, + PLEvent *event) { - mRealObjectOwned = PR_FALSE; - mRealObject = nsnull; - mDestQueue = nsnull; + mOwner = owner; + mMethodIndex = methodIndex; + mParameterList = parameterList; + mParameterCount = parameterCount; + mEvent = event; } -nsProxyObject::nsProxyObject(PLEventQueue *destQueue, nsISupports *realObject) +nsProxyObjectCallInfo::~nsProxyObjectCallInfo() { + PR_FREEIF(mEvent); + + if (mParameterList) + free( (void*) mParameterList); +} + + +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +NS_IMPL_ISUPPORTS(nsProxyObject, kISupportsIID) + + +nsProxyObject::nsProxyObject() +{ + NS_INIT_REFCNT(); + NS_ADDREF_THIS(); + + mRealObjectOwned = PR_FALSE; + mRealObject = nsnull; + mDestQueue = nsnull; + mProxyType = PROXY_SYNC; +} + + +nsProxyObject::nsProxyObject(PLEventQueue *destQueue, ProxyType proxyType, nsISupports *realObject) +{ + NS_INIT_REFCNT(); + NS_ADDREF_THIS(); + mRealObjectOwned = PR_FALSE; mRealObject = realObject; mDestQueue = destQueue; + mProxyType = proxyType; mRealObject->AddRef(); } -nsProxyObject::nsProxyObject(PLEventQueue *destQueue, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID) +nsProxyObject::nsProxyObject(PLEventQueue *destQueue, ProxyType proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID) { + NS_INIT_REFCNT(); + NS_ADDREF_THIS(); + mRealObjectOwned = PR_TRUE; mDestQueue = destQueue; + mProxyType = proxyType; nsresult rv = nsComponentManager::CreateInstance(aClass, aDelegate, @@ -58,8 +101,6 @@ nsProxyObject::nsProxyObject(PLEventQueue *destQueue, const nsCID &aClass, nsIS } } - - nsProxyObject::~nsProxyObject() { PL_ENTER_EVENT_QUEUE_MONITOR(mDestQueue); @@ -81,66 +122,92 @@ nsProxyObject::Post( PRUint32 methodIndex, /* which method to PRUint32 paramCount, /* number of params */ nsXPTCVariant *params) { - + PL_ENTER_EVENT_QUEUE_MONITOR(mDestQueue); - + + NS_ASSERTION(mRealObject, "no native object"); + + NS_ADDREF_THIS(); // so that our destructor does not pull out from under us. This will be released in the DestroyHandler() + PLEvent *event = PR_NEW(PLEvent); - if (event == NULL) + + if (event == nsnull) { PL_EXIT_EVENT_QUEUE_MONITOR(mDestQueue); return NS_ERROR_OUT_OF_MEMORY; } + + nsProxyObjectCallInfo *info = new nsProxyObjectCallInfo(this, methodIndex, params, paramCount, event); - NS_ASSERTION(mRealObject, "no native object"); PL_InitEvent(event, - this, - nsProxyObject::EventHandler, - nsProxyObject::DestroyHandler); - - - mMethodIndex = methodIndex; - mParameterCount = paramCount; - mParameterList = params; - - PL_PostSynchronousEvent(mDestQueue, (PLEvent *)event); - - PL_EXIT_EVENT_QUEUE_MONITOR(mDestQueue); - - PR_FREEIF(event); - - return mResult; -} - - - -void -nsProxyObject::InvokeMethod() -{ - // invoke the magic of xptc... - PL_ENTER_EVENT_QUEUE_MONITOR(mDestQueue); - - mResult = XPTC_InvokeByIndex( mRealObject, - mMethodIndex, - mParameterCount, - mParameterList); - - PL_EXIT_EVENT_QUEUE_MONITOR(mDestQueue); -} - - - -void nsProxyObject::DestroyHandler(PLEvent *self) {} - - -void* nsProxyObject::EventHandler(PLEvent *self) -{ - nsProxyObject* proxyObject = (nsProxyObject*)PL_GetEventOwner(self); - - if (proxyObject != nsnull) + info, + EventHandler, + DestroyHandler); + + if (mProxyType == PROXY_SYNC) { - proxyObject->InvokeMethod(); - } + PL_PostSynchronousEvent(mDestQueue, event); + + nsresult rv = info->GetResult(); + + delete info; + + PL_EXIT_EVENT_QUEUE_MONITOR(mDestQueue); + + return rv; + + } + else if (mProxyType == PROXY_ASYNC) + { + PL_PostEvent(mDestQueue, event); + + PL_EXIT_EVENT_QUEUE_MONITOR(mDestQueue); + + return NS_OK; + } + + PL_EXIT_EVENT_QUEUE_MONITOR(mDestQueue); + return NS_ERROR_UNEXPECTED; + +} + + +void DestroyHandler(PLEvent *self) +{ + nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self); + nsProxyObject* proxyObject = owner->GetProxyObject(); + + if (proxyObject->GetProxyType() == PROXY_ASYNC) + { + delete owner; + } + + // decrement once since we increased it during the Post() + proxyObject->Release(); +} + +void* EventHandler(PLEvent *self) +{ + nsProxyObjectCallInfo *info = (nsProxyObjectCallInfo*)PL_GetEventOwner(self); + nsProxyObject *proxyObject = info->GetProxyObject(); + PLEventQueue *eventQ = proxyObject->GetQueue(); + + if (info != nsnull) + { + + PL_ENTER_EVENT_QUEUE_MONITOR(eventQ); + + // invoke the magic of xptc... + nsresult rv = XPTC_InvokeByIndex( proxyObject->GetRealObject(), + info->GetMethodIndex(), + info->GetParameterCount(), + info->GetParameterList()); + + info->SetResult(rv); + + PL_EXIT_EVENT_QUEUE_MONITOR(eventQ); + } return NULL; } diff --git a/xpcom/proxy/src/nsProxyEventClass.cpp b/xpcom/proxy/src/nsProxyEventClass.cpp index 4b82a8570e05..473db5b63652 100644 --- a/xpcom/proxy/src/nsProxyEventClass.cpp +++ b/xpcom/proxy/src/nsProxyEventClass.cpp @@ -201,7 +201,7 @@ nsProxyEventClass::CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID if (rv == NS_OK) { - nsProxyEventObject* proxyObj = nsProxyEventObject::GetNewOrUsedProxy(self->GetQueue(), aInstancePtr, aIID); + nsProxyEventObject* proxyObj = nsProxyEventObject::GetNewOrUsedProxy(self->GetQueue(), PROXY_SYNC, aInstancePtr, aIID); if(proxyObj) { return proxyObj; diff --git a/xpcom/proxy/src/nsProxyEventObject.cpp b/xpcom/proxy/src/nsProxyEventObject.cpp index 202d3ebfa37e..80088101c1bc 100644 --- a/xpcom/proxy/src/nsProxyEventObject.cpp +++ b/xpcom/proxy/src/nsProxyEventObject.cpp @@ -37,8 +37,9 @@ nsProxyEventObject* nsProxyEventObject::GetNewOrUsedProxy(PLEventQueue *destQueue, - nsISupports *aObj, - REFNSIID aIID) + ProxyType proxyType, + nsISupports *aObj, + REFNSIID aIID) { nsProxyEventObject* proxy = NULL; nsProxyEventObject* root = NULL; @@ -84,7 +85,7 @@ nsProxyEventObject::GetNewOrUsedProxy(PLEventQueue *destQueue, if (aObj == rootObject) { // the root will do double duty as the interface wrapper - proxy = root = new nsProxyEventObject(destQueue, aObj, clazz, nsnull); + proxy = root = new nsProxyEventObject(destQueue, proxyType, aObj, clazz, nsnull); if(root) realToProxyMap->Put(&key, root); goto return_wrapper; @@ -98,7 +99,7 @@ nsProxyEventObject::GetNewOrUsedProxy(PLEventQueue *destQueue, goto return_wrapper; } - root = new nsProxyEventObject(destQueue, rootObject, rootClazz, nsnull); + root = new nsProxyEventObject(destQueue, proxyType, rootObject, rootClazz, nsnull); NS_RELEASE(rootClazz); if(!root) @@ -114,7 +115,7 @@ nsProxyEventObject::GetNewOrUsedProxy(PLEventQueue *destQueue, if(!proxy) { - proxy = new nsProxyEventObject(destQueue, aObj, clazz, root); + proxy = new nsProxyEventObject(destQueue, proxyType, aObj, clazz, root); if(!proxy) { goto return_wrapper; @@ -147,6 +148,7 @@ return_wrapper: nsProxyEventObject::nsProxyEventObject(PLEventQueue *destQueue, + ProxyType proxyType, nsISupports* aObj, nsProxyEventClass* aClass, nsProxyEventObject* root) @@ -154,7 +156,7 @@ nsProxyEventObject::nsProxyEventObject(PLEventQueue *destQueue, mNext(NULL) { mRoot = (root ? root : this); - mProxyObject = new nsProxyObject(destQueue, aObj); + mProxyObject = new nsProxyObject(destQueue, proxyType, aObj); NS_INIT_REFCNT(); NS_ADDREF_THIS(); @@ -178,7 +180,7 @@ nsProxyEventObject::~nsProxyEventObject() } if (mProxyObject != nsnull) - delete mProxyObject; + mProxyObject->Release(); NS_RELEASE(mClass); @@ -271,19 +273,16 @@ nsProxyEventObject::CallMethod(PRUint16 methodIndex, uint8 paramCount = info->GetParamCount(); nsXPTCVariant *fullParam = (nsXPTCVariant*)malloc(sizeof(nsXPTCVariant) * paramCount); - + for (int index = 0; index < paramCount; index++) { fullParam[index].flags = 0; fullParam[index].val = params[index].val; } + + // fullParam will be deleted inside the mProxyObject - nsresult rv = mProxyObject->Post(methodIndex, paramCount, fullParam); - - if (fullParam) - free( (void*) fullParam); - - return rv; + return mProxyObject->Post(methodIndex, paramCount, fullParam); } diff --git a/xpcom/proxy/src/nsProxyEventPrivate.h b/xpcom/proxy/src/nsProxyEventPrivate.h index 1d98bb190748..2f282f564bab 100644 --- a/xpcom/proxy/src/nsProxyEventPrivate.h +++ b/xpcom/proxy/src/nsProxyEventPrivate.h @@ -83,8 +83,9 @@ public: static nsProxyEventObject* GetNewOrUsedProxy(PLEventQueue *destQueue, - nsISupports *aObj, - REFNSIID aIID); + ProxyType proxyType, + nsISupports *aObj, + REFNSIID aIID); PLEventQueue* GetQueue() const { return mProxyObject->GetQueue(); } @@ -101,6 +102,7 @@ public: private: nsProxyEventObject(); // not implemented nsProxyEventObject(PLEventQueue *destQueue, + ProxyType proxyType, nsISupports* aObj, nsProxyEventClass* aClass, nsProxyEventObject* root); @@ -130,13 +132,23 @@ public: NS_IMETHOD GetProxyObject(PLEventQueue *destQueue, REFNSIID aIID, nsISupports* aObj, + ProxyType proxyType, void** aProxyObject); NS_IMETHOD GetProxyObject(PLEventQueue *destQueue, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID, + ProxyType proxyType, void** aProxyObject); + + + + // Helpers + static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + + + nsProxyObjectManager(); virtual ~nsProxyObjectManager(); @@ -144,7 +156,8 @@ public: nsHashtable *GetRealObjectToProxyObjectMap(); nsHashtable *GetIIDToProxyClassMap(); - + + private: static nsProxyObjectManager* mInstance; diff --git a/xpcom/proxy/src/nsProxyObjectManager.cpp b/xpcom/proxy/src/nsProxyObjectManager.cpp index 6450e1c2d2fd..beb664a40844 100644 --- a/xpcom/proxy/src/nsProxyObjectManager.cpp +++ b/xpcom/proxy/src/nsProxyObjectManager.cpp @@ -122,15 +122,27 @@ nsProxyObjectManager::GetInstance() } +// Helpers +NS_IMETHODIMP +nsProxyObjectManager::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr) +{ + nsProxyObjectManager *proxyObjectManager = GetInstance(); + + if (proxyObjectManager == NULL) + return NS_ERROR_OUT_OF_MEMORY; + + return proxyObjectManager->QueryInterface(aIID, aInstancePtr); +} + NS_IMETHODIMP -nsProxyObjectManager::GetProxyObject(PLEventQueue *destQueue, REFNSIID aIID, nsISupports* aObj, void** aProxyObject) +nsProxyObjectManager::GetProxyObject(PLEventQueue *destQueue, REFNSIID aIID, nsISupports* aObj, ProxyType proxyType, void** aProxyObject) { *aProxyObject = nsnull; // check to see if proxy is there or not. - *aProxyObject = nsProxyEventObject::GetNewOrUsedProxy(destQueue, aObj, aIID); + *aProxyObject = nsProxyEventObject::GetNewOrUsedProxy(destQueue, proxyType, aObj, aIID); if (*aProxyObject != nsnull) { return NS_OK; @@ -145,6 +157,7 @@ nsProxyObjectManager::GetProxyObject(PLEventQueue *destQueue, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID, + ProxyType proxyType, void** aProxyObject) { *aProxyObject = nsnull; @@ -157,7 +170,7 @@ nsProxyObjectManager::GetProxyObject(PLEventQueue *destQueue, if (ciObject == nsnull) return NS_ERROR_NULL_POINTER; - nsresult rv = GetProxyObject(destQueue, nsIProxyCreateInstance::GetIID(), ciObject, (void**)&ciProxy); + nsresult rv = GetProxyObject(destQueue, nsIProxyCreateInstance::GetIID(), ciObject, PROXY_SYNC, (void**)&ciProxy); if (NS_FAILED(rv)) { @@ -189,7 +202,7 @@ nsProxyObjectManager::GetProxyObject(PLEventQueue *destQueue, // 5. Now create a proxy object for the requested object. - rv = GetProxyObject(destQueue, aIID, aObj, aProxyObject); + rv = GetProxyObject(destQueue, aIID, aObj, proxyType, aProxyObject); // 6. release ownership of aObj so that aProxyObject owns it. diff --git a/xpcom/proxy/tests/proxytests.cpp b/xpcom/proxy/tests/proxytests.cpp index 76e541bc5df6..70964164495e 100644 --- a/xpcom/proxy/tests/proxytests.cpp +++ b/xpcom/proxy/tests/proxytests.cpp @@ -77,7 +77,7 @@ static NS_DEFINE_IID(kIAllocatorIID, NS_IALLOCATOR_IID); static NS_DEFINE_IID(kAllocatorCID, NS_ALLOCATOR_CID); #ifdef XP_PC -#define XPCOM_DLL "xpcom32.dll" +#define XPCOM_DLL "xpcom.dll" #else #ifdef XP_MAC #define XPCOM_DLL "XPCOM_DLL" @@ -87,18 +87,6 @@ static NS_DEFINE_IID(kAllocatorCID, NS_ALLOCATOR_CID); #endif -#ifdef XP_PC -#define LIBPROXY_DLL "libproxy.dll" -#else -#ifdef XP_MAC -#define LIBPROXY_DLL "LIBPROXY_DLL" -#else -#define LIBPROXY_DLL "libproxy.so" -#endif -#endif - - - /***************************************************************************/ extern "C" void NS_SetupRegistry() @@ -134,7 +122,7 @@ NS_SetupRegistry() nsComponentManager::RegisterComponent(kAllocatorCID, NULL, NULL, XPCOM_DLL, PR_FALSE, PR_FALSE); - nsComponentManager::RegisterComponent(kProxyObjectManagerCID, NULL, NULL, LIBPROXY_DLL, + nsComponentManager::RegisterComponent(kProxyObjectManagerCID, NULL, NULL, XPCOM_DLL, PR_FALSE, PR_FALSE); } @@ -260,6 +248,8 @@ void TestCase_TwoClassesOneInterface(void *arg) nsIProxyObjectManager::GetIID(), (void**)&proxyObjectFactory); + printf("ProxyObjectManager: %x ", proxyObjectFactory); + PR_ASSERT(proxyObjectFactory); nsITestXPCFoo *proxyObject; @@ -272,9 +262,9 @@ void TestCase_TwoClassesOneInterface(void *arg) PR_ASSERT(foo); PR_ASSERT(foo2); - proxyObjectFactory->GetProxyObject(argsStruct->queue, nsITestXPCFoo::GetIID(), foo, (void**)&proxyObject); + proxyObjectFactory->GetProxyObject(argsStruct->queue, nsITestXPCFoo::GetIID(), foo, PROXY_ASYNC, (void**)&proxyObject); - proxyObjectFactory->GetProxyObject(argsStruct->queue, nsITestXPCFoo::GetIID(), foo2, (void**)&proxyObject2); + proxyObjectFactory->GetProxyObject(argsStruct->queue, nsITestXPCFoo::GetIID(), foo2, PROXY_ASYNC, (void**)&proxyObject2); if (proxyObject && proxyObject2) { @@ -314,6 +304,8 @@ void TestCase_TwoClassesOneInterface(void *arg) //printf("Deleting Proxy Object 2 (%ld)\n", threadNumber ); NS_RELEASE(proxyObject2); } + + PR_Sleep( PR_MillisecondsToInterval(10000) ); } @@ -341,6 +333,7 @@ void TestCase_2(void *arg) nsITestXPCFoo::GetIID(), // should be a cid nsnull, nsITestXPCFoo::GetIID(), + PROXY_SYNC, (void**)&proxyObject); if (proxyObject != nsnull) @@ -364,7 +357,7 @@ void TestCase_2(void *arg) static void PR_CALLBACK ProxyTest( void *arg ) { TestCase_TwoClassesOneInterface(arg); - TestCase_2(arg); + // TestCase_2(arg); free((void*) arg); } @@ -447,7 +440,8 @@ main(int argc, char **argv) printf("All Threads Spawned.\n\n"); - printf("Wait for threads.\n"); + + printf("Wait for threads.\n"); for (PRInt32 i = 0; i < numberOfThreads; i++) { PRStatus rv;