|
Boost : |
From: Alexander Terekhov (terekhov_at_[hidden])
Date: 2001-06-29 09:58:20
> The difference is that a detached thread does not
> need to run to completion (in fact they are
> usually coded with infinite loops) while a joined
> thread does.
Bill, for never ending thread it is absolutely
irrelevant whether a thread was detached or not!
The difference is that a detached thread does
not need to be _joined_ in order to reclaim
resources (e.g. thread id) -- it will be done
automatically upon thread termination. In other
words for not detached threads thread ids stays
valid until join() is called -- even if a thread
had already terminated (thread function ended
via return or pthread_exit) its id/thread
function return value/etc.. will be preserved
and will stay preserved until join(). For never
ending threads reclamation of resources never
occurs hence there is no difference at all with
respect to detached status.
> (BTW, the pthreads standard correctly points out that join() is a
> convenience... detached threads can be "waited on" through a
> condition variable.
the new standard appears to strengthen the termination
guaranties with respect to join. the new version says:
33690 ... For instance, after pthread_join ( ) returns, any
33691 application-provided stack storage could be reclaimed.
CV solution does not allow that!!
as for thread object design questions and join/detach please
consider the following POSIX example attached below -- it
creates a new thread type (with a capability for timed join).
Hopefully it will help to clarify matters.
regards,
alexander.
---- 6086 /* 6087 * Construct a thread variety entirely from existing functions 6088 * with which a join can be done, allowing the join to time out. 6089 */ 6090 #include <pthread.h> 6091 #include <time.h> 6092 struct timed_thread { 6093 pthread_t t; 6094 pthread_mutex_t m; 6095 int exiting; 6096 pthread_cond_t exit_c; 6097 void *(*start_routine)(void *arg); 6098 void *arg; 6099 void *status; 6100 }; 6101 typedef struct timed_thread *timed_thread_t; 6102 static pthread_key_t timed_thread_key; 6103 static pthread_once_t timed_thread_once = PTHREAD_ONCE_INIT; 6104 static void timed_thread_init() 6105 { 6106 pthread_key_create(&timed_thread_key, NULL); 6107 } 6108 static void *timed_thread_start_routine(void *args) 6109 /* 6110 * Routine to establish thread-specific data value and run the actual 6111 * thread start routine which was supplied to timed_thread_create(). 6112 */ 6113 { 6114 timed_thread_t tt = (timed_thread_t) args; 6115 pthread_once(&timed_thread_once, timed_thread_init); 6116 pthread_setspecific(timed_thread_key, (void *)tt); 6117 timed_thread_exit((tt->start_routine)(tt->arg)); 6118 } 6119 int timed_thread_create(timed_thread_t ttp, const pthread_attr_t *attr, 6120 void *(*start_routine)(void *), void *arg) 6121 /* 6122 * Allocate a thread which can be used with timed_thread_join(). 6123 */ 6124 { 6125 timed_thread_t tt; 6126 int result; 6127 tt = (timed_thread_t) malloc(sizeof(struct timed_thread)); 6128 pthread_mutex_init(&tt->m,NULL); 6129 tt->exiting = FALSE; 6130 pthread_cond_init(&tt->exit_c,NULL); 6131 tt->start_routine = start_routine; 6132 tt->arg = arg; 6133 tt->status = NULL; 6134 if ((result = pthread_create(&tt->t, attr, 6135 timed_thread_start_routine, (void *)tt)) != 0) { 6136 free(tt); 6137 return result; 6138 } 6139 pthread_detach(tt->t); 6140 ttp = tt; 6141 return 0; 6142 } 6143 int timed_thread_join(timed_thread_t tt, 6144 struct timespec *timeout, 6145 void **status) 6146 { 6147 int result; 6148 pthread_mutex_lock(&tt->m); 6149 result = 0; 6150 /* 6151 * Wait until the thread announces that it is exiting, 6152 * or until timeout. 6153 */ 6154 while (result == 0 && ! tt->exiting) { 6155 result = pthread_cond_timedwait(&tt->exit_c, &tt->m, timeout); 6156 } 6157 pthread_mutex_unlock(&tt->m); 6158 if (result == 0 && tt->exiting) { 6159 *status = tt->status; 6160 free((void *)tt); 6161 return result; 6162 } 6163 return result; 6164 } 6165 void timed_thread_exit(void *status) 6166 { 6167 timed_thread_t tt; 6168 void *specific; 6169 if ((specific=pthread_getspecific(timed_thread_key)) == NULL){ 6170 /* 6171 * Handle cases which won't happen with correct usage. 6172 */ 6173 pthread_exit( NULL); 6174 } 6175 tt = (timed_thread_t) specific; 6176 pthread_mutex_lock(&tt->m); 6177 /* 6178 * Tell a joiner that we're exiting. 6179 */ 6180 tt->status = status; 6181 tt->exiting = TRUE; 6182 pthread_cond_signal(&tt->exit_c); 6183 pthread_mutex_unlock(&tt->m); 6184 /* 6185 * Call pthread exit() to call destructors and really 6186 * exit the thread. 6187 */ 6188 pthread_exit(NULL); 6189 }
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk