$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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 }