Skip to content

Commit db0018f

Browse files
fixes #47 #48
* adjusted stacksize for mac os x * handling status error conditions. * fixed a nasty bug when calling thread::join() that did not properly handled the thread's retval.
1 parent bc377cb commit db0018f

File tree

3 files changed

+54
-26
lines changed

3 files changed

+54
-26
lines changed

include/pthread/thread.hpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,11 @@ namespace pthread {
121121
* If the target thread is already terminated, the method returns immediately.
122122
*
123123
* This method does not itself cause a thread to be terminated.
124-
*
124+
*
125+
* @return the value returned by the joined thread (calling pthread_exit(void *retval))
125126
* @throws pthread_exception if this is not a thread or if thread_id == this_thread::get_id().
126127
*/
127-
int join();
128+
void *join();
128129

129130
/** @return true if this thread can be joined.
130131
*/
@@ -166,10 +167,10 @@ namespace pthread {
166167
*/
167168
void swap ( thread& other );
168169

169-
pthread_t _thread;
170-
pthread_attr_t _attr;
170+
pthread_t _thread; //!< thread identifier
171+
pthread_attr_t _attr; //!< thread attributes (stack size, ...)
171172

172-
thread_status _status;
173+
thread_status _status; //!< thread status (@see thread_status)
173174
};
174175

175176
/** base class of a thread.
@@ -245,9 +246,15 @@ namespace pthread {
245246

246247
/** joins this thread.
247248
*
249+
* @return value returned by the joined thread (pthread_exit(void *retval))
248250
* @throw pthread_exception if deadlock conditions are detected.
249251
*/
250-
int join() { return _thread->join() ;};
252+
void *join() { return _thread->join() ;};
253+
254+
/** @return true if this thread can be joined.
255+
*/
256+
bool joinable() const { return _thread != 0 ;};
257+
251258

252259
private:
253260
pthread::thread *_thread;

src/thread.cpp

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "pthread/thread.hpp"
1010
#include <unistd.h>
11+
#include <cstdio>
1112

1213
namespace pthread {
1314

@@ -22,21 +23,36 @@ namespace pthread {
2223
}
2324
}
2425

25-
int thread::join () {
26-
int rc = 0;
27-
28-
if ( _thread == this_thread::get_id()){
29-
throw pthread_exception("join failed, join yourself would endup in deadlock.");
30-
}
31-
if ( _status == thread_status::not_a_thread ){
32-
throw pthread_exception("join failed, this is not a thread.");
33-
}
26+
void *thread::join () {
27+
int rc = 0;
28+
void *retval = 0;
3429

35-
if ( (rc = pthread_join(_thread, (void **)&_status)) != 0){
36-
throw thread_exception("pthread_join failed.", rc );
30+
#if __cplusplus < 201103L
31+
if ( _thread != NULL){
32+
#else
33+
if ( _thread != nullptr){
34+
#endif
35+
36+
if ( _thread == this_thread::get_id()){
37+
throw pthread_exception("join failed, join yourself would endup in deadlock.");
38+
}
39+
40+
if ( _status == thread_status::not_a_thread ){
41+
throw pthread_exception("join failed, this is not a thread.");
42+
}
43+
44+
if ( (rc = pthread_join(_thread, (void **)&retval)) != 0){
45+
switch ( rc ) {
46+
case EDEADLK:
47+
throw thread_exception("EDEADLKpthread_join failed because of deadlock conditions.", rc );
48+
case EINVAL:
49+
throw thread_exception("EINVEL pthread_join failed not a joinable thread.", rc );
50+
case ESRCH:
51+
break; // thread has already ended.
52+
}
53+
}
3754
}
38-
39-
return rc;
55+
return retval;
4056
}
4157

4258
int thread::cancel () {
@@ -72,7 +88,7 @@ namespace pthread {
7288
}
7389

7490
if ( stack_size > 0 && (rc = pthread_attr_setstacksize(&_attr, stack_size)) != 0 ){
75-
throw thread_exception("pthread_attr_setstacksize failed.", rc );
91+
throw thread_exception("bad stacksize, check size passed to thread::thread; thread not started.", rc );
7692
}
7793

7894
if ((rc = pthread_create(&_thread, &_attr, thread_startup_runnable, (void *) &work)) != 0){
@@ -128,7 +144,9 @@ namespace pthread {
128144
}
129145

130146
thread_group::~thread_group(){
147+
131148
while(! _threads.empty()){
149+
132150
#if __cplusplus < 201103L
133151
std::auto_ptr<pthread::abstract_thread> pat(_threads.front());
134152
#else
@@ -137,9 +155,11 @@ namespace pthread {
137155

138156
_threads.pop_front();
139157

140-
if ( _destructor_joins_first ){
158+
if ( _destructor_joins_first && pat->joinable() ){
141159
try {
142160
pat->join();
161+
} catch ( pthread_exception &err ){
162+
printf("thread_group destructor failed to join one thread. %s, (%d) %s.\n", err.what(), err.pthread_errno(), err.pthread_errmsg());
143163
} catch ( ... ){};
144164
}
145165
}
@@ -158,7 +178,9 @@ namespace pthread {
158178

159179
void thread_group::join(){
160180
for(auto iterator = _threads.begin(); iterator != _threads.end(); iterator++){
161-
(*iterator)->join();
181+
if ( (*iterator)->joinable() ){
182+
(*iterator)->join();
183+
}
162184
}
163185
}
164186

tests/without-cpp11-pthread-tests.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ void message ( const std::string m){
3434
class worker: public pthread::abstract_thread {
3535
public:
3636

37-
worker(const std::string m = "anonymous worker", int sleep = 2*1000):abstract_thread(8000000), msg(m), _sleep(sleep){
38-
// msg.resize(msg.size()+1);
37+
worker(const std::string &m = "anonymous worker", int sleep = 2*1000):abstract_thread(8388608), msg(m), _sleep(sleep){
3938
};
4039

4140
~worker(){
@@ -88,8 +87,8 @@ int main(int argc, const char * argv[]) {
8887
try {
8988
std::cout << "lib version: " << pthread::cpp_pthread_version() << std::endl;
9089

91-
int number_of_threads = 2;
92-
if ( argc > 0 ){
90+
int number_of_threads = 2;
91+
if ( argc > 1 ){
9392
number_of_threads = atoi(argv[1]);
9493
}
9594

0 commit comments

Comments
 (0)