diff --git a/java/xpcom/xpcom/bcIXPCOMStubsAndProxies.h b/java/xpcom/xpcom/bcIXPCOMStubsAndProxies.h index 65ce984bc51..e69de29bb2d 100644 --- a/java/xpcom/xpcom/bcIXPCOMStubsAndProxies.h +++ b/java/xpcom/xpcom/bcIXPCOMStubsAndProxies.h @@ -1,44 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is Sun Microsystems, - * Inc. Portions created by Sun are - * Copyright (C) 1999 Sun Microsystems, Inc. All - * Rights Reserved. - * - * Contributor(s): - * Igor Kushnirskiy - */ - -#ifndef __bcIXPCOMStubsAndProxies_h__ -#define __bcIXPCOMStubsAndProxies_h__ -#include "nsISupports.h" -#include "bcDefs.h" - -/* 843ff582-1dd2-11b2-84b5-b43ba3ad3ef4 */ -#define BC_XPCOMSTUBSANDPROXIES_IID \ - {0x843ff582, 0x1dd2, 0x11b2, \ - {0x84, 0xb5,0xb4, 0x3b, 0xa3, 0xad, 0x3e, 0xf4}} - -class bcIStub; -class bcIORB; - -class bcIXPCOMStubsAndProxies : public nsISupports { -public: - NS_DEFINE_STATIC_IID_ACCESSOR(BC_XPCOMSTUBSANDPROXIES_IID) - NS_IMETHOD GetStub(nsISupports *obj, bcIStub **stub) = 0; - NS_IMETHOD GetOID(nsISupports *obj, bcIORB *orb, bcOID *oid) = 0; - NS_IMETHOD GetProxy(bcOID oid, const nsIID &iid, bcIORB *orb, nsISupports **proxy) = 0; -}; - -#endif diff --git a/java/xpcom/xpcom/bcXPCOMProxy.cpp b/java/xpcom/xpcom/bcXPCOMProxy.cpp index a8e8d368a23..8f5fb38ba88 100644 --- a/java/xpcom/xpcom/bcXPCOMProxy.cpp +++ b/java/xpcom/xpcom/bcXPCOMProxy.cpp @@ -20,17 +20,27 @@ * Igor Kushnirskiy */ -#include "pratom.h" +#include "prmem.h" #include "nsIInterfaceInfoManager.h" +#include "nsCOMPtr.h" +#include "nsIServiceManager.h" +#include "nsIEventQueueService.h" +#include "nsIThread.h" + #include "bcXPCOMProxy.h" #include "bcXPCOMMarshalToolkit.h" //#include "signal.h" //NS_IMPL_ISUPPORTS(bcXPCOMProxy, NS_GET_IID(bcXPCOMProxy)); #include "bcXPCOMLog.h" +#include "bcIXPCOMStubsAndProxies.h" +#include "bcXPCOMStubsAndProxiesCID.h" +static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); +static NS_DEFINE_CID(kStubsAndProxies,BC_XPCOMSTUBSANDPROXIES_CID); + bcXPCOMProxy::bcXPCOMProxy(bcOID _oid, const nsIID &_iid, bcIORB *_orb) { PRLogModuleInfo *log = bcXPCOMLog::GetLog(); NS_INIT_REFCNT(); @@ -69,6 +79,20 @@ NS_IMETHODIMP bcXPCOMProxy::GetInterfaceInfo(nsIInterfaceInfo** info) { return NS_OK; } + +struct CallInfo { + CallInfo(nsIEventQueue *eq, bcIORB *o, bcICall *c ) { + callersEventQ = eq; call = c; orb = o; completed = PR_FALSE; + } + bcICall *call; + bcIORB *orb; + nsCOMPtr callersEventQ; + PRBool completed; +}; + +static void* EventHandler(PLEvent *self); +static void PR_CALLBACK DestroyHandler(PLEvent *self); + NS_IMETHODIMP bcXPCOMProxy::CallMethod(PRUint16 methodIndex, const nsXPTMethodInfo* info, nsXPTCMiniVariant* params) { @@ -78,7 +102,56 @@ NS_IMETHODIMP bcXPCOMProxy::CallMethod(PRUint16 methodIndex, bcIMarshaler *marshaler = call->GetMarshaler(); bcXPCOMMarshalToolkit * mt = new bcXPCOMMarshalToolkit(methodIndex, interfaceInfo, params,orb); mt->Marshal(marshaler); - orb->SendReceive(call); + nsIEventQueue * eventQ; + nsCOMPtr stubsAndProxiesService; + stubsAndProxiesService = do_GetService(kStubsAndProxies); + stubsAndProxiesService->GetEventQueue(&eventQ); + if (eventQ == NULL) { + orb->SendReceive(call); + } else { + nsCOMPtr currentEventQ; + PRBool eventLoopCreated = PR_FALSE; + nsCOMPtr eventQService = do_GetService(kEventQueueServiceCID); + nsresult rv = NS_OK; + + rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(currentEventQ)); + if (NS_FAILED(rv)) { + rv = eventQService->CreateMonitoredThreadEventQueue(); + eventLoopCreated = PR_TRUE; + if (NS_FAILED(rv)) + return rv; + rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(currentEventQ)); + } + + if (NS_FAILED(rv)) { + return rv; + } + CallInfo * callInfo = new CallInfo(currentEventQ,orb,call); + PLEvent *event = PR_NEW(PLEvent); + PL_InitEvent(event, + callInfo, + EventHandler, + DestroyHandler); + eventQ->PostEvent(event); + while (1) { + PR_LOG(log, PR_LOG_DEBUG, ("--Dispatch we got new event\n")); + PLEvent *nextEvent; + rv = currentEventQ->WaitForEvent(&nextEvent); + if (callInfo->completed) { + PR_DELETE(nextEvent); + break; //we are done + } + if (NS_FAILED(rv)) { + break; + } + currentEventQ->HandleEvent(nextEvent); + } + if (eventLoopCreated) { + eventQService->DestroyThreadEventQueue(); + eventQ = NULL; + } + } + NS_IF_RELEASE(eventQ); bcIUnMarshaler * unmarshaler = call->GetUnMarshaler(); mt->UnMarshal(unmarshaler); delete call; delete marshaler; delete unmarshaler; delete mt; @@ -129,3 +202,18 @@ NS_IMETHODIMP bcXPCOMProxy::QueryInterface(REFNSIID aIID, void** aInstancePtr) { return r; } + +static void* EventHandler(PLEvent *self) { + PRLogModuleInfo *log = bcXPCOMLog::GetLog(); + PR_LOG(log, PR_LOG_DEBUG, ("--about to bcXPCOMProxy EventHandler\n")); + CallInfo *callInfo = (CallInfo*)PL_GetEventOwner(self); + callInfo->orb->SendReceive(callInfo->call); + callInfo->completed = PR_TRUE; + PR_LOG(log, PR_LOG_DEBUG, ("--about to callInfo->callersEventQ->PostEvent;\n")); + PLEvent *event = PR_NEW(PLEvent); //nb who is doing free ? + callInfo->callersEventQ->PostEvent(event); + return NULL; +} + +static void PR_CALLBACK DestroyHandler(PLEvent *self) { +} diff --git a/java/xpcom/xpcom/bcXPCOMStub.cpp b/java/xpcom/xpcom/bcXPCOMStub.cpp index ece49a59974..f7ddc914522 100644 --- a/java/xpcom/xpcom/bcXPCOMStub.cpp +++ b/java/xpcom/xpcom/bcXPCOMStub.cpp @@ -27,77 +27,108 @@ #include "bcXPCOMMarshalToolkit.h" #include "bcXPCOMStub.h" #include "bcXPCOMLog.h" - +#include "bcIXPCOMStubsAndProxies.h" +#include "bcXPCOMStubsAndProxiesCID.h" #include "nsIServiceManager.h" - #include "nsIThread.h" static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); -struct CallInfo; +static NS_DEFINE_CID(kStubsAndProxies,BC_XPCOMSTUBSANDPROXIES_CID); + static void* PR_CALLBACK EventHandler(PLEvent *self); static void PR_CALLBACK DestroyHandler(PLEvent *self); struct CallInfo { - CallInfo(nsIEventQueue * eq, bcICall *c, bcIStub *s) { + CallInfo(nsIEventQueue * eq, bcICall *c, bcXPCOMStub *s) { callersEventQ = eq; call = c; stub = s; completed = PR_FALSE; } nsCOMPtr callersEventQ; bcICall *call; - bcIStub *stub; + bcXPCOMStub *stub; PRBool completed; }; bcXPCOMStub::bcXPCOMStub(nsISupports *o) : object(o) { + PRLogModuleInfo *log = bcXPCOMLog::GetLog(); + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStub::bcXPCOMStub\n")); NS_ADDREF(object); - _mOwningThread = NS_CurrentThread(); + nsresult rv; + _mOwningThread = PR_CurrentThread(); eventQService = do_GetService(kEventQueueServiceCID); - eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(owningEventQ)); + rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(owningEventQ)); + if (NS_FAILED(rv)) { + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStub::bcXPCOMStub no eventQ in the current thread\n")); + /* there is no eventQ in the current thread. Let's try using UI thread eventQ + what else can we do? supposedly calling from inside UI thread is safe + */ + rv = eventQService->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(owningEventQ)); + if (NS_FAILED(rv)) { + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStub::bcXPCOMStub no eventQ in the UI thread\n")); + owningEventQ = NULL; + } + } } bcXPCOMStub::~bcXPCOMStub() { NS_RELEASE(object); } +void bcXPCOMStub::DispatchAndSaveThread(bcICall *call, nsIEventQueue *eventQueue) { + PRLogModuleInfo *log = bcXPCOMLog::GetLog(); + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStub::DispatchAndSaveThreade\n")); + bcIID iid; bcOID oid; bcMID mid; + call->GetParams(&iid, &oid, &mid); + nsIInterfaceInfo *interfaceInfo; + nsIInterfaceInfoManager* iimgr; + if( (iimgr = XPTI_GetInterfaceInfoManager()) ) { + if (NS_FAILED(iimgr->GetInfoForIID(&iid, &interfaceInfo))) { + return; //nb exception handling + } + NS_RELEASE(iimgr); + } else { + return; + } + nsXPTCVariant *params; + nsXPTMethodInfo* info; + interfaceInfo->GetMethodInfo(mid,(const nsXPTMethodInfo **)&info); + int paramCount = info->GetParamCount(); + bcXPCOMMarshalToolkit * mt = NULL; + if (paramCount > 0) { + PR_LOG(log, PR_LOG_DEBUG, ("--[c++]bcXPCOMStub paramCount %d\n",paramCount)); + params = (nsXPTCVariant *) PR_Malloc(sizeof(nsXPTCVariant)*paramCount); + mt = new bcXPCOMMarshalToolkit(mid, interfaceInfo, params, call->GetORB()); + bcIUnMarshaler * um = call->GetUnMarshaler(); + mt->UnMarshal(um); + //delete um; + } + //push caller eventQ + nsCOMPtr stubsAndProxiesService; + stubsAndProxiesService = do_GetService(kStubsAndProxies); + stubsAndProxiesService->PushEventQueue(eventQueue); + //nb return value; excepion handling + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStub::DispatchAndSaveThreade about to XPTC_InvokeByIndex\n")); + XPTC_InvokeByIndex(object, mid, paramCount, params); + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStub::DispatchAndSaveThreade after XPTC_InvokeByIndex\n")); + if (mt != NULL) { //nb to do what about nsresult ? + bcIMarshaler * m = call->GetMarshaler(); + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStub::DispatchAndSaveThreade about to mt->Marshal\n")); + mt->Marshal(m); + //delete m; + } + delete mt; + //pop caller eventQueue + stubsAndProxiesService->PopEventQueue(NULL); + return; +} void bcXPCOMStub::Dispatch(bcICall *call) { PRLogModuleInfo *log = bcXPCOMLog::GetLog(); - if (_mOwningThread == NS_CurrentThread()) { - PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStub::Dispatch(bcICall *call)\n")); - bcIID iid; bcOID oid; bcMID mid; - call->GetParams(&iid, &oid, &mid); - nsIInterfaceInfo *interfaceInfo; - nsIInterfaceInfoManager* iimgr; - if( (iimgr = XPTI_GetInterfaceInfoManager()) ) { - if (NS_FAILED(iimgr->GetInfoForIID(&iid, &interfaceInfo))) { - return; //nb exception handling - } - NS_RELEASE(iimgr); - } else { - return; - } - nsXPTCVariant *params; - nsXPTMethodInfo* info; - interfaceInfo->GetMethodInfo(mid,(const nsXPTMethodInfo **)&info); - int paramCount = info->GetParamCount(); - bcXPCOMMarshalToolkit * mt = NULL; - if (paramCount > 0) { - PR_LOG(log, PR_LOG_DEBUG, ("--[c++]bcXPCOMStub paramCount %d\n",paramCount)); - params = (nsXPTCVariant *) PR_Malloc(sizeof(nsXPTCVariant)*paramCount); - mt = new bcXPCOMMarshalToolkit(mid, interfaceInfo, params, call->GetORB()); - bcIUnMarshaler * um = call->GetUnMarshaler(); - mt->UnMarshal(um); - } - //nb return value; excepion handling - XPTC_InvokeByIndex(object, mid, paramCount, params); - if (mt != NULL) { //nb to do what about nsresult ? - bcIMarshaler * m = call->GetMarshaler(); - mt->Marshal(m); - } - //nb memory deallocation - return; + if (_mOwningThread == NS_CurrentThread() + || NULL == (void*)owningEventQ) { + DispatchAndSaveThread(call); } else { PRBool eventLoopCreated = PR_FALSE; nsresult rv = NS_OK; @@ -135,6 +166,10 @@ void bcXPCOMStub::Dispatch(bcICall *call) { } eventQ->HandleEvent(nextEvent); } + if (eventLoopCreated) { + eventQService->DestroyThreadEventQueue(); + eventQ = NULL; + } } } @@ -144,10 +179,10 @@ static void* EventHandler(PLEvent *self) { PRLogModuleInfo *log = bcXPCOMLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("--about to EventHandler\n")); CallInfo * callInfo = (CallInfo*)PL_GetEventOwner(self); - callInfo->stub->Dispatch(callInfo->call); + callInfo->stub->DispatchAndSaveThread(callInfo->call,callInfo->callersEventQ); callInfo->completed = PR_TRUE; PR_LOG(log, PR_LOG_DEBUG, ("--about to callInfo->callersEventQ->PostEvent;\n")); - PLEvent *event = PR_NEW(PLEvent); + PLEvent *event = PR_NEW(PLEvent); //nb who is doing free ? callInfo->callersEventQ->PostEvent(event); return NULL; } @@ -156,3 +191,5 @@ static void PR_CALLBACK DestroyHandler(PLEvent *self) { } + + diff --git a/java/xpcom/xpcom/bcXPCOMStub.h b/java/xpcom/xpcom/bcXPCOMStub.h index f658ad6436c..c73cd30963b 100644 --- a/java/xpcom/xpcom/bcXPCOMStub.h +++ b/java/xpcom/xpcom/bcXPCOMStub.h @@ -32,11 +32,13 @@ public: bcXPCOMStub(nsISupports *obj); virtual ~bcXPCOMStub(); virtual void Dispatch(bcICall *call) ; + void DispatchAndSaveThread(bcICall *call, nsIEventQueue *q = NULL); private: nsISupports *object; void* _mOwningThread; nsCOMPtr owningEventQ; nsCOMPtr eventQService; + }; #endif diff --git a/java/xpcom/xpcom/bcXPCOMStubsAndProxies.cpp b/java/xpcom/xpcom/bcXPCOMStubsAndProxies.cpp index b75947b2265..d39d1c6dd53 100644 --- a/java/xpcom/xpcom/bcXPCOMStubsAndProxies.cpp +++ b/java/xpcom/xpcom/bcXPCOMStubsAndProxies.cpp @@ -70,6 +70,7 @@ public: bcXPCOMStubsAndProxies::bcXPCOMStubsAndProxies() { NS_INIT_REFCNT(); oid2objectMap = new nsSupportsHashtable(256, PR_TRUE); + threadPrivateIndex = 0; } bcXPCOMStubsAndProxies::~bcXPCOMStubsAndProxies() { @@ -122,5 +123,79 @@ NS_IMETHODIMP bcXPCOMStubsAndProxies::GetProxy(bcOID oid, const nsIID &iid, bcIO } +struct EventQueueStack { + PRUint32 stackPointer; + nsIEventQueue *stack[200]; + EventQueueStack() { + stackPointer = 0; + } +}; +NS_IMETHODIMP bcXPCOMStubsAndProxies::GetEventQueue(nsIEventQueue **eventQueue) { + PRLogModuleInfo *log = bcXPCOMLog::GetLog(); + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStubsAndProxies::GetEventQueue\n")); + EventQueueStack *stack; + if (threadPrivateIndex == 0) { + *eventQueue = NULL; + } else { + stack = (EventQueueStack*)PR_GetThreadPrivate(threadPrivateIndex); + if (stack !=0 + && stack->stackPointer != 0) { + *eventQueue = stack->stack[(stack->stackPointer)-1]; + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStubsAndProxies::GetEventQueue eventQueue=%p\n",*eventQueue)); + NS_IF_ADDREF(*eventQueue); + } else { + *eventQueue = NULL; + } + } + return NS_OK; +} +NS_IMETHODIMP bcXPCOMStubsAndProxies::PopEventQueue(nsIEventQueue **_eventQueue) { + PRLogModuleInfo *log = bcXPCOMLog::GetLog(); + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStubsAndProxies::PopEventQueue\n")); + EventQueueStack *stack; + nsIEventQueue * eventQueue; + if (threadPrivateIndex == 0) { + *_eventQueue = NULL; + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStubsAndProxies::PopEventQueue 1\n")); + } else { + stack = (EventQueueStack*)PR_GetThreadPrivate(threadPrivateIndex); + if (stack !=0 + && stack->stackPointer != 0) { + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStubsAndProxies::PopEventQueue 2\n")); + eventQueue = stack->stack[--(stack->stackPointer)]; + } else { + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStubsAndProxies::PopEventQueue 3\n")); + eventQueue = NULL; + } + if (_eventQueue != NULL) { + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStubsAndProxies::PopEventQueue 4\n")); + *_eventQueue = eventQueue; + } else { + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStubsAndProxies::PopEventQueue eventQueue=%p\n",eventQueue)); + NS_IF_RELEASE(eventQueue); + } + } + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStubsAndProxies::PopEventQueue 6\n")); + return NS_OK; +} +NS_IMETHODIMP bcXPCOMStubsAndProxies::PushEventQueue(nsIEventQueue *eventQueue) { + PRLogModuleInfo *log = bcXPCOMLog::GetLog(); + PR_LOG(log, PR_LOG_DEBUG, ("--bcXPCOMStubsAndProxies::PushEventQueue eventQueue=%p\n",eventQueue)); + nsresult r; + if (threadPrivateIndex == 0) { + r = PR_NewThreadPrivateIndex(&threadPrivateIndex,NULL); + PR_ASSERT(threadPrivateIndex != 0 + && NS_SUCCEEDED(r)); + } + EventQueueStack *stack; + stack = (EventQueueStack*)PR_GetThreadPrivate(threadPrivateIndex); + if (stack == NULL) { + stack = new EventQueueStack(); + PR_SetThreadPrivate(threadPrivateIndex, (void *)stack); + } + NS_IF_ADDREF(eventQueue); + stack->stack[(stack->stackPointer)++] = eventQueue; + return NS_OK; +} diff --git a/java/xpcom/xpcom/bcXPCOMStubsAndProxies.h b/java/xpcom/xpcom/bcXPCOMStubsAndProxies.h index c08634faec6..e69de29bb2d 100644 --- a/java/xpcom/xpcom/bcXPCOMStubsAndProxies.h +++ b/java/xpcom/xpcom/bcXPCOMStubsAndProxies.h @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is Sun Microsystems, - * Inc. Portions created by Sun are - * Copyright (C) 1999 Sun Microsystems, Inc. All - * Rights Reserved. - * - * Contributor(s): - * Igor Kushnirskiy - */ -#ifndef __bcXPCOMStubsAndProxies_h -#define __bcXPCOMStubsAndProxies_h -#include "bcIXPCOMStubsAndProxies.h" -#include "bcIORB.h" -#include "bcIStub.h" -#include "bcXPCOMStubsAndProxiesCID.h" - - -class nsSupportsHashtable; - -class bcXPCOMStubsAndProxies : public bcIXPCOMStubsAndProxies { - NS_DECL_ISUPPORTS - NS_DEFINE_STATIC_IID_ACCESSOR(BC_XPCOMSTUBSANDPROXIES_IID) - NS_IMETHOD GetStub(nsISupports *obj, bcIStub **stub); - NS_IMETHOD GetOID(nsISupports *obj, bcIORB *orb, bcOID *oid); - NS_IMETHOD GetProxy(bcOID oid, const nsIID &iid, bcIORB *orb, nsISupports **proxy); - bcXPCOMStubsAndProxies(); - virtual ~bcXPCOMStubsAndProxies(); -private: - nsSupportsHashtable * oid2objectMap; -}; -#endif /* __bcXPCOMStubsAndProxies_h */ - - - - - - - -