From: Alexander Terekhov (terekhov_at_[hidden])
Date: 2001-08-16 08:33:16
> > > I note the clever semantics: this call would have to
> > > throw an exception if the thread had been detached.
> > > But there's no call to detach a thread, so it cannot happen:
> > > threads are detached simply by not calling join.
> > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > really? without ref.counting? i do not understand this.
> > can you explain this?
> Unfortunately, to implement this correctly on top of pthreads I think
> we're going to have to ref-count. Not in the same manner as you do
> with a thread_ref concept, but it's still going to need to be done.
> The biggest problem I see to getting this right is in not knowing
> precisely what POSIX defines as the result of calling join() on a
> thread that's already been joined or detached. If it's undefined
> behavior then I'm going to have problems with "adopted" threads.
> We'll have to discuss what the appropriate design/implementation will
> be in that case. Can you enlighten me on this issue?
i do not think that "adopted" threads (main/initial thread
thread aside) would create a real problem.. (pthreads-win32
solves it via some _np functions, which should never been
used in portable programs anyway..)
>If it's undefined behavior then...
yes, behavior is undefined (use of not detached/joinable
thread (id) by _detach/_join more than once is an error;
with an exception of _join been cancelled):
"A conforming implementation is free to reuse a thread
ID after the thread terminates if it was created with
the detachstate attribute set to PTHREAD_CREATE_DETACHED
or if pthread_detach() or pthread_join() has been called
for that thread. If a thread is detached, its thread ID
is invalid for use as an argument in a call to
pthread_detach() or pthread_join()."
"The detachstate attribute controls whether the thread is
created in a detached state. If the thread is created
detached, then use of the ID of the newly created thread
by the pthread_detach() or pthread_join() function is an
"It has been suggested that a ''detach'' function is not
necessary; the detachstate thread creation attribute is
sufficient, since a thread need never be dynamically
detached. However, need arises in at least two cases:
1. In a cancelation handler for a pthread_join () it is
nearly essential to have a pthread_detach() function
in order to detach the thread on which pthread_join() was
waiting. Without it, it would be necessary to have
the handler do another pthread_join () to attempt to
detach the thread, which would both delay the cancelation
processing for an unbounded period and introduce a
new call to pthread_join ( ), which might itself need
a cancelation handler. A dynamic detach is nearly
essential in this case.
2. In order to detach the ''initial thread'' (as may be
desirable in processes that set up server threads)."
"The pthread_join() function shall suspend execution of
the calling thread until the target thread terminates,
unless the target thread has already terminated. On
return from a successful pthread_join() call with a
non-NULL value_ptr argument, the value passed to
pthread_exit() by the terminating thread shall be made
available in the location referenced by value_ptr.
When a pthread_join() returns successfully, the target
thread has been terminated. The results of multiple
simultaneous calls to pthread_join() specifying
the same target thread are undefined. If the thread
calling pthread_join() is canceled, then the target
thread shall not be detached."
"It is unspecified whether a thread that has exited
but remains unjoined counts against _PTHREAD_THREADS_MAX."
"The pthread_join() function provides a simple mechanism
allowing an application to wait for a thread to terminate.
After the thread terminates, the application may then choose
to clean up resources that were used by the thread. For
instance, after pthread_join() returns, any application-
provided stack storage could be reclaimed. The pthread_join()
or pthread_detach() function should eventually be called for
every thread that is created with the detachstate attribute
set to PTHREAD_CREATE_JOINABLE so that storage associated with
the thread may be reclaimed."
"The interaction between pthread_join() and cancelation is
well-defined for the following reasons:
- The pthread_join() function, like all other
non-async-cancel-safe functions, can only be called with
deferred cancelability type.
- Cancelation cannot occur in the disabled cancelability
state. Thus, only the default cancelability state need be
considered. As specified, either the pthread_join() call is
canceled, or it succeeds, but not both. The difference is
obvious to the application, since either a cancelation
handler is run or pthread_join() returns. There are no race
conditions since pthread_join() was called in the deferred
"The pthread_detach() function shall indicate to the
implementation that storage for the thread thread can be
reclaimed when that thread terminates. If thread has not
terminated, pthread_detach( ) shall not cause it to terminate.
The effect of multiple pthread_detach() calls on
the same target thread is unspecified."
as for "await_completion" or similar names..
thread termination process begins when
a) thread start routine returns;
b) thread start routine gets interrupted
with either thread::exit(...) or thread
cancellation (at some cancellation
point or inside some async.cancellable
thread termination process:
1. "stack unwinding"; calling cancellation
cleanup handlers/C++ destructors;
2. destruction of thread specific data
(iterative process of calling tsd
3. (if detached) auto-destruction of
"native" thread object.
Q) what do you really want to wait for
(with respect to not detached/"joinable"
I. finish/end of execution with respect
to thread start routine "normal" flow
only: **begin of thread termination**;
II. finish/end of execution with respect
to thread start routine "normal" flow
*and* subsequent thread termination
process: **end of thread termination**;
III. ultimate end/everything above plus
destruction of "native" thread
object (**pthread_join returns**
and it is safe now to e.g. reclaim
application provided stack);
i have suggested to provide an
option/functions which would allow to
wait for both: [I-above] - less than
posix "join" and [III-above] - equal
to posix "join" (default), separately..
i have also suggested that on destruction
of not detached/"joinable" C++ thread
(object), [III-above] should be done
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk