Boost logo

Boost :

From: William Kempf (williamkempf_at_[hidden])
Date: 2001-08-24 13:05:24

From: <williamkempf_at_[hidden]>
>>I'm not 100% sure I fully understand their alternatives.
>I have tried to outline the major difference between the current design and
>the alternatives. The current design gives the user explicit control over a
>thread object's lifetime; in particular, it allows the user to destroy a
>thread object before the corresponding thread has finished.

As they can with the thread_ref design as well. In this regard they are
identical. The actual differences lie in the semantics for copying and

>An alternative design places on the implementation the responsibility (and
>the right) to manage the thread objects' lifetimes. This means that the
>implementation, not the user, creates the thread object whenever a thread
>created, and the implementation destroys the thread object at the
>appropriate time (varies across designs.)

There is no "thread object", at least none that are exposed. There's only
"thread state" that's shared. Even with the proposed non-copyable interface
there is still "shared thread state", and it's still the library's
responsibility to create and destroy this state data.

>A possible reason to prefer such a design is that it's likely that the
>implementation would need (in the future, when the functionality is
>expanded) to manage thread-specific state that must be valid for the
>lifetime of the thread. The logical place to put such state is in the
> >thread
>object, but this is not an option with the current design.

This is what TLS is for, and how it's accomplished is an implementation
detail that doesn't effect the interface.

>Here's how a typical alternative design looks like:
>template<class F> thread::ref create(F f);
>thread::ref current();
>void join(thread::ref t);

This was the original interface I proposed. There are serious issues with
the design that have been pointed out. I was hoping you'd fleshed out
solutions to the problems.

>where thread::ref is a (smart) reference to a thread object. It is
>guaranteed by the implementation that current(), when invoked from the same
>thread, will always return a reference to the thread object that has been
>returned from create() when the thread was first started; or, if the thread
>is the main thread, current() will always return a reference to the 'main'
>thread object.

This ignores other threads created outside of the library. To me this is a
serious QoL issue. Addressing the "main" thread and ignoring other threads
seems to be a bigger mistake than simply not adopting any threads. Thread
adoption is one of the biggest problems with implementing this sort of
design. Since it's basically the design used by Win32 there's not much
issue there, but with POSIX there are all sorts of problems.

The biggest issue (which lead to the latest changes to the non-copyable
thread design) is with "join" semantics. I can't see any way to do this
with a thread_ref design. The best we can gaurantee are "wait" semantics,
and on POSIX such semantics may not be enough.

>>In the end I may not choose any of the alternative designs, or even
>>make changes to the current proposal, but at least I can make an
>>informed choice. During submission, if you feel strongly against the
>>design I choose you can elect to vote for not accepting the library.
>Not an option, I'm afraid. Rejecting the whole library because of the
>class' design is an overkill.

If you feel the design is not correct I'd hope you'd reject the library and
hardly see it as overkill. Nothing prevents us from fixing the things that
caused the library to be rejected and re-submitting. This is definately
better than accepting a library you consider to be "broken" (for lack of a
better term).

One thing you didn't respond to here was a request for pointing out areas in
which the proposed design make it difficult/impossible to implement the
thread_ref design. I see several areas that are problematic... but those
same areas already exist when trying to implement thread_ref on top of
POSIX. The only real difference between my proposal and POSIX is the
restriction that only the thread object used to start the thread can be used
to "join" the thread. This restriction helps to insure that multiple calls
to "join" are not made, which is an error. I can relax this restriction
allowing "join" to be called on any thread object, but calling "join" more
than once (on any thread object for any given thread of execution) would
result in undefined behavior. Another problem with this design is that
"detach" would have to become an exposed call instead of being done
automatically if you didn't join. It would then be an error to not call
either "join" or "detach" exactly once for any given thread. All of this
would give more flexibility (and probably make the thread_ref a little
easier to implement) but would make things much more error prone.

Bill Kempf

Get your FREE download of MSN Explorer at

Boost list run by bdawes at, gregod at, cpdaniel at, john at