diff --git a/base/tests/TestThreads.cpp b/base/tests/TestThreads.cpp new file mode 100644 index 000000000000..a9dc3c4b37a6 --- /dev/null +++ b/base/tests/TestThreads.cpp @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "nsIThread.h" +#include + +class nsRunner : public nsIRunnable { +public: + NS_DECL_ISUPPORTS + + NS_IMETHOD Run() { + printf("running %d\n", mNum); + nsIThread* thread; + nsresult rv = nsIThread::GetCurrent(&thread); + if (NS_FAILED(rv)) { + printf("failed to get current thread\n"); + return rv; + } + NS_RELEASE(thread); + + // if we don't do something slow, we'll never see the other + // worker threads run + PR_Sleep(100); + + return rv; + } + + nsRunner(int num) : mNum(num) { + NS_INIT_REFCNT(); + } + +protected: + int mNum; +}; + +NS_IMPL_ISUPPORTS(nsRunner, nsIRunnable::GetIID()); + +nsresult +TestThreads() +{ + nsresult rv; + + nsIThread* runner; + rv = NS_NewThread(&runner, new nsRunner(0)); + if (NS_FAILED(rv)) { + printf("failed to create thread\n"); + return rv; + } + + nsIThread* thread; + rv = nsIThread::GetCurrent(&thread); + if (NS_FAILED(rv)) { + printf("failed to get current thread\n"); + return rv; + } + + PRThreadScope scope; + rv = runner->GetScope(&scope); + if (NS_FAILED(rv)) { + printf("runner already exited\n"); + } + + rv = runner->Join(); // wait for the runner to die before quitting + if (NS_FAILED(rv)) { + printf("join failed\n"); + } + + rv = runner->GetScope(&scope); // this should fail after Join + if (NS_SUCCEEDED(rv)) { + printf("get scope failed\n"); + } + + rv = runner->Interrupt(); // this should fail after Join + if (NS_SUCCEEDED(rv)) { + printf("interrupt failed\n"); + } + + NS_RELEASE(runner); + NS_RELEASE(thread); + + //////////////////////////////////////////////////////////////////////////// + // try an unjoinable thread + rv = NS_NewThread(&runner, new nsRunner(1), 0, PR_USER_THREAD, + PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD); + if (NS_FAILED(rv)) { + printf("failed to create thread\n"); + return rv; + } + + rv = runner->Join(); // wait for the runner to die before quitting + if (NS_SUCCEEDED(rv)) { + printf("shouldn't have been able to join an unjoinable thread\n"); + } + NS_RELEASE(runner); + + return NS_OK; +} + +nsresult +TestThreadPools() +{ + nsIThreadPool* pool; + nsresult rv = NS_NewThreadPool(&pool, 4, 4); + if (NS_FAILED(rv)) { + printf("failed to create thead pool\n"); + return rv; + } + + for (PRUint32 i = 0; i < 100; i++) { + rv = pool->DispatchRequest(new nsRunner(i+2)); + } + rv = pool->Join(); + return rv; +} + +int +main() +{ + nsresult rv = TestThreads(); + if (NS_FAILED(rv)) return -1; + + rv = TestThreadPools(); + if (NS_FAILED(rv)) return -1; + + return 0; +} diff --git a/base/tests/makefile.win b/base/tests/makefile.win index 084aedbd064b..ae7dc770356f 100644 --- a/base/tests/makefile.win +++ b/base/tests/makefile.win @@ -25,6 +25,7 @@ PROG3 = .\$(OBJDIR)\TestCRT.exe PROG4 = .\$(OBJDIR)\FilesTest.exe PROG5 = .\$(OBJDIR)\PropertiesTest.exe PROG6 = .\$(OBJDIR)\TestAutoLock.exe +PROG7 = .\$(OBJDIR)\TestThreads.exe RESFILE = timer.res PROGRAMS = $(PROG0) $(PROG1) \ !ifdef MODULAR_NETLIB @@ -34,6 +35,7 @@ PROGRAMS = $(PROG0) $(PROG1) \ !endif $(PROG4) \ $(PROG6) \ + $(PROG7) \ $(NULL) LINCS=-I..\src -I$(PUBLIC)\xpcom -I$(PUBLIC)\netlib -I$(PUBLIC)\raptor @@ -64,6 +66,7 @@ install:: $(PROGRAMS) !endif $(MAKE_INSTALL) $(PROG4) $(DIST)\bin $(MAKE_INSTALL) $(PROG6) $(DIST)\bin + $(MAKE_INSTALL) $(PROG7) $(DIST)\bin clobber:: rm -f $(DIST)\bin\TimerTest.exe @@ -109,4 +112,6 @@ $(PROG5): $(OBJDIR) PropertiesTest.cpp $(PROG6): $(OBJDIR) TestAutoLock.cpp +$(PROG7): $(OBJDIR) TestThreads.cpp + diff --git a/xpcom/tests/TestThreads.cpp b/xpcom/tests/TestThreads.cpp new file mode 100644 index 000000000000..a9dc3c4b37a6 --- /dev/null +++ b/xpcom/tests/TestThreads.cpp @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "nsIThread.h" +#include + +class nsRunner : public nsIRunnable { +public: + NS_DECL_ISUPPORTS + + NS_IMETHOD Run() { + printf("running %d\n", mNum); + nsIThread* thread; + nsresult rv = nsIThread::GetCurrent(&thread); + if (NS_FAILED(rv)) { + printf("failed to get current thread\n"); + return rv; + } + NS_RELEASE(thread); + + // if we don't do something slow, we'll never see the other + // worker threads run + PR_Sleep(100); + + return rv; + } + + nsRunner(int num) : mNum(num) { + NS_INIT_REFCNT(); + } + +protected: + int mNum; +}; + +NS_IMPL_ISUPPORTS(nsRunner, nsIRunnable::GetIID()); + +nsresult +TestThreads() +{ + nsresult rv; + + nsIThread* runner; + rv = NS_NewThread(&runner, new nsRunner(0)); + if (NS_FAILED(rv)) { + printf("failed to create thread\n"); + return rv; + } + + nsIThread* thread; + rv = nsIThread::GetCurrent(&thread); + if (NS_FAILED(rv)) { + printf("failed to get current thread\n"); + return rv; + } + + PRThreadScope scope; + rv = runner->GetScope(&scope); + if (NS_FAILED(rv)) { + printf("runner already exited\n"); + } + + rv = runner->Join(); // wait for the runner to die before quitting + if (NS_FAILED(rv)) { + printf("join failed\n"); + } + + rv = runner->GetScope(&scope); // this should fail after Join + if (NS_SUCCEEDED(rv)) { + printf("get scope failed\n"); + } + + rv = runner->Interrupt(); // this should fail after Join + if (NS_SUCCEEDED(rv)) { + printf("interrupt failed\n"); + } + + NS_RELEASE(runner); + NS_RELEASE(thread); + + //////////////////////////////////////////////////////////////////////////// + // try an unjoinable thread + rv = NS_NewThread(&runner, new nsRunner(1), 0, PR_USER_THREAD, + PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD); + if (NS_FAILED(rv)) { + printf("failed to create thread\n"); + return rv; + } + + rv = runner->Join(); // wait for the runner to die before quitting + if (NS_SUCCEEDED(rv)) { + printf("shouldn't have been able to join an unjoinable thread\n"); + } + NS_RELEASE(runner); + + return NS_OK; +} + +nsresult +TestThreadPools() +{ + nsIThreadPool* pool; + nsresult rv = NS_NewThreadPool(&pool, 4, 4); + if (NS_FAILED(rv)) { + printf("failed to create thead pool\n"); + return rv; + } + + for (PRUint32 i = 0; i < 100; i++) { + rv = pool->DispatchRequest(new nsRunner(i+2)); + } + rv = pool->Join(); + return rv; +} + +int +main() +{ + nsresult rv = TestThreads(); + if (NS_FAILED(rv)) return -1; + + rv = TestThreadPools(); + if (NS_FAILED(rv)) return -1; + + return 0; +}