|
Boost : |
From: Peter Dimov (pdimov_at_[hidden])
Date: 2001-08-24 08:14:03
From: <williamkempf_at_[hidden]>
> A couple of people have questioned the latest design for
> boost::thread and seem to talk about alternative designs.
"Seem to talk" ;-)
> However,
> 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.
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 is
created, and the implementation destroys the thread object at the
appropriate time (varies across designs.)
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.
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);
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.
The two main variations of the design are
[1] thread::ref is a thread &
This design is more dangerous. The underlying thread object is destroyed
[1.1] whenever a thread ends. This means that a stored reference can
suddenly become invalid.
[1.2] never, unless explicitly requested.
(I don't like either alternative.)
[2] thread::ref is either a dedicated 'smart reference' class, or
shared_ptr<thread>.
The thread object is automatically destroyed by the implementation whenever
the thread ends, and there are no outstanding references to the thread
object.
thread::ref is CopyConstructible and Assignable, allowing its use in
standard containers.
thread::ref is guaranteed to support operator==, operator!=, and operator<
(it's possible to use a thread::ref as a key in an associative container.)
Two variations of this design are whether the 'thread' class is visible to
the user or is hidden in the implementation.
> 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 thread
class' design is an overkill.
-- Peter Dimov Multi Media Ltd.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk