From 80f759cb8feade47d3e452dd815d550e92ae02ea Mon Sep 17 00:00:00 2001 From: "darin%meer.net" Date: Thu, 23 Feb 2006 22:41:23 +0000 Subject: [PATCH] fix critical bug git-svn-id: svn://10.0.0.236/branches/THREADS_20060213_BRANCH@191081 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/xpcom/io/nsStreamUtils.h | 10 +++---- mozilla/xpcom/threads/nsIThreadManager.idl | 4 +-- mozilla/xpcom/threads/nsThread.cpp | 6 ++-- mozilla/xpcom/threads/nsThreadPool.cpp | 33 ++++++++++++++++++---- 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/mozilla/xpcom/io/nsStreamUtils.h b/mozilla/xpcom/io/nsStreamUtils.h index cf08e49fc9b..178721cc343 100644 --- a/mozilla/xpcom/io/nsStreamUtils.h +++ b/mozilla/xpcom/io/nsStreamUtils.h @@ -54,12 +54,12 @@ class nsIDispatchTarget; * the proxy object is destroyed on. * * This function is designed to be used to implement AsyncWait when the - * aEventTarget parameter is non-null. + * aTarget parameter is non-null. */ extern NS_COM nsresult NS_NewInputStreamReadyEvent(nsIInputStreamCallback **aEvent, nsIInputStreamCallback *aNotify, - nsIDispatchTarget *aEventTarget); + nsIDispatchTarget *aTarget); /** * A "one-shot" proxy of the OnOutputStreamReady callback. The resulting @@ -69,12 +69,12 @@ NS_NewInputStreamReadyEvent(nsIInputStreamCallback **aEvent, * the proxy object is destroyed on. * * This function is designed to be used to implement AsyncWait when the - * aEventTarget parameter is non-null. + * aTarget parameter is non-null. */ extern NS_COM nsresult NS_NewOutputStreamReadyEvent(nsIOutputStreamCallback **aEvent, nsIOutputStreamCallback *aNotify, - nsIDispatchTarget *aEventTarget); + nsIDispatchTarget *aTarget); /* ------------------------------------------------------------------------- */ @@ -102,7 +102,7 @@ typedef void (* nsAsyncCopyCallbackFun)(void *closure, nsresult status); extern NS_COM nsresult NS_AsyncCopy(nsIInputStream *aSource, nsIOutputStream *aSink, - nsIDispatchTarget *aEventTarget, + nsIDispatchTarget *aTarget, nsAsyncCopyMode aMode = NS_ASYNCCOPY_VIA_READSEGMENTS, PRUint32 aChunkSize = 4096, nsAsyncCopyCallbackFun aCallbackFun = nsnull, diff --git a/mozilla/xpcom/threads/nsIThreadManager.idl b/mozilla/xpcom/threads/nsIThreadManager.idl index ed5c48440a0..d059f7d631a 100644 --- a/mozilla/xpcom/threads/nsIThreadManager.idl +++ b/mozilla/xpcom/threads/nsIThreadManager.idl @@ -86,8 +86,8 @@ interface nsIThreadManager : nsISupports nsIThread setCurrentThread(in nsIThread thread); /** - * This method returns true if the calling thread is the main thread of the + * This attribute is true if the calling thread is the main thread of the * application process. */ - boolean isMainThread(); + readonly attribute boolean isMainThread; }; diff --git a/mozilla/xpcom/threads/nsThread.cpp b/mozilla/xpcom/threads/nsThread.cpp index ee604a3b184..1681240d1b4 100644 --- a/mozilla/xpcom/threads/nsThread.cpp +++ b/mozilla/xpcom/threads/nsThread.cpp @@ -292,7 +292,7 @@ nsThread::PutTask(nsIRunnable *task, PRUint32 dispatchFlags) NS_IMETHODIMP nsThread::Dispatch(nsIRunnable *runnable, PRUint32 flags) { - LOG(("nsThread(%p) Dispatch [%p %x]\n", this, runnable, flags)); + LOG(("THRD(%p) Dispatch [%p %x]\n", this, runnable, flags)); NS_ENSURE_STATE(mThread); @@ -355,7 +355,7 @@ nsThread::Shutdown() NS_IMETHODIMP nsThread::RunNextTask(PRUint32 flags) { - LOG(("nsThread(%p) RunNextTask [%x]\n", this, flags)); + LOG(("THRD(%p) RunNextTask [%x]\n", this, flags)); NS_ENSURE_STATE(PR_GetCurrentThread() == mThread); NS_ENSURE_ARG(flags == RUN_NORMAL || flags == RUN_NO_WAIT); @@ -381,7 +381,7 @@ nsThread::RunNextTask(PRUint32 flags) nsresult rv = NS_OK; if (task) { - LOG(("nsThread(%p) running [%p]\n", this, task.get())); + LOG(("THRD(%p) running [%p]\n", this, task.get())); task->Run(); } else if (flags & RUN_NO_WAIT) { rv = NS_BASE_STREAM_WOULD_BLOCK; diff --git a/mozilla/xpcom/threads/nsThreadPool.cpp b/mozilla/xpcom/threads/nsThreadPool.cpp index d185afc01de..a254cd6d4dc 100644 --- a/mozilla/xpcom/threads/nsThreadPool.cpp +++ b/mozilla/xpcom/threads/nsThreadPool.cpp @@ -43,6 +43,12 @@ #include "nsAutoPtr.h" #include "nsAutoLock.h" #include "prinrval.h" +#include "prlog.h" + +#ifdef PR_LOGGING +static PRLogModuleInfo *sLog = PR_NewLogModule("nsThreadPool"); +#endif +#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args) // DESIGN: // o Allocate anonymous threads. @@ -82,6 +88,11 @@ nsThreadPool::PutTask(nsIRunnable *task) PRBool spawnThread = PR_FALSE; { nsAutoMonitor mon(mTasks.Monitor()); + + LOG(("THRD-P(%p) put [%d %d %d]\n", this, mIdleCount, mThreads.Count(), + mThreadLimit)); + NS_ASSERTION(mIdleCount <= (PRUint32) mThreads.Count(), "oops"); + // Make sure we have a thread to service this task. if (mIdleCount == 0 && mThreads.Count() < (PRInt32) mThreadLimit) spawnThread = PR_TRUE; @@ -89,6 +100,7 @@ nsThreadPool::PutTask(nsIRunnable *task) mTasks.PutTask(task); } + LOG(("THRD-P(%p) put [spawn=%d]\n", this, spawnThread)); if (!spawnThread) return NS_OK; @@ -105,6 +117,7 @@ nsThreadPool::PutTask(nsIRunnable *task) killThread = PR_TRUE; // okay, we don't need this thread anymore } } + LOG(("THRD-P(%p) put [%p kill=%d]\n", this, thread.get(), killThread)); if (killThread) { thread->Shutdown(); } else { @@ -117,6 +130,8 @@ nsThreadPool::PutTask(nsIRunnable *task) NS_IMETHODIMP nsThreadPool::Run() { + LOG(("THRD-P(%p) enter\n", this)); + nsCOMPtr current; nsThreadManager::get()->GetCurrentThread(getter_AddRefs(current)); @@ -138,10 +153,8 @@ nsThreadPool::Run() } else { if (wasIdle) { // if too many idle threads or idle for too long, then bail. - if (mIdleCount > mIdleThreadLimit || (now - idleSince) > timeout) { - --mIdleCount; + if (mIdleCount > mIdleThreadLimit || (now - idleSince) > timeout) exitThread = PR_TRUE; - } } else { // if would be too many idle threads... if (mIdleCount == mIdleThreadLimit) { @@ -155,24 +168,34 @@ nsThreadPool::Run() } if (exitThread) { + if (wasIdle) + --mIdleCount; mThreads.RemoveObject(current); } else { - mon.Wait(timeout - (now - idleSince)); + PRIntervalTime delta = timeout - (now - idleSince); + LOG(("THRD-P(%p) waiting [%d]\n", this, delta)); + mon.Wait(delta); } + } else if (wasIdle) { + wasIdle = PR_FALSE; + --mIdleCount; } } if (task) { - wasIdle = PR_FALSE; + LOG(("THRD-P(%p) running [%p]\n", this, task.get())); task->Run(); } } while (!exitThread); + LOG(("THRD-P(%p) leave\n", this)); return NS_OK; } NS_IMETHODIMP nsThreadPool::Dispatch(nsIRunnable *task, PRUint32 flags) { + LOG(("THRD-P(%p) dispatch [%p %x]\n", this, task, flags)); + NS_ENSURE_STATE(!mShutdown); if (flags == DISPATCH_NORMAL) {