Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2001-08-24 14:37:48


From: "William Kempf" <williamkempf_at_[hidden]>
> >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.

No, the user can't destroy the thread object via a thread_ref. Only the
thread_ref is destroyed. I've outlined the thread object lifetime in the
previous post.

> The actual differences lie in the semantics for copying and
> "join"/"wait".

Not really. Both designs have a noncopyable thread object. In the
thread_ref-based design the user is given a (smart) reference to it - think
of it as a shared_ptr<thread>.

Join has the same semantics. In a shared_ptr-based design the semantics of
join are as if

void join(shared_ptr<thread> ref)
{
    ref->join();
}

> There is no "thread object", at least none that are exposed.

There is a thread object in your original design - an instance of class
'boost::thread.' This is what I mean by a "thread object."

> >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.

And these serious issues are?

> >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.

Thread adoption is a QoI issue. It is not stated in the interface that
thread::current() does not work for threads created outside the library.

The rules I outlined above explain the semantics of current() and create().

When the implementation does support thread adoption, the semantics of
current() in a thread created outside the library are as described for the
'main' thread; that is, all calls to current() made from that thread will
return a reference to the same unique thread object.

> 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.

I suspect that there's something that I'm missing, because I don't see a
problem with 'join.' Could you elaborate?

> 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 know. I don't have enough information yet. The only outstanding issue
right now is "how do I create a joinable thread object for the main thread"
or if you prefer, "how do I create a joinable thread object for a thread
that hasn't been created by the library."

--
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