1 #ifndef _beos_thread_manager_h_
2 #define _beos_thread_manager_h_
4 #include <cppunit/Exception.h>
5 #include <cppunit/TestResult.h>
10 // Pointer to a function that takes no parameters and
11 // returns no result. All threads must be implemented
12 // in a function of this type.
14 // Helper class to handle thread management
15 template <class TestClass
, class ExpectedException
>
16 class CPPUNIT_API BThreadManager
{
18 typedef void (TestClass::*ThreadMethod
)();
20 BThreadManager(std::string threadName
, TestClass
*object
, ThreadMethod method
, sem_id
&threadSem
);
23 status_t
LaunchThread(CppUnit::TestResult
*result
);
25 // Thread management methods
27 int32
WaitForThread();
30 std::string
getName() const { return fName
; }
37 CppUnit::TestResult
*fTestResult
;
40 static long EntryFunction(BThreadManager
<TestClass
, ExpectedException
>* manager
);
45 template <class TestClass
, class ExpectedException
>
46 BThreadManager
<TestClass
, ExpectedException
>::BThreadManager(
47 std::string threadName
,
57 , fThreadSem(threadSem
)
62 template <class TestClass
, class ExpectedException
>
63 BThreadManager
<TestClass
, ExpectedException
>::~BThreadManager() {
68 template <class TestClass
, class ExpectedException
>
70 BThreadManager
<TestClass
, ExpectedException
>::WaitForThread() {
72 if (find_thread(NULL
) != fID
)
73 wait_for_thread(fID
, &result
);
77 template <class TestClass
, class ExpectedException
>
79 BThreadManager
<TestClass
, ExpectedException
>::Stop() {
81 if (find_thread(NULL
) != fID
) {
86 result
= WaitForThread();
92 template <class TestClass
, class ExpectedException
>
94 BThreadManager
<TestClass
, ExpectedException
>::IsRunning(void) {
97 if (get_thread_info(fID
, &info
) == B_OK
)
106 template <class TestClass
, class ExpectedException
>
108 BThreadManager
<TestClass
, ExpectedException
>::LaunchThread(CppUnit::TestResult
*result
) {
110 return B_ALREADY_RUNNING
;
112 fTestResult
= result
;
113 fID
= spawn_thread((thread_entry
)(BThreadManager::EntryFunction
),
114 fName
.c_str(), B_NORMAL_PRIORITY
, this);
117 if (fID
== B_NO_MORE_THREADS
|| fID
== B_NO_MEMORY
) {
121 // Aquire the semaphore, then start the thread.
122 if (acquire_sem(fThreadSem
) != B_OK
)
123 throw CppUnit::Exception("BThreadManager::LaunchThread() -- Error acquiring thread semaphore");
124 err
= resume_thread(fID
);
130 template <class TestClass
, class ExpectedException
>
132 BThreadManager
<TestClass
, ExpectedException
>::EntryFunction(BThreadManager
<TestClass
, ExpectedException
> *manager
) {
137 template <class TestClass
, class ExpectedException
>
139 BThreadManager
<TestClass
, ExpectedException
>::Run(void) {
140 // These outer try/catch blocks handle unexpected exceptions.
141 // Said exceptions are caught and noted in the TestResult
142 // class, but not allowed to escape and disrupt the other
143 // threads that are assumingly running concurrently.
146 // Our parent ThreadedTestCaller should check fObject to be non-NULL,
147 // but we'll do it here too just to be sure.
149 throw CppUnit::Exception("BThreadManager::Run() -- NULL fObject pointer");
151 // Before running, we need to add this thread's name to
152 // the object's id->(name,subtestnum) map.
153 fObject
->InitThreadInfo(fID
, fName
);
155 // This inner try/catch block is for expected exceptions.
156 // If we get through it without an exception, we have to
157 // raise a different exception that makes note of the fact
158 // that the exception we were expecting didn't arrive. If
159 // no exception is expected, then nothing is done (see
160 // "cppunit/TestCaller.h" for detail on the classes used
161 // to handle this behaviour).
163 (fObject
->*fMethod
)();
164 } catch ( ExpectedException
& ) {
167 CppUnit::ExpectedExceptionTraits
<ExpectedException
>::expectedException();
169 } catch ( CppUnit::Exception
&e
) {
170 // Add on the thread name, then note the exception
171 CppUnit::Exception
*threadException
= new CppUnit::Exception(
172 std::string(e
.what()) + " (thread: " + fName
+ ")",
175 fTestResult
->addFailure( fObject
, threadException
);
177 catch ( std::exception
&e
) {
178 // Add on the thread name, then note the exception
179 CppUnit::Exception
*threadException
= new CppUnit::Exception(
180 std::string(e
.what()) + " (thread: " + fName
+ ")"
182 fTestResult
->addError( fObject
, threadException
);
185 // Add on the thread name, then note the exception
186 CppUnit::Exception
*threadException
= new CppUnit::Exception(
187 "caught unknown exception (thread: " + fName
+ ")"
189 fTestResult
->addError( fObject
, threadException
);
192 // Release the semaphore we acquired earlier
193 release_sem(fThreadSem
);