Adding "Fire And Forget" async method calling.

Added Create() function for the generic factory.
Made ProxyObject into an nsISupports Object for refcounting.
Fixed proxytest to work in the new xpcom2 world.
This commit is contained in:
dougt%netscape.com 1999-05-28 22:15:20 +00:00
Родитель 6369bae2ff
Коммит 29aaa9fa9b
8 изменённых файлов: 250 добавлений и 119 удалений

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

@ -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 *); \

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

@ -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;
};

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

@ -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;
}

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

@ -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;

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

@ -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);
}

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

@ -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;

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

@ -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.

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

@ -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;