mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-06 06:22:33 +00:00
Added a nested event loop instead of blocking during sync calls. Partial fix
for bug 13724. (I still must remove ifdef's for the autoproxy code.) r=brendan@meer.net.
This commit is contained in:
parent
a0d87839ca
commit
448861e47a
@ -24,43 +24,43 @@
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NS_WITH_PROXIED_SERVICE: macro to make using services that need to be proxied
|
||||
// before using them easier.
|
||||
// before using them easier.
|
||||
// Now you can replace this:
|
||||
// {
|
||||
// nsresult rv;
|
||||
// NS_WITH_SERVICE(nsIMyService, pIMyService, kMyServiceCID, &rv);
|
||||
// if(NS_FAILED(rv))
|
||||
// return;
|
||||
// NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv);
|
||||
// if(NS_FAILED(rv))
|
||||
// return;
|
||||
// nsIMyService pIProxiedObject = NULL;
|
||||
// rv = pIProxyObjectManager->GetProxyObject(pIProxyQueue,
|
||||
// nsIMyService::GetIID(),
|
||||
// pIMyService, PROXY_SYNC,
|
||||
// (void**)&pIProxiedObject);
|
||||
// pIProxiedObject->DoIt(...); // Executed on same thread as pIProxyQueue
|
||||
// ...
|
||||
// pIProxiedObject->Release(); // Must be done as not managed for you.
|
||||
// }
|
||||
// with this:
|
||||
// {
|
||||
// nsresult rv;
|
||||
// NS_WITH_PROXIED_SERVICE(nsIMyService, pIMyService, kMyServiceCID,
|
||||
// pIProxyQueue, &rv);
|
||||
// if(NS_FAILED(rv))
|
||||
// return;
|
||||
// pIMyService->DoIt(...); // Executed on the same thread as pIProxyQueue
|
||||
// }
|
||||
// nsresult rv;
|
||||
// NS_WITH_SERVICE(nsIMyService, pIMyService, kMyServiceCID, &rv);
|
||||
// if(NS_FAILED(rv))
|
||||
// return;
|
||||
// NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv);
|
||||
// if(NS_FAILED(rv))
|
||||
// return;
|
||||
// nsIMyService pIProxiedObject = NULL;
|
||||
// rv = pIProxyObjectManager->GetProxyObject(pIProxyQueue,
|
||||
// nsIMyService::GetIID(),
|
||||
// pIMyService, PROXY_SYNC,
|
||||
// (void**)&pIProxiedObject);
|
||||
// pIProxiedObject->DoIt(...); // Executed on same thread as pIProxyQueue
|
||||
// ...
|
||||
// pIProxiedObject->Release(); // Must be done as not managed for you.
|
||||
// }
|
||||
// with this:
|
||||
// {
|
||||
// nsresult rv;
|
||||
// NS_WITH_PROXIED_SERVICE(nsIMyService, pIMyService, kMyServiceCID,
|
||||
// pIProxyQueue, &rv);
|
||||
// if(NS_FAILED(rv))
|
||||
// return;
|
||||
// pIMyService->DoIt(...); // Executed on the same thread as pIProxyQueue
|
||||
// }
|
||||
// and the automatic destructor will take care of releasing the service and
|
||||
// the proxied object for you.
|
||||
//
|
||||
// Note that this macro requires you to link with the xpcom DLL to pick up the
|
||||
// static member functions from nsServiceManager.
|
||||
|
||||
#define NS_WITH_PROXIED_SERVICE(T, var, cid, Q, rvAddr) \
|
||||
nsProxiedService _serv##var(cid, T::GetIID(), Q, rvAddr); \
|
||||
T* var = (T*)(nsISupports*)_serv##var;
|
||||
#define NS_WITH_PROXIED_SERVICE(T, var, cid, Q, rvAddr) \
|
||||
nsProxiedService _serv##var(cid, T::GetIID(), Q, rvAddr); \
|
||||
T* var = (T*)(nsISupports*)_serv##var;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsProxiedService
|
||||
@ -69,60 +69,60 @@
|
||||
class nsProxiedService : public nsService
|
||||
{
|
||||
protected:
|
||||
nsISupports* mProxiedService;
|
||||
nsISupports* mProxiedService;
|
||||
public:
|
||||
nsProxiedService(const nsCID &aClass, const nsIID &aIID,
|
||||
nsIEventQueue* pIProxyQueue, nsresult*rv): nsService(aClass, aIID, rv),
|
||||
mProxiedService(nsnull)
|
||||
{
|
||||
static NS_DEFINE_IID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
|
||||
nsIEventQueue* pIProxyQueue, nsresult*rv): nsService(aClass, aIID, rv),
|
||||
mProxiedService(nsnull)
|
||||
{
|
||||
static NS_DEFINE_IID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
|
||||
|
||||
if(NS_FAILED(*rv))
|
||||
return;
|
||||
NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager,
|
||||
kProxyObjectManagerCID, rv);
|
||||
if(NS_FAILED(*rv))
|
||||
{
|
||||
nsServiceManager::ReleaseService(mCID, mService);
|
||||
mService = nsnull;
|
||||
return;
|
||||
}
|
||||
if(NS_FAILED(*rv))
|
||||
return;
|
||||
NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager,
|
||||
kProxyObjectManagerCID, rv);
|
||||
if(NS_FAILED(*rv))
|
||||
{
|
||||
nsServiceManager::ReleaseService(mCID, mService);
|
||||
mService = nsnull;
|
||||
return;
|
||||
}
|
||||
|
||||
*rv = pIProxyObjectManager->GetProxyObject(pIProxyQueue,
|
||||
aIID,
|
||||
mService,
|
||||
PROXY_SYNC,
|
||||
(void**)&mProxiedService);
|
||||
if(NS_FAILED(*rv))
|
||||
{
|
||||
nsServiceManager::ReleaseService(mCID, mService);
|
||||
mService = nsnull;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
~nsProxiedService()
|
||||
{
|
||||
if(mProxiedService)
|
||||
NS_RELEASE(mProxiedService);
|
||||
// Base class will free mService
|
||||
}
|
||||
*rv = pIProxyObjectManager->GetProxyObject(pIProxyQueue,
|
||||
aIID,
|
||||
mService,
|
||||
PROXY_SYNC,
|
||||
(void**)&mProxiedService);
|
||||
if(NS_FAILED(*rv))
|
||||
{
|
||||
nsServiceManager::ReleaseService(mCID, mService);
|
||||
mService = nsnull;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
~nsProxiedService()
|
||||
{
|
||||
if(mProxiedService)
|
||||
NS_RELEASE(mProxiedService);
|
||||
// Base class will free mService
|
||||
}
|
||||
|
||||
nsISupports* operator->() const
|
||||
{
|
||||
NS_PRECONDITION(mProxiedService != 0, "Your code should test the error result from the constructor.");
|
||||
return mProxiedService;
|
||||
}
|
||||
nsISupports* operator->() const
|
||||
{
|
||||
NS_PRECONDITION(mProxiedService != 0, "Your code should test the error result from the constructor.");
|
||||
return mProxiedService;
|
||||
}
|
||||
|
||||
PRBool operator==(const nsISupports* other)
|
||||
{
|
||||
return ((mProxiedService == other) || (mService == other));
|
||||
}
|
||||
PRBool operator==(const nsISupports* other)
|
||||
{
|
||||
return ((mProxiedService == other) || (mService == other));
|
||||
}
|
||||
|
||||
operator nsISupports*() const
|
||||
{
|
||||
return mProxiedService;
|
||||
}
|
||||
operator nsISupports*() const
|
||||
{
|
||||
return mProxiedService;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -19,15 +19,19 @@
|
||||
#ifndef __nsProxyEvent_h_
|
||||
#define __nsProxyEvent_h_
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIFactory.h"
|
||||
|
||||
#include "nsIEventQueue.h"
|
||||
#include "plevent.h"
|
||||
#include "prtypes.h"
|
||||
#include "xptcall.h"
|
||||
#include "xptinfo.h"
|
||||
|
||||
class nsProxyObjectCallInfo;
|
||||
|
||||
#define PROXY_SYNC 0x0001 // act just like a function call.
|
||||
#define PROXY_ASYNC 0x0002 // fire and forget. This will return immediately and you will lose all return information.
|
||||
#define PROXY_ALWAYS 0x0004 // ignore check to see if the eventQ is on the same thread as the caller, and alway return a proxied object.
|
||||
@ -63,44 +67,50 @@
|
||||
|
||||
class nsProxyObject : public nsISupports
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsCOMTypeInfo<nsISupports>::GetIID())
|
||||
nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject);
|
||||
nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID);
|
||||
|
||||
nsProxyObject();
|
||||
nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject);
|
||||
nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID);
|
||||
virtual ~nsProxyObject();
|
||||
|
||||
|
||||
virtual ~nsProxyObject();
|
||||
nsresult Post(PRUint32 methodIndex, nsXPTMethodInfo *info,
|
||||
nsXPTCMiniVariant *params, nsIInterfaceInfo *interfaceInfo);
|
||||
|
||||
nsresult NestedEventLoop(nsProxyObjectCallInfo *proxyInfo);
|
||||
nsISupports* GetRealObject() const { return mRealObject; }
|
||||
nsIEventQueue* GetQueue();
|
||||
PRInt32 GetProxyType() const { return mProxyType; }
|
||||
|
||||
nsresult Post(PRUint32 methodIndex, nsXPTMethodInfo *info, nsXPTCMiniVariant *params, nsIInterfaceInfo *interfaceInfo);
|
||||
|
||||
nsISupports* GetRealObject() const { return mRealObject; }
|
||||
nsIEventQueue* GetQueue() const { return mDestQueue; }
|
||||
PRInt32 GetProxyType() const { return mProxyType; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
typedef enum
|
||||
{
|
||||
convertOutParameters = 1,
|
||||
convertInParameters,
|
||||
convertAllParameters
|
||||
private:
|
||||
#ifdef AUTOPROXIFICATION
|
||||
typedef enum
|
||||
{
|
||||
convertOutParameters = 1,
|
||||
convertInParameters,
|
||||
convertAllParameters
|
||||
|
||||
} AutoProxyConvertTypes;
|
||||
} AutoProxyConvertTypes;
|
||||
|
||||
#ifdef AUTOPROXIFICATION
|
||||
nsresult AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMiniVariant * params,
|
||||
nsIInterfaceInfo *interfaceInfo, AutoProxyConvertTypes convertType);
|
||||
|
||||
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 */
|
||||
PRBool mRealObjectOwned;
|
||||
PRInt32 mProxyType;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
};
|
||||
@ -119,22 +129,28 @@ public:
|
||||
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; }
|
||||
PRBool GetCompleted();
|
||||
|
||||
void SetResult(nsresult rv) {mResult = rv; }
|
||||
void SetCompleted();
|
||||
|
||||
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 */
|
||||
PRInt32 mCompleted; /* is true when the method has been called. */
|
||||
|
||||
nsCOMPtr<nsProxyObject> mOwner; /* this is the strong referenced nsProxyObject */
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -87,6 +87,7 @@ class nsIProxyObjectManager : public nsISupports
|
||||
{
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_IPROXYEVENT_MANAGER_IID; return iid; }
|
||||
static const nsIID& GetCID() { static nsIID iid = NS_PROXYEVENT_MANAGER_CID; return iid; }
|
||||
|
||||
NS_IMETHOD GetProxyObject(nsIEventQueue *destQueue,
|
||||
REFNSIID aIID,
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "nsProxyEventPrivate.h"
|
||||
#include "nsProxyObjectManager.h"
|
||||
|
||||
#include "pratom.h"
|
||||
#include "prmem.h" // for PR_NEW
|
||||
#include "xptcall.h"
|
||||
|
||||
@ -30,7 +31,7 @@
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIThread.h"
|
||||
|
||||
#include "nsIAtom.h" //hack!
|
||||
#include "nsIAtom.h" //hack! Need a way to define a component as threadsafe (ie. sta).
|
||||
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
@ -43,6 +44,7 @@ nsProxyObjectCallInfo::nsProxyObjectCallInfo(nsProxyObject* owner,
|
||||
PRUint32 parameterCount,
|
||||
PLEvent *event)
|
||||
{
|
||||
mCompleted = 0;
|
||||
mOwner = owner;
|
||||
mMethodIndex = methodIndex;
|
||||
mParameterList = parameterList;
|
||||
@ -59,33 +61,31 @@ nsProxyObjectCallInfo::~nsProxyObjectCallInfo()
|
||||
free( (void*) mParameterList);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS0(nsProxyObject)
|
||||
|
||||
nsProxyObject::nsProxyObject()
|
||||
PRBool
|
||||
nsProxyObjectCallInfo::GetCompleted()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
mRealObjectOwned = PR_FALSE;
|
||||
mRealObject = nsnull;
|
||||
mDestQueue = nsnull;
|
||||
mProxyType = PROXY_SYNC;
|
||||
return (PRBool)mCompleted;
|
||||
}
|
||||
void
|
||||
nsProxyObjectCallInfo::SetCompleted()
|
||||
{
|
||||
PR_AtomicSet(&mCompleted, 1);
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS0(nsProxyObject)
|
||||
|
||||
nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
mRealObjectOwned = PR_FALSE;
|
||||
mRealObject = realObject;
|
||||
mProxyType = proxyType;
|
||||
mDestQueue = destQueue;
|
||||
|
||||
NS_ADDREF(mRealObject);
|
||||
NS_ADDREF(mDestQueue);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -94,45 +94,98 @@ nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
mRealObjectOwned = PR_TRUE;
|
||||
|
||||
nsComponentManager::CreateInstance(aClass,
|
||||
aDelegate,
|
||||
aIID,
|
||||
(void**) &mRealObject);
|
||||
|
||||
mProxyType = proxyType;
|
||||
mDestQueue = destQueue;
|
||||
|
||||
NS_ADDREF(mDestQueue);
|
||||
|
||||
nsresult rv = nsComponentManager::CreateInstance(aClass,
|
||||
aDelegate,
|
||||
aIID,
|
||||
(void**) &mRealObject);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
mRealObjectOwned = PR_FALSE;
|
||||
mRealObject = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
nsProxyObject::~nsProxyObject()
|
||||
{
|
||||
if (mDestQueue)
|
||||
mDestQueue->EnterMonitor();
|
||||
// FIX! mDestQueue->RevokeEvents(this);
|
||||
|
||||
if(mRealObject != nsnull)
|
||||
{
|
||||
if (!mRealObjectOwned)
|
||||
NS_RELEASE(mRealObject);
|
||||
else
|
||||
NS_RELEASE(mRealObject);
|
||||
}
|
||||
|
||||
if (mDestQueue)
|
||||
mDestQueue->ExitMonitor();
|
||||
|
||||
if (mDestQueue != nsnull)
|
||||
NS_RELEASE(mDestQueue);
|
||||
|
||||
if(mRealObject)
|
||||
NS_RELEASE(mRealObject);
|
||||
}
|
||||
|
||||
|
||||
nsIEventQueue*
|
||||
nsProxyObject::GetQueue()
|
||||
{
|
||||
if (mDestQueue)
|
||||
NS_ADDREF(mDestQueue);
|
||||
return mDestQueue;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsProxyObject::NestedEventLoop(nsProxyObjectCallInfo *proxyInfo)
|
||||
{
|
||||
if (proxyInfo == nsnull) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PLEvent* event = proxyInfo->GetPLEvent();
|
||||
PRBool eventLoopCreated = PR_FALSE;
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsIEventQueue *eventQ;
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
eventLoopCreated = PR_TRUE;
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
while (! proxyInfo->GetCompleted())
|
||||
{
|
||||
rv = eventQ->GetEvent(&event);
|
||||
if (NS_FAILED(rv)) break;
|
||||
eventQ->HandleEvent(event);
|
||||
}
|
||||
|
||||
NS_RELEASE(eventQ);
|
||||
|
||||
if (eventLoopCreated)
|
||||
eventQService->DestroyThreadEventQueue();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsProxyObject::convertMiniVariantToVariant(nsXPTMethodInfo *methodInfo, nsXPTCMiniVariant * params, nsXPTCVariant **fullParam, uint8 *paramCount)
|
||||
{
|
||||
uint8 pCount = methodInfo->GetParamCount();
|
||||
|
||||
*fullParam = (nsXPTCVariant*)malloc(sizeof(nsXPTCVariant) * pCount);
|
||||
|
||||
if (*fullParam == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
for (int i = 0; i < pCount; i++)
|
||||
(*fullParam)[i].Init(params[i], methodInfo->GetParam(i).GetType());
|
||||
|
||||
*paramCount = pCount;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMiniVariant * params, nsIInterfaceInfo *interfaceInfo)
|
||||
{
|
||||
@ -144,9 +197,14 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi
|
||||
if (mRealObject == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
||||
if (methodInfo->IsNotXPCOM())
|
||||
return NS_ERROR_PROXY_INVALID_IN_PARAMETER;
|
||||
|
||||
PLEvent *event = PR_NEW(PLEvent);
|
||||
|
||||
if (event == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Auto-proxification
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
@ -158,33 +216,19 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// convert the nsXPTCMiniVariant to a nsXPTCVariant
|
||||
|
||||
uint8 paramCount = methodInfo->GetParamCount();
|
||||
|
||||
nsXPTCVariant *fullParam = (nsXPTCVariant*)malloc(sizeof(nsXPTCVariant) * paramCount);
|
||||
nsXPTCVariant *fullParam;
|
||||
uint8 paramCount;
|
||||
rv = convertMiniVariantToVariant(methodInfo, params, &fullParam, ¶mCount);
|
||||
|
||||
for (int i = 0; i < paramCount; i++)
|
||||
fullParam[i].Init(params[i], methodInfo->GetParam(i).GetType());
|
||||
|
||||
mDestQueue->EnterMonitor();
|
||||
|
||||
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 == nsnull)
|
||||
{
|
||||
mDestQueue->ExitMonitor();
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsProxyObjectCallInfo *proxyInfo = new nsProxyObjectCallInfo(this, methodIndex, fullParam, paramCount, event);
|
||||
|
||||
if (proxyInfo == nsnull)
|
||||
{
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
PL_InitEvent(event,
|
||||
proxyInfo,
|
||||
@ -193,7 +237,22 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi
|
||||
|
||||
if (mProxyType & PROXY_SYNC)
|
||||
{
|
||||
mDestQueue->PostSynchronousEvent(event, nsnull);
|
||||
PRBool callDirectly;
|
||||
mDestQueue->IsQueueOnCurrentThread(&callDirectly);
|
||||
|
||||
if (callDirectly)
|
||||
{
|
||||
EventHandler(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
mDestQueue->PostEvent(event);
|
||||
|
||||
rv = NestedEventLoop(proxyInfo);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = proxyInfo->GetResult();
|
||||
delete proxyInfo;
|
||||
@ -206,17 +265,15 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi
|
||||
#endif
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
mDestQueue->ExitMonitor();
|
||||
return rv;
|
||||
}
|
||||
else if (mProxyType & PROXY_ASYNC)
|
||||
|
||||
if (mProxyType & PROXY_ASYNC)
|
||||
{
|
||||
mDestQueue->PostEvent(event);
|
||||
mDestQueue->ExitMonitor();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mDestQueue->ExitMonitor();
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
}
|
||||
@ -326,7 +383,7 @@ nsProxyObject::AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *met
|
||||
else
|
||||
{
|
||||
|
||||
nsIEventQueue *eventQ;
|
||||
nsIEventQueue *eventQ = nsnull;
|
||||
/*
|
||||
if the parameter is coming |in|, it should only be called on the callers thread.
|
||||
else, if the parameter is an |out| thread, it should only be called on the proxy
|
||||
@ -340,23 +397,21 @@ nsProxyObject::AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *met
|
||||
else
|
||||
{
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
if ( NS_SUCCEEDED( rv ) )
|
||||
{
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
|
||||
if ( NS_FAILED( rv ) )
|
||||
{
|
||||
// the caller does not have an eventQ of their own. bad.
|
||||
eventQ = GetQueue();
|
||||
rv = NS_OK; // todo: remove!
|
||||
#ifdef DEBUG
|
||||
printf("**************************************************\n");
|
||||
printf("xpcom-proxy: Caller does not have an EventQ\n");
|
||||
printf("**************************************************\n");
|
||||
#endif /* DEBUG */
|
||||
|
||||
}
|
||||
}
|
||||
if ( NS_FAILED( rv ) )
|
||||
return rv
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
|
||||
if ( NS_FAILED( rv ) )
|
||||
{
|
||||
// the caller does not have an eventQ of their own. bad.
|
||||
eventQ = GetQueue();
|
||||
rv = NS_OK; // todo: remove!
|
||||
#ifdef DEBUG
|
||||
printf("**************************************************\n");
|
||||
printf("xpcom-proxy: Caller does not have an EventQ\n");
|
||||
printf("**************************************************\n");
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a hack until we can do some lookup
|
||||
@ -373,6 +428,7 @@ nsProxyObject::AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *met
|
||||
{
|
||||
nsAllocator::Free((void*)iid);
|
||||
NS_RELEASE(manager);
|
||||
NS_RELEASE(eventQ);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -385,6 +441,8 @@ nsProxyObject::AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *met
|
||||
GetProxyType(),
|
||||
(void**) &aProxyObject);
|
||||
}
|
||||
|
||||
NS_RELEASE(eventQ);
|
||||
}
|
||||
|
||||
nsAllocator::Free((void*)iid);
|
||||
@ -439,6 +497,8 @@ nsProxyObject::AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *met
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void DestroyHandler(PLEvent *self)
|
||||
{
|
||||
nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
|
||||
@ -448,45 +508,33 @@ void DestroyHandler(PLEvent *self)
|
||||
{
|
||||
delete owner;
|
||||
}
|
||||
|
||||
// decrement once since we increased it during the Post()
|
||||
NS_RELEASE(proxyObject);
|
||||
else
|
||||
{
|
||||
owner->SetCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
void* EventHandler(PLEvent *self)
|
||||
{
|
||||
nsProxyObjectCallInfo *info = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
|
||||
nsProxyObject *proxyObject = info->GetProxyObject();
|
||||
nsIEventQueue *eventQ = proxyObject->GetQueue();
|
||||
|
||||
nsProxyObjectCallInfo *info = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
|
||||
|
||||
if (info != nsnull)
|
||||
{
|
||||
if (eventQ == nsnull || proxyObject == nsnull)
|
||||
nsProxyObject *proxyObject = info->GetProxyObject();
|
||||
|
||||
if (proxyObject)
|
||||
{
|
||||
info->SetResult(NS_ERROR_OUT_OF_MEMORY) ;
|
||||
return NULL;
|
||||
// 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);
|
||||
}
|
||||
|
||||
// invoke the magic of xptc...
|
||||
nsresult rv = XPTC_InvokeByIndex( proxyObject->GetRealObject(),
|
||||
info->GetMethodIndex(),
|
||||
info->GetParameterCount(),
|
||||
info->GetParameterList());
|
||||
|
||||
info->SetResult(rv);
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -46,29 +46,27 @@ class nsProxyEventClass;
|
||||
|
||||
class nsProxyEventClass : public nsISupports
|
||||
{
|
||||
public:
|
||||
// all the interface method declarations...
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
public:
|
||||
NS_IMETHOD DelegatedQueryInterface(nsProxyEventObject* self, REFNSIID aIID, void** aInstancePtr);
|
||||
|
||||
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 GetRootProxyObject(nsProxyEventObject* anObject, nsProxyEventObject** result);
|
||||
nsresult CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID aIID, nsProxyEventObject** aInstancePtr);
|
||||
|
||||
virtual ~nsProxyEventClass();
|
||||
private:
|
||||
nsProxyEventClass(); // not implemented
|
||||
nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo);
|
||||
|
||||
protected:
|
||||
|
||||
nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo);
|
||||
virtual ~nsProxyEventClass();
|
||||
|
||||
private:
|
||||
nsIInterfaceInfo* mInfo;
|
||||
nsIID mIID;
|
||||
uint32* mDescriptors;
|
||||
nsIID mIID;
|
||||
uint32* mDescriptors;
|
||||
};
|
||||
|
||||
|
||||
@ -82,9 +80,7 @@ public:
|
||||
NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info);
|
||||
|
||||
// call this method and return result
|
||||
NS_IMETHOD CallMethod(PRUint16 methodIndex,
|
||||
const nsXPTMethodInfo* info,
|
||||
nsXPTCMiniVariant* params);
|
||||
NS_IMETHOD CallMethod(PRUint16 methodIndex, const nsXPTMethodInfo* info, nsXPTCMiniVariant* params);
|
||||
|
||||
|
||||
static nsProxyEventObject* GetNewOrUsedProxy(nsIEventQueue *destQueue,
|
||||
@ -93,31 +89,30 @@ public:
|
||||
REFNSIID aIID);
|
||||
|
||||
|
||||
nsIEventQueue* GetQueue() const { return mProxyObject->GetQueue(); }
|
||||
nsIEventQueue* GetPLQueue() const { return mProxyObject->GetQueue(); }
|
||||
|
||||
REFNSIID GetIID() const {return GetClass()->GetIID();}
|
||||
nsProxyEventClass* GetClass() const { return mClass; }
|
||||
|
||||
nsISupports* GetRealObject() const { return mProxyObject->GetRealObject(); }
|
||||
nsProxyEventObject* GetRootProxyObject() const { return mRoot; }
|
||||
REFNSIID GetIID() const { return GetClass()->GetIID();}
|
||||
|
||||
nsProxyEventObject* Find(REFNSIID aIID);
|
||||
nsIEventQueue* GetQueue() const { return mProxyObject->GetQueue(); }
|
||||
nsIEventQueue* GetPLQueue() const { return mProxyObject->GetQueue(); }
|
||||
nsProxyEventClass* GetClass() const { return mClass; }
|
||||
nsISupports* GetRealObject() const { return mProxyObject->GetRealObject(); }
|
||||
nsProxyEventObject* GetRootProxyObject() const { return mRoot; }
|
||||
|
||||
nsProxyEventObject* Find(REFNSIID aIID);
|
||||
|
||||
|
||||
protected:
|
||||
virtual ~nsProxyEventObject();
|
||||
|
||||
private:
|
||||
nsProxyEventObject(); // not implemented
|
||||
|
||||
nsProxyEventObject(nsIEventQueue *destQueue,
|
||||
PRInt32 proxyType,
|
||||
nsISupports* aObj,
|
||||
nsProxyEventClass* aClass,
|
||||
nsProxyEventObject* root);
|
||||
|
||||
private:
|
||||
|
||||
nsProxyObject* mProxyObject;
|
||||
|
||||
nsProxyEventClass* mClass;
|
||||
nsProxyObject* mProxyObject;
|
||||
nsProxyEventClass* mClass;
|
||||
nsProxyEventObject* mRoot;
|
||||
nsProxyEventObject* mNext;
|
||||
};
|
||||
@ -134,8 +129,7 @@ class nsProxyObjectManager: public nsIProxyObjectManager
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPROXYEVENT_MANAGER_IID);
|
||||
|
||||
|
||||
NS_IMETHOD GetProxyObject(nsIEventQueue *destQueue,
|
||||
REFNSIID aIID,
|
||||
nsISupports* aObj,
|
||||
@ -151,10 +145,7 @@ public:
|
||||
|
||||
|
||||
|
||||
// Helpers
|
||||
static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
|
||||
|
||||
|
||||
static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
|
||||
|
||||
nsProxyObjectManager();
|
||||
virtual ~nsProxyObjectManager();
|
||||
|
@ -46,7 +46,6 @@ class nsProxyCreateInstance : public nsIProxyCreateInstance
|
||||
|
||||
nsProxyCreateInstance();
|
||||
virtual ~nsProxyCreateInstance();
|
||||
|
||||
};
|
||||
|
||||
nsProxyCreateInstance::nsProxyCreateInstance()
|
||||
|
@ -29,10 +29,11 @@
|
||||
|
||||
#include "nsITestProxy.h"
|
||||
|
||||
|
||||
|
||||
#include "nsProxyObjectManager.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
|
||||
static NS_DEFINE_IID(kProxyObjectManagerIID, NS_IPROXYEVENT_MANAGER_IID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
/***************************************************************************/
|
||||
extern "C" void
|
||||
@ -133,8 +134,25 @@ NS_IMPL_ISUPPORTS(nsTestXPCFoo2,kITestXPCFooIID)
|
||||
|
||||
NS_IMETHODIMP nsTestXPCFoo2::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval)
|
||||
{
|
||||
printf("Thread (%d) nsTestXPCFoo2::Test2() called successfully! Party on...\n", p1);
|
||||
*retval = 0;
|
||||
printf("calling back to caller!\n\n");
|
||||
|
||||
nsIProxyObjectManager* manager;
|
||||
nsITestProxy * proxyObject;
|
||||
|
||||
nsServiceManager::GetService( NS_XPCOMPROXY_PROGID,
|
||||
kProxyObjectManagerIID,
|
||||
(nsISupports **)&manager);
|
||||
|
||||
printf("ProxyObjectManager: %d \n", manager);
|
||||
|
||||
PR_ASSERT(manager);
|
||||
|
||||
manager->GetProxyObject((nsIEventQueue*)p1, nsITestProxy::GetIID(), this, PROXY_SYNC, (void**)&proxyObject);
|
||||
proxyObject->Test3(nsnull, nsnull);
|
||||
|
||||
printf("Deleting Proxy Object\n");
|
||||
NS_RELEASE(proxyObject);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -149,7 +167,7 @@ NS_IMETHODIMP nsTestXPCFoo2::Test2()
|
||||
|
||||
NS_IMETHODIMP nsTestXPCFoo2::Test3(nsISupports *p1, nsISupports **p2)
|
||||
{
|
||||
*p2 = nsnull;
|
||||
printf("Got called");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -219,11 +237,6 @@ void TestCase_TwoClassesOneInterface(void *arg)
|
||||
rv = proxyObject->Test2();
|
||||
printf("Thread (%d) error: %d.\n", threadNumber, rv);
|
||||
|
||||
|
||||
printf("Thread (%d) Prior to calling proxyObject2->Test.\n", threadNumber);
|
||||
rv = proxyObject2->Test(threadNumber, 0, &a);
|
||||
printf("Thread (%d) proxyObject2 error: %d.\n", threadNumber, rv);
|
||||
|
||||
printf("Thread (%d) Prior to calling proxyObject2->Test2.\n", threadNumber);
|
||||
rv = proxyObject2->Test2();
|
||||
printf("Thread (%d) proxyObject2 error: %d.\n", threadNumber, rv);
|
||||
@ -240,6 +253,67 @@ void TestCase_TwoClassesOneInterface(void *arg)
|
||||
|
||||
|
||||
|
||||
void TestCase_NestedLoop(void *arg)
|
||||
{
|
||||
ArgsStruct *argsStruct = (ArgsStruct*) arg;
|
||||
|
||||
|
||||
nsIProxyObjectManager* manager;
|
||||
|
||||
nsServiceManager::GetService( NS_XPCOMPROXY_PROGID,
|
||||
kProxyObjectManagerIID,
|
||||
(nsISupports **)&manager);
|
||||
|
||||
printf("ProxyObjectManager: %d \n", manager);
|
||||
|
||||
PR_ASSERT(manager);
|
||||
|
||||
nsITestProxy *proxyObject;
|
||||
nsTestXPCFoo2* foo = new nsTestXPCFoo2();
|
||||
|
||||
PR_ASSERT(foo);
|
||||
|
||||
|
||||
manager->GetProxyObject(argsStruct->queue, nsITestProxy::GetIID(), foo, PROXY_SYNC, (void**)&proxyObject);
|
||||
|
||||
if (proxyObject)
|
||||
{
|
||||
// release ownership of the real object.
|
||||
|
||||
PRInt32 a;
|
||||
nsresult rv;
|
||||
PRInt32 threadNumber = argsStruct->threadNumber;
|
||||
|
||||
printf("Deleting real Object (%d)\n", threadNumber);
|
||||
NS_RELEASE(foo);
|
||||
|
||||
PRInt32 retval;
|
||||
|
||||
printf("Getting EventQueue...\n");
|
||||
|
||||
nsIEventQueue* eventQ;
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
|
||||
if (NS_FAILED(rv))
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
else
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
|
||||
|
||||
printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber);
|
||||
rv = proxyObject->Test((PRInt32)eventQ, 0, &retval);
|
||||
printf("Thread (%d) proxyObject error: %d.\n", threadNumber, rv);
|
||||
|
||||
printf("Deleting Proxy Object (%d)\n", threadNumber );
|
||||
NS_RELEASE(proxyObject);
|
||||
}
|
||||
|
||||
PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -320,17 +394,15 @@ void TestCase_nsISupports(void *arg)
|
||||
|
||||
static void PR_CALLBACK ProxyTest( void *arg )
|
||||
{
|
||||
TestCase_TwoClassesOneInterface(arg);
|
||||
//TestCase_TwoClassesOneInterface(arg);
|
||||
// TestCase_2(arg);
|
||||
TestCase_nsISupports(arg);
|
||||
//TestCase_nsISupports(arg);
|
||||
TestCase_NestedLoop(arg);
|
||||
|
||||
NS_RELEASE( ((ArgsStruct*) arg)->queue);
|
||||
free((void*) arg);
|
||||
NS_RELEASE( ((ArgsStruct*) arg)->queue);
|
||||
free((void*) arg);
|
||||
}
|
||||
|
||||
#include "nsIEventQueueService.h"
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
nsIEventQueue *gEventQueue = nsnull;
|
||||
|
||||
static void PR_CALLBACK EventLoop( void *arg )
|
||||
@ -427,7 +499,7 @@ main(int argc, char **argv)
|
||||
0 );
|
||||
|
||||
|
||||
PR_Sleep(PR_MillisecondsToInterval(10000));
|
||||
PR_Sleep(PR_MillisecondsToInterval(1000));
|
||||
|
||||
NS_ASSERTION(gEventQueue, "no main event queue"); // BAD BAD BAD. EVENT THREAD DID NOT CREATE QUEUE. This may be a timing issue, set the
|
||||
// sleep about longer, and try again.
|
||||
|
Loading…
x
Reference in New Issue
Block a user