From 290dd746b0a8edd0bbd0df423b4d7de265f7ffc2 Mon Sep 17 00:00:00 2001 From: "waterson%netscape.com" Date: Tue, 22 Feb 2000 06:01:57 +0000 Subject: [PATCH] Bug 27855. Use an event instead of a timer to flush the event queue when the app is shutting down. r=syd, a=jevering. git-svn-id: svn://10.0.0.236/trunk@61422 18797224-902f-48f8-a5cc-f745e15eee43 --- .../xpfe/appshell/src/nsAppShellService.cpp | 71 ++++++++++++++----- mozilla/xpfe/appshell/src/nsAppShellService.h | 18 +++-- 2 files changed, 65 insertions(+), 24 deletions(-) diff --git a/mozilla/xpfe/appshell/src/nsAppShellService.cpp b/mozilla/xpfe/appshell/src/nsAppShellService.cpp index 5df6c3ae023..f720ad660be 100644 --- a/mozilla/xpfe/appshell/src/nsAppShellService.cpp +++ b/mozilla/xpfe/appshell/src/nsAppShellService.cpp @@ -33,7 +33,6 @@ #include "nsIObserver.h" #include "nsWeakReference.h" #include "nsXPComFactory.h" /* template implementation of a XPCOM factory */ -#include "nsITimer.h" #include "nsIAppShell.h" #include "nsIWidget.h" @@ -80,7 +79,7 @@ static NS_DEFINE_CID(kMetaCharsetCID, NS_META_CHARSET_CID); static char *gEQActivatedNotification = "nsIEventQueueActivated"; static char *gEQDestroyedNotification = "nsIEventQueueDestroyed"; -nsAppShellService::nsAppShellService() : mWindowMediator( NULL ) +nsAppShellService::nsAppShellService() : mWindowMediator( NULL ), mShuttingDown( PR_FALSE ) { NS_INIT_REFCNT(); @@ -407,12 +406,10 @@ nsAppShellService::Quit() // Quit the application. We will asynchronously call the appshell's // Exit() method via the ExitCallback() to allow one last pass // through any events in the queue. This guarantees a tidy cleanup. + nsresult rv = NS_OK; - if (! mShutdownTimer) { - // Only set the shutdown timer if it hasn't already been set. - nsresult rv; - rv = NS_NewTimer(getter_AddRefs(mShutdownTimer)); - if (NS_FAILED(rv)) return rv; + if (! mShuttingDown) { + mShuttingDown = PR_TRUE; // Enumerate through each open window and close it NS_WITH_SERVICE(nsIWindowMediator, windowMediator, kWindowMediatorCID, &rv); @@ -444,25 +441,63 @@ nsAppShellService::Quit() } // Note that we don't allow any premature returns from the above - // loop: no matter what, make sure we set the callback timer. If + // loop: no matter what, make sure we send the exit event. If // worst comes to worst, we'll do a leaky shutdown but we WILL - // shut down. - rv = mShutdownTimer->Init(ExitCallback, this, 0); + // shut down. Well, assuming that all *this* stuff works ;-). + nsCOMPtr svc = do_GetService(kEventQueueServiceCID, &rv); if (NS_FAILED(rv)) return rv; + + nsCOMPtr queue; + rv = svc->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); + if (NS_FAILED(rv)) return rv; + + ExitEvent* event = new ExitEvent; + if (! event) + return NS_ERROR_OUT_OF_MEMORY; + + PL_InitEvent(NS_REINTERPRET_CAST(PLEvent*, event), + nsnull, + HandleExitEvent, + DestroyExitEvent); + + event->mService = this; + NS_ADDREF(event->mService); + + rv = queue->EnterMonitor(); + if (NS_SUCCEEDED(rv)) { + rv = queue->PostEvent(NS_REINTERPRET_CAST(PLEvent*, event)); + } + (void) queue->ExitMonitor(); + + if (NS_FAILED(rv)) { + NS_RELEASE(event->mService); + delete event; + } } - return NS_OK; + return rv; +} + +void* +nsAppShellService::HandleExitEvent(PLEvent* aEvent) +{ + ExitEvent* event = NS_REINTERPRET_CAST(ExitEvent*, aEvent); + + // Tell the appshell to exit + event->mService->mAppShell->Exit(); + + // We're done "shutting down". + event->mService->mShuttingDown = PR_FALSE; + + return nsnull; } void -nsAppShellService::ExitCallback(nsITimer* aTimer, void* aClosure) +nsAppShellService::DestroyExitEvent(PLEvent* aEvent) { - nsAppShellService* svc = NS_REINTERPRET_CAST(nsAppShellService*, aClosure); - - // Tell the appshell to exit - svc->mAppShell->Exit(); - - svc->mShutdownTimer = nsnull; + ExitEvent* event = NS_REINTERPRET_CAST(ExitEvent*, aEvent); + NS_RELEASE(event->mService); + delete event; } NS_IMETHODIMP diff --git a/mozilla/xpfe/appshell/src/nsAppShellService.h b/mozilla/xpfe/appshell/src/nsAppShellService.h index df14b02cb3d..4c5bf3e13f9 100644 --- a/mozilla/xpfe/appshell/src/nsAppShellService.h +++ b/mozilla/xpfe/appshell/src/nsAppShellService.h @@ -27,7 +27,7 @@ #include "nsIObserver.h" #include "nsWeakReference.h" #include "nsIAppShell.h" -#include "nsITimer.h" +#include "plevent.h" class nsAppShellService : public nsIAppShellService, public nsIObserver, @@ -64,11 +64,17 @@ protected: PRBool mDeleteCalled; nsISplashScreen *mSplashScreen; - // The mShutdownTimer is set in Quit() to asynchronously call the - // ExitCallback(). This allows one last pass through any events in - // the event queue before shutting down the appshell. - nsCOMPtr mShutdownTimer; - static void ExitCallback(nsITimer* aTimer, void* aClosure); + // Set when the appshell service is going away. + PRBool mShuttingDown; + + // A "last event" that is used to flush the appshell's event queue. + struct ExitEvent { + PLEvent mEvent; + nsAppShellService* mService; + }; + + static void* HandleExitEvent(PLEvent* aEvent); + static void DestroyExitEvent(PLEvent* aEvent); }; #endif