diff --git a/mailnews/imap/src/nsImapProtocol.cpp b/mailnews/imap/src/nsImapProtocol.cpp index e42ee17f677..79600626fbe 100644 --- a/mailnews/imap/src/nsImapProtocol.cpp +++ b/mailnews/imap/src/nsImapProtocol.cpp @@ -316,8 +316,7 @@ nsresult nsImapProtocol::Initialize(nsIImapHostSessionList * aHostSessionList, n // PR_UNJOINABLE_THREAD, 0); nsIThread* workerThread = nsnull; - nsresult rv = NS_NewThread(&workerThread, this, 0, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, - PR_UNJOINABLE_THREAD); + nsresult rv = NS_NewThread(&workerThread, this); if (NS_FAILED(rv)) { NS_ASSERTION(workerThread, "Unable to create imap thread.\n"); diff --git a/xpcom/build/nsXPComInit.cpp b/xpcom/build/nsXPComInit.cpp index 894529a1dc0..4d275eec7f9 100644 --- a/xpcom/build/nsXPComInit.cpp +++ b/xpcom/build/nsXPComInit.cpp @@ -48,6 +48,8 @@ #include "nsFileSpecImpl.h" +#include "nsThread.h" + // base static NS_DEFINE_CID(kAllocatorCID, NS_ALLOCATOR_CID); // ds @@ -88,6 +90,8 @@ static NS_DEFINE_CID(kGenericFactoryCID, NS_GENERICFACTORY_CID); // threads static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kEventQueueCID, NS_EVENTQUEUE_CID); +static NS_DEFINE_CID(kThreadCID, NS_THREAD_CID); +static NS_DEFINE_CID(kThreadPoolCID, NS_THREADPOOL_CID); // proxy static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); @@ -321,6 +325,18 @@ nsresult NS_COM NS_InitXPCOM(nsIServiceManager* *result, nsEventQueueImpl::Create); if (NS_FAILED(rv)) return rv; + rv = RegisterGenericFactory(compMgr, kThreadCID, + NS_THREAD_CLASSNAME, + NS_THREAD_PROGID, + nsThread::Create); + if (NS_FAILED(rv)) return rv; + + rv = RegisterGenericFactory(compMgr, kThreadPoolCID, + NS_THREADPOOL_CLASSNAME, + NS_THREADPOOL_PROGID, + nsThreadPool::Create); + if (NS_FAILED(rv)) return rv; + rv = RegisterGenericFactory(compMgr, kProxyObjectManagerCID, NS_XPCOMPROXY_CLASSNAME, diff --git a/xpcom/tests/TestBuffers.cpp b/xpcom/tests/TestBuffers.cpp index bf1db8af482..8a4c1f4eca4 100644 --- a/xpcom/tests/TestBuffers.cpp +++ b/xpcom/tests/TestBuffers.cpp @@ -108,7 +108,7 @@ WriteMessages(nsIBuffer* buffer) nsIThread* thread; Reader* reader = new Reader(buffer); NS_ADDREF(reader); - rv = NS_NewThread(&thread, reader); + rv = NS_NewThread(&thread, reader, 0, PR_JOINABLE_THREAD); if (NS_FAILED(rv)) { printf("failed to create thread\n"); return rv; diff --git a/xpcom/tests/TestPipes.cpp b/xpcom/tests/TestPipes.cpp index 44e6adf99ff..69de53ffbfb 100644 --- a/xpcom/tests/TestPipes.cpp +++ b/xpcom/tests/TestPipes.cpp @@ -104,7 +104,7 @@ TestPipe(nsIInputStream* in, nsIOutputStream* out) if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(receiver); - rv = NS_NewThread(&thread, receiver); + rv = NS_NewThread(&thread, receiver, 0, PR_JOINABLE_THREAD); if (NS_FAILED(rv)) return rv; PRUint32 total = 0; @@ -214,7 +214,7 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out) if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(receiver); - rv = NS_NewThread(&thread, receiver); + rv = NS_NewThread(&thread, receiver, 0, PR_JOINABLE_THREAD); if (NS_FAILED(rv)) return rv; PRUint32 total = 0; @@ -419,7 +419,7 @@ TestChainedPipes() if (pump == nsnull) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(pump); - rv = NS_NewThread(&thread, pump); + rv = NS_NewThread(&thread, pump, 0, PR_JOINABLE_THREAD); if (NS_FAILED(rv)) return rv; nsIThread* receiverThread; @@ -427,7 +427,7 @@ TestChainedPipes() if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(receiver); - rv = NS_NewThread(&receiverThread, receiver); + rv = NS_NewThread(&receiverThread, receiver, 0, PR_JOINABLE_THREAD); if (NS_FAILED(rv)) return rv; PRUint32 total = 0; diff --git a/xpcom/tests/TestThreads.cpp b/xpcom/tests/TestThreads.cpp index a824915590e..ecbf28b17c0 100644 --- a/xpcom/tests/TestThreads.cpp +++ b/xpcom/tests/TestThreads.cpp @@ -58,7 +58,7 @@ TestThreads() nsresult rv; nsIThread* runner; - rv = NS_NewThread(&runner, new nsRunner(0)); + rv = NS_NewThread(&runner, new nsRunner(0), 0, PR_JOINABLE_THREAD); if (NS_FAILED(rv)) { printf("failed to create thread\n"); return rv; @@ -97,8 +97,7 @@ TestThreads() //////////////////////////////////////////////////////////////////////////// // try an unjoinable thread - rv = NS_NewThread(&runner, new nsRunner(1), 0, - PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD); + rv = NS_NewThread(&runner, new nsRunner(1)); if (NS_FAILED(rv)) { printf("failed to create thread\n"); return rv; diff --git a/xpcom/threads/nsIThread.idl b/xpcom/threads/nsIThread.idl index b40701452d4..aa0f44f037d 100644 --- a/xpcom/threads/nsIThread.idl +++ b/xpcom/threads/nsIThread.idl @@ -17,15 +17,33 @@ */ #include "nsISupports.idl" + %{C++ #include "prthread.h" + +#define NS_THREAD_CID \ +{ /* 85CE5510-7808-11d3-A181-0050041CAF44 */ \ + 0x85ce5510, \ + 0x7808, \ + 0x11d3, \ + {0xa1, 0x81, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \ +} + +#define NS_THREAD_PROGID "component://netscape/thread" +#define NS_THREAD_CLASSNAME "Thread" +#if 0 +%} + +typedef PRUint32 PRThreadPriority; +typedef PRUint32 PRThreadScope; +typedef PRUint32 PRThreadState; + +%{C++ +#endif %} interface nsIRunnable; -native PRThreadPriority(PRThreadPriority); -native PRThreadScope(PRThreadScope); -native PRThreadState(PRThreadState); [ptr] native PRThread(PRThread); [scriptable, uuid(6be5e380-6886-11d3-9382-00104ba0fd40)] @@ -37,6 +55,11 @@ interface nsIThread : nsISupports readonly attribute PRThreadScope Scope; readonly attribute PRThreadState State; [noscript] PRThread GetPRThread(); + void Init(in nsIRunnable aRunnable, + in unsigned long aStackSize, + in PRThreadPriority aPriority, + in PRThreadScope aScope, + in PRThreadState aState); %{C++ // returns the nsIThread for the current thread: @@ -61,7 +84,14 @@ extern NS_COM nsresult NS_NewThread(nsIThread* *result, nsIRunnable* runnable, PRUint32 stackSize = 0, + PRThreadState state = PR_UNJOINABLE_THREAD, PRThreadPriority priority = PR_PRIORITY_NORMAL, - PRThreadScope scope = PR_GLOBAL_THREAD, - PRThreadState state = PR_JOINABLE_THREAD); + PRThreadScope scope = PR_GLOBAL_THREAD); + +extern NS_COM nsresult +NS_NewThread(nsIThread* *result, + PRUint32 stackSize = 0, + PRThreadState state = PR_UNJOINABLE_THREAD, + PRThreadPriority priority = PR_PRIORITY_NORMAL, + PRThreadScope scope = PR_GLOBAL_THREAD); %} diff --git a/xpcom/threads/nsIThreadPool.idl b/xpcom/threads/nsIThreadPool.idl index 568ef0efa29..1bfd239c52a 100644 --- a/xpcom/threads/nsIThreadPool.idl +++ b/xpcom/threads/nsIThreadPool.idl @@ -19,6 +19,23 @@ #include "nsISupports.idl" %{C++ #include "prthread.h" + +#define NS_THREADPOOL_CID \ +{ /* CC530631-7808-11d3-A181-0050041CAF44 */ \ + 0xcc530631, \ + 0x7808, \ + 0x11d3, \ + {0xa1, 0x81, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \ +} + +#define NS_THREADPOOL_PROGID "component://netscape/thread-pool" +#define NS_THREADPOOL_CLASSNAME "Thread Pool" +#if 0 +%} +typedef PRUint32 PRThreadPriority; +typedef PRUint32 PRThreadScope; +%{C++ +#endif %} interface nsIRunnable; @@ -29,6 +46,9 @@ interface nsIThreadPool : nsISupports void DispatchRequest(in nsIRunnable runnable); void ProcessPendingRequests(); void Shutdown(); + void Init(in unsigned long aStackSize, + in PRThreadPriority aPriority, + in PRThreadScope aScope); }; %{C++ diff --git a/xpcom/threads/nsThread.cpp b/xpcom/threads/nsThread.cpp index dacf328fe87..b66ce9b91bf 100644 --- a/xpcom/threads/nsThread.cpp +++ b/xpcom/threads/nsThread.cpp @@ -59,27 +59,6 @@ nsThread::nsThread() #endif /* PR_LOGGING */ } -nsresult -nsThread::Init(nsIRunnable* runnable, - PRUint32 stackSize, - PRThreadPriority priority, - PRThreadScope scope, - PRThreadState state) -{ - mRunnable = runnable; - - NS_ADDREF_THIS(); // released in nsThread::Exit - if (state == PR_JOINABLE_THREAD) - NS_ADDREF_THIS(); // released in nsThread::Join - mThread = PR_CreateThread(PR_USER_THREAD, Main, this, - priority, scope, state, stackSize); - PR_LOG(nsIThreadLog, PR_LOG_DEBUG, - ("nsIThread %p created\n", this)); - if (mThread == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - return NS_OK; -} - nsThread::~nsThread() { PR_LOG(nsIThreadLog, PR_LOG_DEBUG, @@ -116,6 +95,16 @@ nsThread::Exit(void* arg) NS_RELEASE(self); } +NS_METHOD +nsThread::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) +{ + nsThread* thread = new nsThread(); + if (!thread) return NS_ERROR_OUT_OF_MEMORY; + nsresult rv = thread->QueryInterface(aIID, aResult); + if (NS_FAILED(rv)) delete thread; + return rv; +} + NS_IMPL_ISUPPORTS1(nsThread, nsIThread) NS_IMETHODIMP @@ -193,13 +182,34 @@ nsThread::GetPRThread(PRThread* *result) return NS_OK; } +NS_IMETHODIMP +nsThread::Init(nsIRunnable* runnable, + PRUint32 stackSize, + PRThreadPriority priority, + PRThreadScope scope, + PRThreadState state) +{ + mRunnable = runnable; + + NS_ADDREF_THIS(); // released in nsThread::Exit + if (state == PR_JOINABLE_THREAD) + NS_ADDREF_THIS(); // released in nsThread::Join + mThread = PR_CreateThread(PR_USER_THREAD, Main, this, + priority, scope, state, stackSize); + PR_LOG(nsIThreadLog, PR_LOG_DEBUG, + ("nsIThread %p created\n", this)); + if (mThread == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; +} + NS_COM nsresult NS_NewThread(nsIThread* *result, nsIRunnable* runnable, PRUint32 stackSize, + PRThreadState state, PRThreadPriority priority, - PRThreadScope scope, - PRThreadState state) + PRThreadScope scope) { nsresult rv; nsThread* thread = new nsThread(); @@ -217,6 +227,21 @@ NS_NewThread(nsIThread* *result, return NS_OK; } +NS_COM nsresult +NS_NewThread(nsIThread* *result, + PRUint32 stackSize, + PRThreadState state, + PRThreadPriority priority, + PRThreadScope scope) +{ + nsThread* thread = new nsThread(); + if (thread == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(thread); + *result = thread; + return NS_OK; +} + //////////////////////////////////////////////////////////////////////////////// nsresult @@ -302,51 +327,6 @@ nsThreadPool::nsThreadPool(PRUint32 minThreads, PRUint32 maxThreads) NS_INIT_REFCNT(); } -nsresult -nsThreadPool::Init(PRUint32 stackSize, - PRThreadPriority priority, - PRThreadScope scope) -{ - nsresult rv; - - rv = NS_NewISupportsArray(getter_AddRefs(mThreads)); - if (NS_FAILED(rv)) return rv; - - rv = NS_NewISupportsArray(getter_AddRefs(mRequests)); - if (NS_FAILED(rv)) return rv; - - mRequestMonitor = PR_NewMonitor(); - if (mRequestMonitor == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - - PR_CEnterMonitor(this); - - for (PRUint32 i = 0; i < mMinThreads; i++) { - nsThreadPoolRunnable* runnable = - new nsThreadPoolRunnable(this); - if (runnable == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(runnable); - - nsIThread* thread; - - rv = NS_NewThread(&thread, runnable, stackSize, priority, scope, - PR_JOINABLE_THREAD); // needed for Shutdown - NS_RELEASE(runnable); - if (NS_FAILED(rv)) goto exit; - - rv = mThreads->AppendElement(thread) ? NS_OK : NS_ERROR_FAILURE; - NS_RELEASE(thread); - if (NS_FAILED(rv)) goto exit; - } - // wait for some worker thread to be ready - PR_CWait(this, PR_INTERVAL_NO_TIMEOUT); - - exit: - PR_CExitMonitor(this); - return rv; -} - nsThreadPool::~nsThreadPool() { if (mThreads) { @@ -431,6 +411,16 @@ nsThreadPool::GetRequest() return request; } +NS_METHOD +nsThreadPool::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) +{ + nsThreadPool* pool = new nsThreadPool(0, 4); + if (!pool) return NS_ERROR_OUT_OF_MEMORY; + nsresult rv = pool->QueryInterface(aIID, aResult); + if (NS_FAILED(rv)) delete pool; + return rv; +} + NS_IMETHODIMP nsThreadPool::ProcessPendingRequests() { @@ -494,6 +484,52 @@ nsThreadPool::Shutdown() return rv; } +NS_IMETHODIMP +nsThreadPool::Init(PRUint32 stackSize, + PRThreadPriority priority, + PRThreadScope scope) +{ + nsresult rv; + + rv = NS_NewISupportsArray(getter_AddRefs(mThreads)); + if (NS_FAILED(rv)) return rv; + + rv = NS_NewISupportsArray(getter_AddRefs(mRequests)); + if (NS_FAILED(rv)) return rv; + + mRequestMonitor = PR_NewMonitor(); + if (mRequestMonitor == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + PR_CEnterMonitor(this); + + for (PRUint32 i = 0; i < mMinThreads; i++) { + nsThreadPoolRunnable* runnable = + new nsThreadPoolRunnable(this); + if (runnable == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(runnable); + + nsIThread* thread; + + rv = NS_NewThread(&thread, runnable, stackSize, + PR_JOINABLE_THREAD, /* needed for Shutdown */ + priority, scope); + NS_RELEASE(runnable); + if (NS_FAILED(rv)) goto exit; + + rv = mThreads->AppendElement(thread) ? NS_OK : NS_ERROR_FAILURE; + NS_RELEASE(thread); + if (NS_FAILED(rv)) goto exit; + } + // wait for some worker thread to be ready + PR_CWait(this, PR_INTERVAL_NO_TIMEOUT); + + exit: + PR_CExitMonitor(this); + return rv; +} + NS_COM nsresult NS_NewThreadPool(nsIThreadPool* *result, PRUint32 minThreads, PRUint32 maxThreads, diff --git a/xpcom/threads/nsThread.h b/xpcom/threads/nsThread.h index 2946a1134e9..1b94e5d48cd 100644 --- a/xpcom/threads/nsThread.h +++ b/xpcom/threads/nsThread.h @@ -32,23 +32,12 @@ public: NS_DECL_ISUPPORTS // nsIThread methods: - NS_IMETHOD Join(); - NS_IMETHOD GetPriority(PRThreadPriority *result); - NS_IMETHOD SetPriority(PRThreadPriority value); - NS_IMETHOD Interrupt(); - NS_IMETHOD GetScope(PRThreadScope *result); - NS_IMETHOD GetState(PRThreadState *result); - NS_IMETHOD GetPRThread(PRThread* *result); - + NS_DECL_NSITHREAD + // nsThread methods: nsThread(); virtual ~nsThread(); - nsresult Init(nsIRunnable* runnable, - PRUint32 stackSize, - PRThreadPriority priority, - PRThreadScope scope, - PRThreadState state); nsresult RegisterThreadSelf(); void SetPRThread(PRThread* thread) { mThread = thread; } @@ -57,6 +46,8 @@ public: static PRUintn kIThreadSelfIndex; + static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + protected: PRThread* mThread; nsCOMPtr mRunnable; @@ -71,18 +62,15 @@ public: NS_DECL_ISUPPORTS // nsIThreadPool methods: - NS_IMETHOD DispatchRequest(nsIRunnable* runnable); - NS_IMETHOD ProcessPendingRequests(); - NS_IMETHOD Shutdown(); + NS_DECL_NSITHREADPOOL // nsThreadPool methods: nsThreadPool(PRUint32 minThreads, PRUint32 maxThreads); virtual ~nsThreadPool(); - nsresult Init(PRUint32 stackSize, - PRThreadPriority priority, - PRThreadScope scope); nsIRunnable* GetRequest(); + + static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); protected: nsCOMPtr mThreads; @@ -101,7 +89,7 @@ public: NS_DECL_ISUPPORTS // nsIRunnable methods: - NS_IMETHOD Run(); + NS_DECL_NSIRUNNABLE // nsThreadPoolRunnable methods: nsThreadPoolRunnable(nsThreadPool* pool);