From 36abefe61ee39047f6a574eafb582981652f3050 Mon Sep 17 00:00:00 2001 From: "dougt%netscape.com" Date: Fri, 9 Aug 2002 04:03:45 +0000 Subject: [PATCH] Attempting to fix the idle time topcrash. b=155447, r=pavlov, sr=dveditz --- xpcom/threads/nsTimerImpl.cpp | 99 ++++++++++++++++------------------- xpcom/threads/nsTimerImpl.h | 7 ++- 2 files changed, 50 insertions(+), 56 deletions(-) diff --git a/xpcom/threads/nsTimerImpl.cpp b/xpcom/threads/nsTimerImpl.cpp index a5af3dd927f5..8d37cb015888 100644 --- a/xpcom/threads/nsTimerImpl.cpp +++ b/xpcom/threads/nsTimerImpl.cpp @@ -35,17 +35,16 @@ #include "nsTimerImpl.h" #include "TimerThread.h" +#include "nsAutoLock.h" -#include "nsSupportsArray.h" +#include "nsVoidArray.h" #include "nsIEventQueue.h" static TimerThread *gThread = nsnull; - // only the main thread supports idle timers. -static nsSupportsArray *gIdleTimers = nsnull; - static PRBool gFireOnIdle = PR_FALSE; +static nsTimerManager* gManager = nsnull; #include "prmem.h" #include "prinit.h" @@ -202,7 +201,6 @@ void nsTimerImpl::Shutdown() NS_RELEASE(gThread); gFireOnIdle = PR_FALSE; - NS_IF_RELEASE(gIdleTimers); } @@ -389,14 +387,9 @@ void* handleTimerEvent(TimerEventType* event) if (gFireOnIdle) { if (NS_STATIC_CAST(nsTimerImpl*, event->e.owner)->IsIdle()) { - nsCOMPtr currentThread, mainThread; - nsIThread::GetCurrent(getter_AddRefs(currentThread)); - nsIThread::GetMainThread(getter_AddRefs(mainThread)); - if (currentThread == mainThread) { - gIdleTimers->AppendElement(NS_STATIC_CAST(nsITimer*, NS_STATIC_CAST(nsTimerImpl*, event->e.owner))); - - return NULL; - } + NS_ASSERTION(gManager, "Global Thread Manager is null!"); + gManager->AddIdleTimer(NS_STATIC_CAST(nsTimerImpl*, event->e.owner)); + return nsnull; } } @@ -509,11 +502,23 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsTimerManager, nsITimerManager) nsTimerManager::nsTimerManager() { NS_INIT_REFCNT(); + mLock = PR_NewLock(); + gManager = this; } nsTimerManager::~nsTimerManager() { + gManager = nsnull; + PR_DestroyLock(mLock); + nsTimerImpl *theTimer; + PRInt32 count = mIdleTimers.Count(); + + for(PRInt32 i = 0; i<=count; i++) { + theTimer = NS_STATIC_CAST(nsTimerImpl*, mIdleTimers[0]); + mIdleTimers.RemoveElement(theTimer); + NS_IF_RELEASE(theTimer); + } } NS_IMETHODIMP nsTimerManager::SetUseIdleTimers(PRBool aUseIdleTimers) @@ -523,14 +528,6 @@ NS_IMETHODIMP nsTimerManager::SetUseIdleTimers(PRBool aUseIdleTimers) gFireOnIdle = aUseIdleTimers; - if (gFireOnIdle && !gIdleTimers) { - gIdleTimers = new nsSupportsArray(); - if (!gIdleTimers) - return NS_ERROR_OUT_OF_MEMORY; - - NS_ADDREF(gIdleTimers); - } - return NS_OK; } @@ -542,52 +539,44 @@ NS_IMETHODIMP nsTimerManager::GetUseIdleTimers(PRBool *aUseIdleTimers) NS_IMETHODIMP nsTimerManager::HasIdleTimers(PRBool *aHasTimers) { - *aHasTimers = PR_FALSE; - - if (!gFireOnIdle) - return NS_OK; - - nsCOMPtr currentThread, mainThread; - nsIThread::GetCurrent(getter_AddRefs(currentThread)); - nsIThread::GetMainThread(getter_AddRefs(mainThread)); - - if (currentThread != mainThread) { - return NS_OK; - } - - PRUint32 count; - gIdleTimers->Count(&count); + nsAutoLock lock (mLock); + PRUint32 count = mIdleTimers.Count(); *aHasTimers = (count != 0); + return NS_OK; +} +nsresult nsTimerManager::AddIdleTimer(nsITimer* timer) +{ + if (!timer) + return NS_ERROR_FAILURE; + nsAutoLock lock(mLock); + mIdleTimers.AppendElement(timer); + NS_ADDREF(timer); return NS_OK; } NS_IMETHODIMP nsTimerManager::FireNextIdleTimer() { - if (!gFireOnIdle) - return NS_OK; - - nsCOMPtr currentThread, mainThread; - nsIThread::GetCurrent(getter_AddRefs(currentThread)); - nsIThread::GetMainThread(getter_AddRefs(mainThread)); - - if (currentThread != mainThread) { + if (!gFireOnIdle || !nsIThread::IsMainThread()) { return NS_OK; } - PRUint32 count; - gIdleTimers->Count(&count); + nsTimerImpl *theTimer = nsnull; - if (count > 0) { - nsTimerImpl *theTimer = NS_STATIC_CAST(nsTimerImpl*, NS_STATIC_CAST(nsITimer*, gIdleTimers->ElementAt(0))); // addrefs - - gIdleTimers->RemoveElement(NS_STATIC_CAST(nsITimer*, theTimer), 0); - - theTimer->Fire(); - - NS_RELEASE(theTimer); + { + nsAutoLock lock (mLock); + PRUint32 count = mIdleTimers.Count(); + + if (count == 0) + return NS_OK; + + theTimer = NS_STATIC_CAST(nsTimerImpl*, mIdleTimers[0]); + mIdleTimers.RemoveElement(theTimer); } - // pull out each one starting at the beginning until no more are left and fire them. + + theTimer->Fire(); + + NS_RELEASE(theTimer); return NS_OK; } diff --git a/xpcom/threads/nsTimerImpl.h b/xpcom/threads/nsTimerImpl.h index 470644a3d7e5..ac632be75650 100644 --- a/xpcom/threads/nsTimerImpl.h +++ b/xpcom/threads/nsTimerImpl.h @@ -43,7 +43,7 @@ #include "nsITimer.h" #include "nsITimerCallback.h" #include "nsIScriptableTimer.h" - +#include "nsVoidArray.h" #include "nsIThread.h" #include "nsCOMPtr.h" @@ -181,6 +181,11 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSITIMERMANAGER + + nsresult AddIdleTimer(nsITimer* timer); +private: + PRLock *mLock; + nsVoidArray mIdleTimers; };