From a271419de6bf4c0bc355a8ef6268174410fd544c Mon Sep 17 00:00:00 2001 From: "pavlov%netscape.com" Date: Mon, 5 Jun 2000 21:53:25 +0000 Subject: [PATCH] Fix for eventqueue objects leaking bug #20166. This also removes the hacked fix for bug #36361 and uses a real fix. Major overhaul of nsEventQueue and nsEventQueueService. r=waterson,brendan. tested on windows, linux and mac git-svn-id: svn://10.0.0.236/trunk@71554 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/dom/src/base/nsGlobalWindow.cpp | 5 +- mozilla/profile/Acct/nsAccount.cpp | 27 - mozilla/widget/src/gtk/nsAppShell.cpp | 20 +- mozilla/xpcom/proxy/src/nsProxyEvent.cpp | 10 +- .../xpcom/proxy/src/nsProxyEventObject.cpp | 7 +- mozilla/xpcom/threads/nsEventQueue.cpp | 177 ++++--- mozilla/xpcom/threads/nsEventQueue.h | 21 +- mozilla/xpcom/threads/nsEventQueueService.cpp | 474 ++++++------------ mozilla/xpcom/threads/nsEventQueueService.h | 24 +- mozilla/xpcom/threads/nsPIEventQueueChain.h | 3 + .../xpfe/appshell/src/nsWebShellWindow.cpp | 14 +- mozilla/xpfe/appshell/src/nsXULWindow.cpp | 2 +- mozilla/xpfe/appshell/src/nsXULWindow.h | 2 +- 13 files changed, 307 insertions(+), 479 deletions(-) diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index 6e5139817c2..c070f00abbe 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -2622,7 +2622,7 @@ NS_IMETHODIMP GlobalWindowImpl::OpenInternal(JSContext* cx, jsval* argv, treeOwner->FindItemWithName(name.GetUnicode(), nsnull, getter_AddRefs(newDocShellItem)); - nsIEventQueue* modalEventQueue; // This has an odd ownership model + nsCOMPtr modalEventQueue; // This has an odd ownership model nsCOMPtr eventQService; PRBool windowIsNew = PR_FALSE; @@ -2635,8 +2635,7 @@ NS_IMETHODIMP GlobalWindowImpl::OpenInternal(JSContext* cx, jsval* argv, { eventQService = do_GetService(kEventQueueServiceCID); if(eventQService && - NS_SUCCEEDED(eventQService->PushThreadEventQueue( - &modalEventQueue))) + NS_SUCCEEDED(eventQService->PushThreadEventQueue(getter_AddRefs(modalEventQueue)))) windowIsModal = PR_TRUE; } treeOwner->GetNewWindow(chromeFlags, getter_AddRefs(newDocShellItem)); diff --git a/mozilla/profile/Acct/nsAccount.cpp b/mozilla/profile/Acct/nsAccount.cpp index 77c816749fb..03056fd32e4 100644 --- a/mozilla/profile/Acct/nsAccount.cpp +++ b/mozilla/profile/Acct/nsAccount.cpp @@ -44,7 +44,6 @@ //#include "nsFileLocations.h" //#include "nsEscape.h" -#include "nsIEventQueueService.h" #include "nsIPersistentProperties2.h" #include "nsIServiceManager.h" #include "nsNetUtil.h" @@ -55,18 +54,12 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #include "nsSpecialSystemDirectory.h" -#include "plevent.h" - - #define TEST_URL "resource:/res/test.properties" #define NETLIB_DLL "netlib.dll" #define RAPTORBASE_DLL "raptorbase.dll" #define XPCOM_DLL "xpcom32.dll" -static NS_DEFINE_IID(kEventQueueCID, NS_EVENTQUEUE_CID); -static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); -static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID); static NS_DEFINE_IID(kIPersistentPropertiesIID, NS_IPERSISTENTPROPERTIES_IID); //#ifdef XP_PC @@ -347,10 +340,6 @@ int nsAccount::GetNCIValues(nsString MiddleValue) if (NS_FAILED(ret)) return ret; - NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &ret); - if (NS_FAILED(ret)) return ret; - - nsCOMPtr uri; ret = NS_NewURI(getter_AddRefs(uri), Trial, nsnull, service); if (NS_FAILED(ret)) return ret; @@ -359,12 +348,6 @@ int nsAccount::GetNCIValues(nsString MiddleValue) ret = NS_OpenURI(&channel, uri, service); if (NS_FAILED(ret)) return ret; - - nsIEventQueue *eventQ = nsnull; - ret = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ); - if (NS_FAILED(ret)) return ret; - - ret = channel->OpenInputStream(&in); if (NS_FAILED(ret)) return ret; @@ -439,10 +422,6 @@ int nsAccount::GetConfigValues(nsString fileName) if (NS_FAILED(ret)) return ret; - NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &ret); - if (NS_FAILED(ret)) return ret; - - nsCOMPtr uri; ret = NS_NewURI(getter_AddRefs(uri), Trial, nsnull, service); if (NS_FAILED(ret)) return ret; @@ -451,12 +430,6 @@ int nsAccount::GetConfigValues(nsString fileName) ret = NS_OpenURI(&channel, uri, service); if (NS_FAILED(ret)) return ret; - - nsIEventQueue *eventQ = nsnull; - ret = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ); - if (NS_FAILED(ret)) return ret; - - ret = channel->OpenInputStream(&in); if (NS_FAILED(ret)) return ret; diff --git a/mozilla/widget/src/gtk/nsAppShell.cpp b/mozilla/widget/src/gtk/nsAppShell.cpp index 71bf836a38b..716dd544f63 100644 --- a/mozilla/widget/src/gtk/nsAppShell.cpp +++ b/mozilla/widget/src/gtk/nsAppShell.cpp @@ -40,9 +40,6 @@ #include "glib.h" - -#define EVENT_QUEUES_SUCK - static PRBool sInitialized = PR_FALSE; static PLHashTable *sQueueHashTable = nsnull; static PLHashTable *sCountHashTable = nsnull; @@ -66,6 +63,9 @@ our_gdk_io_invoke(GIOChannel* source, GIOCondition condition, gpointer data) static void our_gdk_io_destroy(gpointer data) { +#ifdef DEBUG_APPSHELL + printf("our_gdk_io_destroy()\n"); +#endif OurGdkIOClosure* ioc = (OurGdkIOClosure*) data; if (ioc) { g_free(ioc); @@ -294,9 +294,7 @@ NS_IMETHODIMP nsAppShell::Spinup() // XXX shouldn't this be automatic? done: -#ifndef EVENT_QUEUES_SUCK ListenToEventQueue(mEventQueue, PR_TRUE); -#endif return rv; } @@ -312,9 +310,7 @@ NS_IMETHODIMP nsAppShell::Spindown() printf("nsAppShell::Spindown()\n"); #endif if (mEventQueue) { -#ifndef EVENT_QUEUES_SUCK ListenToEventQueue(mEventQueue, PR_FALSE); -#endif mEventQueue->ProcessPendingEvents(); mEventQueue = nsnull; } @@ -334,10 +330,6 @@ NS_IMETHODIMP nsAppShell::Run() if (!mEventQueue) return NS_ERROR_NOT_INITIALIZED; -#ifdef EVENT_QUEUES_SUCK - ListenToEventQueue(mEventQueue, PR_TRUE); -#endif - // kick up gtk_main. this won't return until gtk_main_quit is called gtk_main(); @@ -378,10 +370,6 @@ NS_IMETHODIMP nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent) g_main_iteration(PR_TRUE); -#ifdef EVENT_QUEUES_SUCK - mEventQueue->ProcessPendingEvents(); -#endif - return NS_OK; } @@ -434,7 +422,7 @@ NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue, if (count - 1 == 0) { gint tag = GPOINTER_TO_INT(PL_HashTableLookup(sQueueHashTable, GINT_TO_POINTER(key))); if (tag > 0) { - gdk_input_remove(tag); + g_source_remove(tag); PL_HashTableRemove(sQueueHashTable, GINT_TO_POINTER(key)); } } diff --git a/mozilla/xpcom/proxy/src/nsProxyEvent.cpp b/mozilla/xpcom/proxy/src/nsProxyEvent.cpp index ba828407748..de5a219d5f8 100644 --- a/mozilla/xpcom/proxy/src/nsProxyEvent.cpp +++ b/mozilla/xpcom/proxy/src/nsProxyEvent.cpp @@ -206,7 +206,7 @@ nsProxyObjectCallInfo::PostCompleted() nsIEventQueue* nsProxyObjectCallInfo::GetCallersQueue() { - return mCallersEventQ; + return mCallersEventQ; } void nsProxyObjectCallInfo::SetCallersQueue(nsIEventQueue* queue) @@ -227,7 +227,7 @@ nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISup { NS_INIT_REFCNT(); - nsServiceManager::GetService(kEventQueueServiceCID, NS_GET_IID(nsIEventQueueService), getter_AddRefs(mEventQService)); + mEventQService = do_GetService(kEventQueueServiceCID); mRealObject = realObject; mDestQueue = do_QueryInterface(destQueue); @@ -239,7 +239,7 @@ nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const { NS_INIT_REFCNT(); - nsServiceManager::GetService(kEventQueueServiceCID, NS_GET_IID(nsIEventQueueService), getter_AddRefs(mEventQService)); + mEventQService = do_GetService(kEventQueueServiceCID); nsComponentManager::CreateInstance(aClass, aDelegate, @@ -616,7 +616,7 @@ AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTC else { - nsIEventQueue *eventQ = nsnull; + nsCOMPtr eventQ; /* 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 @@ -659,7 +659,6 @@ AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTC { nsMemory::Free((void*)iid); NS_RELEASE(manager); - NS_RELEASE(eventQ); continue; } @@ -673,7 +672,6 @@ AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTC (void**) &aProxyObject); } - NS_RELEASE(eventQ); } nsMemory::Free((void*)iid); diff --git a/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp b/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp index bc46ce7a0c1..c0c94ff89f5 100644 --- a/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp +++ b/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp @@ -162,9 +162,10 @@ nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue, // this will be our key in the hash table. // this must not be a nsCOMPtr since we need to make sure that we do a QI. nsCOMPtr destQRoot; - if(NS_FAILED(destQueue->QueryInterface(NS_GET_IID(nsISupports), (void**)&destQueue))) - return nsnull; - + nsresult rv; + destQRoot = do_QueryInterface(destQueue, &rv); + if (NS_FAILED(rv)) + return nsnull; char* rootKeyString = PR_sprintf_append(nsnull, "%p.%p.%d", (PRUint32)rootObject.get(), (PRUint32)destQRoot.get(), proxyType); nsStringKey rootkey(rootKeyString); diff --git a/mozilla/xpcom/threads/nsEventQueue.cpp b/mozilla/xpcom/threads/nsEventQueue.cpp index 01662919576..a4564d7166f 100644 --- a/mozilla/xpcom/threads/nsEventQueue.cpp +++ b/mozilla/xpcom/threads/nsEventQueue.cpp @@ -49,37 +49,73 @@ static char *gDestroyedNotification = "nsIEventQueueDestroyed"; nsEventQueueImpl::nsEventQueueImpl() { NS_INIT_REFCNT(); - AddRef(); + NS_ADDREF_THIS(); /* The slightly weird ownership model for eventqueues goes like this: - there's an addref from the factory generally held by whoever asked for + + General: + There's an addref from the factory generally held by whoever asked for the queue. The queue addrefs itself (right here) and releases itself - when it goes dark and empty. Chained queues also hold references to - their immediate elder link, because we have code that assumes the random - release of a queue can't break a chain earlier than our current pointer. - A queue releases itself immediately upon being chained, dropping - the addref given it by the factory. Only the references held to it by - a younger chained queue (and from the outside), and this one here in the - constructor, keep it alive. The release when it goes dark and empty - will queue it, as it were, for destruction. - (A dark queue no longer accepts events, an empty one has none.) + after someone calls StopAcceptingEvents() on the queue and when it is + dark and empty (in CheckForDeactivation()). + + Chained queues: + + Eldest queue: + The eldest queue in a chain is held on to by the EventQueueService + in a hash table, so it is possible that the eldest queue may not be + released until the EventQueueService is shutdown. + You may not call StopAcceptingEvents() on this queue until you have + done so on all younger queues. + + General: + Each queue holds a reference to their immediate elder link and a weak + reference to their immediate younger link. Because you must shut down + queues from youngest to eldest, all the references will be removed. + + It happens something like: + queue->StopAcceptingEvents() + { + CheckForDeactivation() + { + -- hopefully we are able to shutdown now -- + Unlink() + { + -- remove the reference we hold to our elder queue -- + -- NULL out our elder queues weak reference to us -- + } + RELEASE ourself (to balance the ADDREF here in the constructor) + -- and we should go away. -- + } + } + + + Notes: + A dark queue no longer accepts events. An empty queue simply has no events. */ - mEventQueue = NULL; - mYoungerQueue = NULL; - mElderQueue = NULL; +#if defined(PR_LOGGING) && defined(DEBUG_danm) + PR_LOG(gEventQueueLog, PR_LOG_DEBUG, + ("EventQueue: Created [queue=%lx]",(long)mEventQueue)); + ++gEventQueueLogCount; +#endif + + mYoungerQueue = nsnull; + mEventQueue = nsnull; mAcceptingEvents = PR_TRUE; mCouldHaveEvents = PR_TRUE; } nsEventQueueImpl::~nsEventQueueImpl() { + Unlink(); + #if defined(PR_LOGGING) && defined(DEBUG_danm) PR_LOG(gEventQueueLog, PR_LOG_DEBUG, ("EventQueue: Destroyed [queue=%lx]",(long)mEventQueue)); ++gEventQueueLogCount; #endif - Unlink(); - if (mEventQueue != NULL) { + + if (mEventQueue) { NotifyObservers(gDestroyedNotification); PL_DestroyEventQueue(mEventQueue); } @@ -143,7 +179,11 @@ NS_IMPL_THREADSAFE_ISUPPORTS2(nsEventQueueImpl, NS_IMETHODIMP nsEventQueueImpl::StopAcceptingEvents() { - NS_ASSERTION(mElderQueue, "attempted to disable eldest queue in chain"); + // this assertion is bogus. I should be able to shut down the eldest queue, + // as long as there are no younger children + + + NS_ASSERTION(mElderQueue || !mYoungerQueue, "attempted to disable eldest queue in chain"); mAcceptingEvents = PR_FALSE; CheckForDeactivation(); #if defined(PR_LOGGING) && defined(DEBUG_danm) @@ -160,22 +200,23 @@ void nsEventQueueImpl::NotifyObservers(const char *aTopic) { nsresult rv; - nsAutoString topic; - topic.AssignWithConversion(aTopic); - nsISupports *us = NS_STATIC_CAST(nsISupports *,(NS_STATIC_CAST(nsIEventQueue *,this))); - - NS_WITH_SERVICE(nsIObserverService, os, NS_OBSERVERSERVICE_PROGID, &rv); - if (NS_SUCCEEDED(rv)) + nsCOMPtr os = do_GetService(NS_OBSERVERSERVICE_PROGID, &rv); + if (NS_SUCCEEDED(rv)) { + nsAutoString topic; + topic.AssignWithConversion(aTopic); + nsCOMPtr kungFuDeathGrip(this); + nsCOMPtr us(do_QueryInterface(kungFuDeathGrip)); os->Notify(us, topic.GetUnicode(), NULL); + } } NS_IMETHODIMP nsEventQueueImpl::InitEvent(PLEvent* aEvent, - void* owner, - PLHandleEventProc handler, - PLDestroyEventProc destructor) + void* owner, + PLHandleEventProc handler, + PLDestroyEventProc destructor) { PL_InitEvent(aEvent, owner, handler, destructor); return NS_OK; @@ -246,35 +287,34 @@ nsEventQueueImpl::PostSynchronousEvent(PLEvent* aEvent, void** aResult) NS_IMETHODIMP nsEventQueueImpl::EnterMonitor() { - PL_ENTER_EVENT_QUEUE_MONITOR(mEventQueue); - return NS_OK; + PL_ENTER_EVENT_QUEUE_MONITOR(mEventQueue); + return NS_OK; } NS_IMETHODIMP nsEventQueueImpl::ExitMonitor() { - PL_EXIT_EVENT_QUEUE_MONITOR(mEventQueue); - return NS_OK; + PL_EXIT_EVENT_QUEUE_MONITOR(mEventQueue); + return NS_OK; } NS_IMETHODIMP nsEventQueueImpl::RevokeEvents(void* owner) { - PL_RevokeEvents(mEventQueue, owner); - return NS_OK; + PL_RevokeEvents(mEventQueue, owner); + return NS_OK; } NS_IMETHODIMP nsEventQueueImpl::GetPLEventQueue(PLEventQueue** aEventQueue) { - *aEventQueue = mEventQueue; - - if (mEventQueue == NULL) - return NS_ERROR_NULL_POINTER; + if (!mEventQueue) + return NS_ERROR_NULL_POINTER; - return NS_OK; + *aEventQueue = mEventQueue; + return NS_OK; } NS_IMETHODIMP @@ -288,8 +328,8 @@ nsEventQueueImpl::IsQueueOnCurrentThread(PRBool *aResult) NS_IMETHODIMP nsEventQueueImpl::IsQueueNative(PRBool *aResult) { - *aResult = PL_IsQueueNative(mEventQueue); - return NS_OK; + *aResult = PL_IsQueueNative(mEventQueue); + return NS_OK; } NS_IMETHODIMP @@ -401,8 +441,8 @@ nsEventQueueImpl::GetEventQueueSelectFD() NS_METHOD nsEventQueueImpl::Create(nsISupports *aOuter, - REFNSIID aIID, - void **aResult) + REFNSIID aIID, + void **aResult) { nsEventQueueImpl* evt = new nsEventQueueImpl(); if (evt == NULL) @@ -420,7 +460,7 @@ NS_IMETHODIMP nsEventQueueImpl::AppendQueue(nsIEventQueue *aQueue) { nsresult rv; - nsIEventQueue *end; + nsCOMPtr end; nsCOMPtr queueChain(do_QueryInterface(aQueue)); if (!aQueue) @@ -434,12 +474,11 @@ nsEventQueueImpl::AppendQueue(nsIEventQueue *aQueue) // (be careful doing this outside nsEventQueueService's mEventQMonitor) - GetYoungest(&end); // addrefs. released by Unlink. + GetYoungest(getter_AddRefs(end)); nsCOMPtr endChain(do_QueryInterface(end)); if (endChain) { endChain->SetYounger(queueChain); queueChain->SetElder(endChain); - NS_RELEASE(aQueue); // the addref from the constructor rv = NS_OK; } return rv; @@ -448,22 +487,27 @@ nsEventQueueImpl::AppendQueue(nsIEventQueue *aQueue) NS_IMETHODIMP nsEventQueueImpl::Unlink() { - nsPIEventQueueChain *young = mYoungerQueue, - *old = mElderQueue; + nsCOMPtr young = mYoungerQueue, + old = mElderQueue; + +#if defined(PR_LOGGING) && defined(DEBUG_danm) + PR_LOG(gEventQueueLog, PR_LOG_DEBUG, + ("EventQueue: unlink [queue=%lx, younger=%lx, elder=%lx]", + (long)mEventQueue,(long)mYoungerQueue, (long)mElderQueue.get())); + ++gEventQueueLogCount; +#endif // this is probably OK, but shouldn't happen by design, so tell me if it does NS_ASSERTION(!mYoungerQueue, "event queue chain broken in middle"); // break links early in case the Release cascades back onto us - mYoungerQueue = 0; - mElderQueue = 0; + mYoungerQueue = nsnull; + mElderQueue = nsnull; if (young) young->SetElder(old); if (old) { old->SetYounger(young); - if (!young) - NS_RELEASE(old); // release addref from AppendQueue } return NS_OK; } @@ -483,17 +527,18 @@ nsEventQueueImpl::GetYoungest(nsIEventQueue **aQueue) NS_IMETHODIMP nsEventQueueImpl::GetYoungestActive(nsIEventQueue **aQueue) { - nsIEventQueue *answer = NULL; + nsCOMPtr answer; if (mYoungerQueue) - mYoungerQueue->GetYoungestActive(&answer); - if (answer == NULL) - if (mAcceptingEvents && mCouldHaveEvents) { + mYoungerQueue->GetYoungestActive(getter_AddRefs(answer)); + if (!answer) { + if (mAcceptingEvents && mCouldHaveEvents) answer = NS_STATIC_CAST(nsIEventQueue *, this); - NS_ADDREF(answer); - } else + else CheckForDeactivation(); + } *aQueue = answer; + NS_IF_ADDREF(*aQueue); return NS_OK; } @@ -511,3 +556,23 @@ nsEventQueueImpl::SetElder(nsPIEventQueueChain *aQueue) return NS_OK; } +NS_IMETHODIMP +nsEventQueueImpl::GetYounger(nsIEventQueue **aQueue) +{ + if (!mYoungerQueue) { + *aQueue = nsnull; + return NS_OK; + } + return mYoungerQueue->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&aQueue); +} + +NS_IMETHODIMP +nsEventQueueImpl::GetElder(nsIEventQueue **aQueue) +{ + if (!mElderQueue) { + *aQueue = nsnull; + return NS_OK; + } + return mElderQueue->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&aQueue); +} + diff --git a/mozilla/xpcom/threads/nsEventQueue.h b/mozilla/xpcom/threads/nsEventQueue.h index e03e3c2df80..4eff662ac99 100644 --- a/mozilla/xpcom/threads/nsEventQueue.h +++ b/mozilla/xpcom/threads/nsEventQueue.h @@ -37,9 +37,10 @@ public: // nsIEventQueue interface... NS_IMETHOD InitEvent(PLEvent* aEvent, void* owner, - PLHandleEventProc handler, PLDestroyEventProc destructor); + PLHandleEventProc handler, + PLDestroyEventProc destructor); - NS_IMETHOD_(PRStatus) PostEvent(PLEvent* aEvent); + NS_IMETHOD_(PRStatus) PostEvent(PLEvent* aEvent); NS_IMETHOD PostSynchronousEvent(PLEvent* aEvent, void** aResult); NS_IMETHOD ProcessPendingEvents(); @@ -80,22 +81,24 @@ public: NS_IMETHOD GetYoungest(nsIEventQueue **aQueue); NS_IMETHOD GetYoungestActive(nsIEventQueue **aQueue); NS_IMETHOD SetYounger(nsPIEventQueueChain *aQueue); + NS_IMETHOD GetYounger(nsIEventQueue **aQueue); NS_IMETHOD SetElder(nsPIEventQueueChain *aQueue); + NS_IMETHOD GetElder(nsIEventQueue **aQueue); private: PLEventQueue *mEventQueue; PRBool mAcceptingEvents, // accept new events or pass them on? mCouldHaveEvents; // accepting new ones, or still have old ones? - nsPIEventQueueChain *mYoungerQueue, - *mElderQueue; + nsCOMPtr mElderQueue; // younger can hold on to elder + nsPIEventQueueChain *mYoungerQueue; // but elder can't hold on to younger void NotifyObservers(const char *aTopic); void CheckForDeactivation() { - if (mCouldHaveEvents && !mAcceptingEvents && !PL_EventAvailable(mEventQueue)) { - mCouldHaveEvents = PR_FALSE; - Release(); - } - } + if (mCouldHaveEvents && !mAcceptingEvents && !PL_EventAvailable(mEventQueue)) { + mCouldHaveEvents = PR_FALSE; + NS_RELEASE_THIS(); // balance ADDREF from the constructor + } + } }; diff --git a/mozilla/xpcom/threads/nsEventQueueService.cpp b/mozilla/xpcom/threads/nsEventQueueService.cpp index 80a21bc92dd..f7990c76bde 100644 --- a/mozilla/xpcom/threads/nsEventQueueService.cpp +++ b/mozilla/xpcom/threads/nsEventQueueService.cpp @@ -29,7 +29,7 @@ #include "prlog.h" -#if defined(PR_LOGGING) +#if defined(PR_LOGGING) || defined(DEBUG_danm) extern PRLogModuleInfo* gEventQueueLog; extern PRUint32 gEventQueueLogCount; #endif @@ -68,223 +68,42 @@ public: //////////////////////////////////////////////////////////////////////////////// -/* - * EventQueueEntry maintains the data associated with each entry in - * the EventQueue service's hash table... - * - * It derives from nsISupports merely as a convienence since the entries are - * reference counted... - */ -class EventQueueEntry : public nsISupports -{ -public: - EventQueueEntry(nsEventQueueServiceImpl *aService, ThreadKey &aKey, - PRBool aNative); - virtual ~EventQueueEntry(); - - // nsISupports interface... - NS_DECL_ISUPPORTS - - nsIEventQueue* GetEventQueue(void); // addrefs! - - nsresult AddQueue(void); - - void RemoveQueue(nsIEventQueue *aQueue); // queue goes dark, and is released - ThreadKey *TheThreadKey(void) - { return &mHashKey; } - - // methods for accessing the linked list of event queue entries - void Link(EventQueueEntry *aAfter); - void Unlink(void); - EventQueueEntry *Next(void) - { return mNextEntry; } - -private: - nsresult MakeNewQueue(PRThread* thread, PRBool aNative, - nsIEventQueue **aQueue); - - nsIEventQueue *mQueue; - ThreadKey mHashKey; - nsEventQueueServiceImpl *mService; // weak reference, obviously - EventQueueEntry *mPrevEntry, - *mNextEntry; -}; - -/* nsISupports interface implementation... */ -NS_IMPL_ISUPPORTS0(EventQueueEntry) - -EventQueueEntry::EventQueueEntry(nsEventQueueServiceImpl *aService, ThreadKey &aKey, PRBool aNative) : - mHashKey(aKey), mPrevEntry(0), mNextEntry(0) -{ - NS_INIT_REFCNT(); - mService = aService; - MakeNewQueue(aKey.id, aNative, &mQueue); - NS_ASSERTION(mQueue, "EventQueueEntry constructor failed"); - if (mService) - mService->AddEventQueueEntry(this); -} - -EventQueueEntry::~EventQueueEntry() -{ - if (mService) - mService->RemoveEventQueueEntry(this); - NS_IF_RELEASE(mQueue); -} - -// Return the active event queue on our chain -nsIEventQueue* EventQueueEntry::GetEventQueue(void) -{ - nsIEventQueue* answer = NULL; - - if (mQueue) { - nsCOMPtr ourChain(do_QueryInterface(mQueue)); - if (ourChain) - ourChain->GetYoungest(&answer); - else { - NS_ADDREF(mQueue); - answer = mQueue; - } - } - return answer; -} - -nsresult EventQueueEntry::MakeNewQueue(PRThread* thread, - PRBool aNative, - nsIEventQueue **aQueue) -{ - nsIEventQueue *queue = 0; - nsresult rv; - - rv = nsComponentManager::CreateInstance(kEventQueueCID, NULL, - NS_GET_IID(nsIEventQueue), (void**) &queue); - - if (NS_SUCCEEDED(rv)) { - rv = queue->InitFromPRThread(thread, aNative); - if (NS_FAILED(rv)) { - NS_RELEASE(queue); - queue = 0; // redundant, but makes me feel better - } - } - *aQueue = queue; - return rv; -} - -nsresult EventQueueEntry::AddQueue(void) -{ - PRBool native; - nsIEventQueue *newQueue = NULL; - nsresult rv = NS_ERROR_NOT_INITIALIZED; - - if (mQueue) { - mQueue->IsQueueNative(&native); - rv = MakeNewQueue(PR_GetCurrentThread(), native, &newQueue); - - // add it to our chain of queues - if (NS_SUCCEEDED(rv)) { - nsCOMPtr ourChain(do_QueryInterface(mQueue)); - if (ourChain) - ourChain->AppendQueue(newQueue); - else - NS_RELEASE(newQueue); - } - } - return rv; -} - -void EventQueueEntry::RemoveQueue(nsIEventQueue *aQueue) -{ - aQueue->StopAcceptingEvents(); - NS_RELEASE(aQueue); - // it's now gone dark, and will be deleted and unlinked as soon as - // everyone else lets go -} - -// this is an apology for symmetry breaking between EventQueueEntry and nsEventQueueServiceImpl. -// the latter handles both sides of the dual data structure containing the former, those being -// nsEventQueueServiceImpl's hashtable and linked list, while the former contains the code -// for handling linked lists, on which the latter relies. if that was complicated, it's because -// it is, and thus the apology. -void EventQueueEntry::Link(EventQueueEntry *aAfter) -{ - if (aAfter) { - mNextEntry = aAfter->mNextEntry; - if (mNextEntry) - mNextEntry->mPrevEntry = this; - aAfter->mNextEntry = this; - } else - mNextEntry = 0; - mPrevEntry = aAfter; -} - -void EventQueueEntry::Unlink(void) -{ - if (mNextEntry) - mNextEntry->mPrevEntry = mPrevEntry; - if (mPrevEntry) - mPrevEntry->mNextEntry = mNextEntry; - mNextEntry = 0; - mPrevEntry = 0; -} - -//////////////////////////////////////////////////////////////////////////////// - -EventQueueEntryEnumerator::EventQueueEntryEnumerator() -{ - mCurrent = 0; -} - -EventQueueEntryEnumerator::~EventQueueEntryEnumerator() -{ -} - -void EventQueueEntryEnumerator::Reset(EventQueueEntry *aStart) -{ - mCurrent = aStart; -} - -void EventQueueEntryEnumerator::Skip(EventQueueEntry *aSkip) -{ - if (mCurrent == aSkip) - mCurrent = aSkip->Next(); -} - -EventQueueEntry * -EventQueueEntryEnumerator::Get(void) -{ - EventQueueEntry *rtnval = mCurrent; - if (mCurrent) - mCurrent = mCurrent->Next(); - return rtnval; -} - -//////////////////////////////////////////////////////////////////////////////// -/* TODO: unify the dual, redundant data structures holding EventQueueEntrys: - they're held simultaneously in both a hashtable and a linked list. -*/ - nsEventQueueServiceImpl::nsEventQueueServiceImpl() { NS_INIT_REFCNT(); - mEventQTable = new nsHashtable(16); mEventQMonitor = PR_NewMonitor(); - mBaseEntry = 0; #if defined(PR_LOGGING) && defined(DEBUG_danm) if (!gEventQueueLog) gEventQueueLog = PR_NewLogModule("nseventqueue"); #endif } +PRBool hash_enum_remove_queues(nsHashKey *aKey, void *aData, void* closure) +{ + // 'queue' should be the eldest queue. + nsIEventQueue *tmpQueue = (nsIEventQueue*)aData; + + nsCOMPtr pie(do_QueryInterface(tmpQueue)); + nsCOMPtr q; + + // stop accepting events for youngest to oldest + pie->GetYoungest(getter_AddRefs(q)); + while (q) { + q->StopAcceptingEvents(); + + nsCOMPtr pq(do_QueryInterface(q)); + pq->GetElder(getter_AddRefs(q)); + } + + return PR_TRUE; +} + nsEventQueueServiceImpl::~nsEventQueueServiceImpl() { - EventQueueEntry *entry; - - // Destroy any remaining PLEventQueues - mEnumerator.Reset(mBaseEntry); - while ((entry = mEnumerator.Get()) != 0) - delete entry; - - delete mEventQTable; + // XXX make it so we only enum over this once + mEventQTable.Enumerate(hash_enum_remove_queues, nsnull); // call StopAcceptingEvents on everything + mEventQTable.Reset(); // this should release all the PR_DestroyMonitor(mEventQMonitor); } @@ -321,8 +140,8 @@ nsEventQueueServiceImpl::CreateMonitoredThreadEventQueue() } NS_IMETHODIMP -nsEventQueueServiceImpl::CreateFromIThread( - nsIThread *aThread, PRBool aNative, nsIEventQueue **aResult) +nsEventQueueServiceImpl::CreateFromIThread(nsIThread *aThread, PRBool aNative, + nsIEventQueue **aResult) { nsresult rv; PRThread *prThread; @@ -331,94 +150,70 @@ nsEventQueueServiceImpl::CreateFromIThread( if (NS_SUCCEEDED(rv)) { rv = CreateEventQueue(prThread, aNative); // addrefs if (NS_SUCCEEDED(rv)) - rv = GetThreadEventQueue(prThread, aResult); // doesn't addref + rv = GetThreadEventQueue(prThread, aResult); // addrefs } return rv; } +// private method +NS_IMETHODIMP +nsEventQueueServiceImpl::MakeNewQueue(PRThread* thread, + PRBool aNative, + nsIEventQueue **aQueue) +{ + nsresult rv; + nsCOMPtr queue = do_CreateInstance(kEventQueueCID, &rv); + + if (NS_SUCCEEDED(rv)) { + rv = queue->InitFromPRThread(thread, aNative); + } + *aQueue = queue; + NS_IF_ADDREF(*aQueue); + return rv; +} + +// private method NS_IMETHODIMP nsEventQueueServiceImpl::CreateEventQueue(PRThread *aThread, PRBool aNative) { nsresult rv = NS_OK; ThreadKey key(aThread); - EventQueueEntry* evQueueEntry; + nsCOMPtr queue; /* Enter the lock which protects the EventQ hashtable... */ PR_EnterMonitor(mEventQMonitor); /* create only one event queue chain per thread... */ - evQueueEntry = (EventQueueEntry*)mEventQTable->Get(&key); - if (NULL == evQueueEntry) { - evQueueEntry = new EventQueueEntry(this, key, aNative); - if (NULL == evQueueEntry) { - rv = NS_ERROR_OUT_OF_MEMORY; - goto done; - } - } - NS_ADDREF(evQueueEntry); + queue = getter_AddRefs((nsIEventQueue*)mEventQTable.Get(&key)); + + if (!queue) { + // we don't have one in the table + rv = MakeNewQueue(PR_GetCurrentThread(), aNative, getter_AddRefs(queue)); // create new queue + mEventQTable.Put(&key, queue); // add to the table (initial addref) + } -done: // Release the EventQ lock... PR_ExitMonitor(mEventQMonitor); return rv; } -void -nsEventQueueServiceImpl::AddEventQueueEntry(EventQueueEntry *aEntry) -{ - EventQueueEntry *last, *current; - - // add to the hashtable, then to the end of the linked list - mEventQTable->Put(aEntry->TheThreadKey(), aEntry); - if (mBaseEntry) { - for (last = 0, current = mBaseEntry; current; current = current->Next()) - last = current; - aEntry->Link(last); - } else - mBaseEntry = aEntry; -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PLEventQueue *equeue; - nsCOMPtr iqueue = aEntry->GetEventQueue(); - iqueue->GetPLEventQueue(&equeue); - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Service add queue entry [queue=%lx]",(long)equeue)); - ++gEventQueueLogCount; -#endif -} - -void -nsEventQueueServiceImpl::RemoveEventQueueEntry(EventQueueEntry *aEntry) -{ - mEventQTable->Remove(aEntry->TheThreadKey()); - if (mBaseEntry == aEntry) - mBaseEntry = aEntry->Next(); - mEnumerator.Skip(aEntry); - aEntry->Unlink(); -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PLEventQueue *equeue; - nsCOMPtr iqueue = aEntry->GetEventQueue(); - iqueue->GetPLEventQueue(&equeue); - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Service remove queue entry [queue=%lx]",(long)equeue)); - ++gEventQueueLogCount; -#endif -} NS_IMETHODIMP nsEventQueueServiceImpl::DestroyThreadEventQueue(void) { nsresult rv = NS_OK; ThreadKey key(PR_GetCurrentThread()); - EventQueueEntry* evQueueEntry; /* Enter the lock which protects the EventQ hashtable... */ PR_EnterMonitor(mEventQMonitor); - evQueueEntry = (EventQueueEntry*)mEventQTable->Get(&key); - if (NULL != evQueueEntry) - NS_RELEASE(evQueueEntry); - else - rv = NS_ERROR_FAILURE; + nsCOMPtr queue; + queue = getter_AddRefs((nsIEventQueue*)mEventQTable.Get(&key)); // remove nsIEventQueue from hash table (releases) + if (queue) { + queue->StopAcceptingEvents(); // tell the queue to stop accepting events + queue = nsnull; // release the ref we hold on to now so that the queue might go away when we release below + mEventQTable.Remove(&key); // remove nsIEventQueue from hash table (releases) + } // Release the EventQ lock... PR_ExitMonitor(mEventQMonitor); @@ -430,21 +225,38 @@ nsEventQueueServiceImpl::CreateFromPLEventQueue(PLEventQueue* aPLEventQueue, nsI { // Create our thread queue using the component manager nsresult rv; - nsIEventQueue* aQueue; - if (NS_FAILED(rv = nsComponentManager::CreateInstance(kEventQueueCID, NULL, NS_GET_IID(nsIEventQueue), - (void**)&aQueue))) { - return rv; - } + nsCOMPtr queue = do_CreateInstance(kEventQueueCID, &rv); + if (NS_FAILED(rv)) return rv; - if (NS_FAILED(rv = aQueue->InitFromPLQueue(aPLEventQueue))) { - NS_IF_RELEASE(aQueue); - return rv; - } + rv = queue->InitFromPLQueue(aPLEventQueue); + if (NS_FAILED(rv)) return rv; - *aResult = aQueue; + *aResult = queue; + NS_IF_ADDREF(*aResult); return NS_OK; } + +// Return the active event queue on our chain +/* inline */ +nsresult nsEventQueueServiceImpl::GetYoungestEventQueue(nsIEventQueue *queue, nsIEventQueue **aResult) +{ + nsCOMPtr answer; + + if (queue) { + nsCOMPtr ourChain(do_QueryInterface(queue)); + if (ourChain) + ourChain->GetYoungest(getter_AddRefs(answer)); + else + answer = queue; + } + + *aResult = answer; + NS_IF_ADDREF(*aResult); + return NS_OK; +} + + // create new event queue, append it to the current thread's chain of event queues. // return it, addrefed. NS_IMETHODIMP @@ -452,43 +264,49 @@ nsEventQueueServiceImpl::PushThreadEventQueue(nsIEventQueue **aNewQueue) { nsresult rv = NS_OK; ThreadKey key(PR_GetCurrentThread()); - EventQueueEntry* evQueueEntry; + PRBool native = PR_TRUE; // native by default as per old comment + NS_ASSERTION(aNewQueue, "PushThreadEventQueue called with null param"); - *aNewQueue = NULL; /* Enter the lock which protects the EventQ hashtable... */ PR_EnterMonitor(mEventQMonitor); - evQueueEntry = (EventQueueEntry*)mEventQTable->Get(&key); - NS_ASSERTION(evQueueEntry, "pushed event queue on top of nothing"); - if (NULL == evQueueEntry) { - // shouldn't happen. as a fallback, we guess you wanted a native queue - evQueueEntry = new EventQueueEntry(this, key, PR_TRUE); - if (NULL == evQueueEntry) { - rv = NS_ERROR_OUT_OF_MEMORY; - goto done; + nsCOMPtr queue = getter_AddRefs((nsIEventQueue*)mEventQTable.Get(&key)); + NS_ASSERTION(queue, "pushed event queue on top of nothing"); + + if (queue) { // find out what kind of queue our relatives are + nsCOMPtr youngQueue; + GetYoungestEventQueue(queue, getter_AddRefs(youngQueue)); + if (youngQueue) { + queue->IsQueueNative(&native); } } - else { - // An entry was already present. We need to push a new - // queue onto our stack. - rv = evQueueEntry->AddQueue(); + + nsCOMPtr newQueue; + MakeNewQueue(key.id, native, getter_AddRefs(newQueue)); // create new queue + + if (!queue) { + // shouldn't happen. as a fallback, we guess you wanted a native queue + mEventQTable.Put(&key, newQueue); } - if (NS_SUCCEEDED(rv)) { - *aNewQueue = evQueueEntry->GetEventQueue(); - NS_ADDREF(evQueueEntry); + // append to the event queue chain + nsCOMPtr ourChain(do_QueryInterface(queue)); // QI the queue in the hash table + if (ourChain) + ourChain->AppendQueue(newQueue); // append new queue to it + + *aNewQueue = newQueue; + NS_IF_ADDREF(*aNewQueue); + #if defined(PR_LOGGING) && defined(DEBUG_danm) - PLEventQueue *equeue; - (*aNewQueue)->GetPLEventQueue(&equeue); - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Service push queue [queue=%lx]",(long)equeue)); - ++gEventQueueLogCount; + PLEventQueue *equeue; + (*aNewQueue)->GetPLEventQueue(&equeue); + PR_LOG(gEventQueueLog, PR_LOG_DEBUG, + ("EventQueue: Service push queue [queue=%lx]",(long)equeue)); + ++gEventQueueLogCount; #endif - } -done: // Release the EventQ lock... PR_ExitMonitor(mEventQMonitor); return rv; @@ -500,27 +318,27 @@ nsEventQueueServiceImpl::PopThreadEventQueue(nsIEventQueue *aQueue) { nsresult rv = NS_OK; ThreadKey key(PR_GetCurrentThread()); - EventQueueEntry* evQueueEntry; /* Enter the lock which protects the EventQ hashtable... */ PR_EnterMonitor(mEventQMonitor); - evQueueEntry = (EventQueueEntry*)mEventQTable->Get(&key); - if (NULL != evQueueEntry) { - nsrefcnt refcnt; - NS_RELEASE2(evQueueEntry, refcnt); - // If this wasn't the last reference, we must be popping. - if (refcnt > 0) { + nsCOMPtr queue = getter_AddRefs((nsIEventQueue*)mEventQTable.Get(&key)); // addrefs + if (queue) { #if defined(PR_LOGGING) && defined(DEBUG_danm) - PLEventQueue *equeue; - aQueue->GetPLEventQueue(&equeue); - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Service pop queue [queue=%lx]",(long)equeue)); + PLEventQueue *equeue; + aQueue->GetPLEventQueue(&equeue); + PR_LOG(gEventQueueLog, PR_LOG_DEBUG, + ("EventQueue: Service pop queue [queue=%lx]",(long)equeue)); ++gEventQueueLogCount; #endif - evQueueEntry->RemoveQueue(aQueue); + aQueue->StopAcceptingEvents(); + + if (aQueue == queue.get()) { // are we reomving the eldest queue? + mEventQTable.Remove(&key); // remove nsIEventQueue from hash table (releases) } + + // should we release aQueue ?? hmm... only if it is in the hash table i think } else { rv = NS_ERROR_FAILURE; } @@ -534,7 +352,6 @@ NS_IMETHODIMP nsEventQueueServiceImpl::GetThreadEventQueue(PRThread* aThread, nsIEventQueue** aResult) { nsresult rv = NS_OK; - EventQueueEntry* evQueueEntry; /* Parameter validation... */ if (NULL == aResult) return NS_ERROR_NULL_POINTER; @@ -545,7 +362,7 @@ nsEventQueueServiceImpl::GetThreadEventQueue(PRThread* aThread, nsIEventQueue** { keyThread = PR_GetCurrentThread(); } - else if (keyThread == NS_UI_THREAD) + else if (keyThread == NS_UI_THREAD) { nsCOMPtr mainIThread; @@ -562,12 +379,15 @@ nsEventQueueServiceImpl::GetThreadEventQueue(PRThread* aThread, nsIEventQueue** /* Enter the lock which protects the EventQ hashtable... */ PR_EnterMonitor(mEventQMonitor); - evQueueEntry = (EventQueueEntry*)mEventQTable->Get(&key); - + nsCOMPtr queue = getter_AddRefs((nsIEventQueue*)mEventQTable.Get(&key)); + PR_ExitMonitor(mEventQMonitor); - if (NULL != evQueueEntry) { - *aResult = evQueueEntry->GetEventQueue(); // Queue addrefing is done by this call. + if (queue) { + nsCOMPtr youngestQueue; + GetYoungestEventQueue(queue, getter_AddRefs(youngestQueue)); // get the youngest active queue + *aResult = youngestQueue; + NS_IF_ADDREF(*aResult); } else { // XXX: Need error code for requesting an event queue when none exists... *aResult = NULL; @@ -581,16 +401,14 @@ nsEventQueueServiceImpl::GetThreadEventQueue(PRThread* aThread, nsIEventQueue** NS_IMETHODIMP nsEventQueueServiceImpl::ResolveEventQueue(nsIEventQueue* queueOrConstant, nsIEventQueue* *resultQueue) { - if (queueOrConstant == NS_CURRENT_EVENTQ) - { - return GetThreadEventQueue(NS_CURRENT_THREAD, resultQueue); - } - else if (queueOrConstant == NS_UI_THREAD_EVENTQ) - { - return GetThreadEventQueue(NS_UI_THREAD, resultQueue); - } + if (queueOrConstant == NS_CURRENT_EVENTQ) { + return GetThreadEventQueue(NS_CURRENT_THREAD, resultQueue); + } + else if (queueOrConstant == NS_UI_THREAD_EVENTQ) { + return GetThreadEventQueue(NS_UI_THREAD, resultQueue); + } - *resultQueue = queueOrConstant; - NS_ADDREF(*resultQueue); - return NS_OK; + *resultQueue = queueOrConstant; + NS_ADDREF(*resultQueue); + return NS_OK; } diff --git a/mozilla/xpcom/threads/nsEventQueueService.h b/mozilla/xpcom/threads/nsEventQueueService.h index c5ef2962533..39174e9a6eb 100644 --- a/mozilla/xpcom/threads/nsEventQueueService.h +++ b/mozilla/xpcom/threads/nsEventQueueService.h @@ -27,25 +27,11 @@ #include "nsHashtable.h" class nsIEventQueue; -class EventQueueEntry; - -// because available enumerators can't handle deletions during enumeration -class EventQueueEntryEnumerator { -public: - EventQueueEntryEnumerator(); - virtual ~EventQueueEntryEnumerator(); - void Reset(EventQueueEntry *aStart); - EventQueueEntry *Get(void); - void Skip(EventQueueEntry *aSkip); -private: - EventQueueEntry *mCurrent; -}; //////////////////////////////////////////////////////////////////////////////// class nsEventQueueServiceImpl : public nsIEventQueueService { -friend class EventQueueEntry; public: nsEventQueueServiceImpl(); virtual ~nsEventQueueServiceImpl(); @@ -76,13 +62,11 @@ private: Addref the descriptor in any case. parameter aNative is ignored if the queue already exists. */ NS_IMETHOD CreateEventQueue(PRThread *aThread, PRBool aNative); - void AddEventQueueEntry(EventQueueEntry *aEntry); - void RemoveEventQueueEntry(EventQueueEntry *aEntry); + NS_IMETHOD MakeNewQueue(PRThread* thread, PRBool aNative, nsIEventQueue **aQueue); + inline nsresult GetYoungestEventQueue(nsIEventQueue *queue, nsIEventQueue **aResult); - nsHashtable *mEventQTable; - EventQueueEntry *mBaseEntry; - PRMonitor *mEventQMonitor; - EventQueueEntryEnumerator mEnumerator; + nsSupportsHashtable mEventQTable; + PRMonitor *mEventQMonitor; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/xpcom/threads/nsPIEventQueueChain.h b/mozilla/xpcom/threads/nsPIEventQueueChain.h index 14cbe3acf4a..03eae8553c9 100644 --- a/mozilla/xpcom/threads/nsPIEventQueueChain.h +++ b/mozilla/xpcom/threads/nsPIEventQueueChain.h @@ -68,7 +68,10 @@ public: NS_IMETHOD GetYoungestActive(nsIEventQueue **aQueue) = 0; NS_IMETHOD SetYounger(nsPIEventQueueChain *aQueue) = 0; + NS_IMETHOD GetYounger(nsIEventQueue **aQueue) = 0; + NS_IMETHOD SetElder(nsPIEventQueueChain *aQueue) = 0; + NS_IMETHOD GetElder(nsIEventQueue **aQueue) = 0; }; #endif /* nsPIEventQueueChain_h___ */ diff --git a/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp b/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp index 02000ef2beb..27bf8611b5b 100644 --- a/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp +++ b/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp @@ -189,8 +189,8 @@ public: ~stEventQueueStack(); nsresult Success() const { return mPushedStack; } private: - nsIEventQueueService *mService; - nsIEventQueue *mQueue; + nsCOMPtr mService; + nsCOMPtr mQueue; nsresult mGotService, mPushedStack; }; @@ -198,20 +198,16 @@ stEventQueueStack::stEventQueueStack() { // ick! this makes bad assumptions about the structure of the service, but // the service manager seems to need to work this way... - mGotService = nsServiceManager::GetService(kEventQueueServiceCID, - NS_GET_IID(nsIEventQueueService), - (nsISupports **) &mService); + mService = do_GetService(kEventQueueServiceCID, &mGotService); + mPushedStack = mGotService; if (NS_SUCCEEDED(mGotService)) - mService->PushThreadEventQueue(&mQueue); + mService->PushThreadEventQueue(getter_AddRefs(mQueue)); } stEventQueueStack::~stEventQueueStack() { if (NS_SUCCEEDED(mPushedStack)) mService->PopThreadEventQueue(mQueue); // more ick! - if (NS_SUCCEEDED(mGotService)) - nsServiceManager::ReleaseService(kEventQueueServiceCID, - NS_STATIC_CAST(nsISupports *, mService)); } nsWebShellWindow::nsWebShellWindow() : nsXULWindow() diff --git a/mozilla/xpfe/appshell/src/nsXULWindow.cpp b/mozilla/xpfe/appshell/src/nsXULWindow.cpp index 67e4c980618..b58f869c6c0 100644 --- a/mozilla/xpfe/appshell/src/nsXULWindow.cpp +++ b/mozilla/xpfe/appshell/src/nsXULWindow.cpp @@ -1362,7 +1362,7 @@ nsEventQueueStack::nsEventQueueStack() : mQueue(nsnull) mService = do_GetService(kEventQueueServiceCID); if(mService) - mService->PushThreadEventQueue(&mQueue); + mService->PushThreadEventQueue(getter_AddRefs(mQueue)); } nsEventQueueStack::~nsEventQueueStack() { diff --git a/mozilla/xpfe/appshell/src/nsXULWindow.h b/mozilla/xpfe/appshell/src/nsXULWindow.h index be3e69ae451..b805777e748 100644 --- a/mozilla/xpfe/appshell/src/nsXULWindow.h +++ b/mozilla/xpfe/appshell/src/nsXULWindow.h @@ -137,7 +137,7 @@ public: protected: nsCOMPtr mService; - nsIEventQueue *mQueue; + nsCOMPtr mQueue; }; #endif /* nsXULWindow_h__ */