Boost logo

Boost :

From: williamkempf_at_[hidden]
Date: 2001-06-26 17:10:36


--- In boost_at_y..., Beman Dawes <bdawes_at_a...> wrote:
> At 04:14 PM 6/26/2001, williamkempf_at_h... wrote:
>
> >Yet another alternative would be to do away with the thread_desc
idea
> >all together. In that case the constructor for thread would be
the
> >creation routine and the destructor must either "join" the thread
> >or "detach" it (using pthread terminology instead of current
> >Boost.Threads terminology), and there will be little use for self
()
> >and it's implementation would be problematic enough to warrant
> >removal. This design would still allow developers to manage
threads
> >by creating them on the heap and storing them in what ever smart
> >pointers they wish to. This would be a well designed C++
solution,
> >but it differs enough from what programmers have grown to expect
with
> >other APIs that it may not be a well liked solution.
>
> This is the design I've been hoping you would propose, because it
seems so
> much more "in the spirit of C++".

I have mentioned this design before, including the problems that I
saw with this approach.

> It may take a bit of getting used to by traditional threads
programmers,
> but it will be more familiar to most programmers, much easier to
teach, and
> it wouldn't surprise me if because of those factors it turns out to
be less
> error prone.
>
> I'd like to encourage you to flesh out the interface. My guess is
it is
> really simple.

It would simply be this:

    class thread : boost::noncopyable
    {
    public:
        thread(const detail::threadfunc& func);
        ~thread();

        bool is_alive() const;
        bool join();
        bool detach();

        static void join_all(); // This may be pointless!?
        static void sleep(const xtime& xt);
        static void yield();
    };

The destructor will call join() unless a call to detach() had been
previously made.

> Also see if you can think of serious impediments to
> implementation.

The first impediment is that it's a very common practice to copy
the "thread" (actually the descriptor, as you pointed out) in order
to allow some other piece of the program manage the thread. For
instance, a thread pool is going to have to store the threads in some
sort of data structure. This design requires all such uses to be
dynamically allocated via new, which complicates the management
though it can be lessened by immediately placing them in a smart
pointer.

The second impediment is that constructing threads in a loop becomes
much more complicated. You either have to (again) create the threads
dynamically via new and manage the lifetime (probably with a smart
pointer), or call detach() on all of them. The detach() approach
will either require you to not care when the threads end (in fact,
they will be unceremoniously terminated when the main thread exits),
or to have join_all() join even detached threads (the latter means
that you can only use the detach() method if you know what threads
may be running and want to wait on all of them).

With smart pointers you get the same result here as you do with the
thread_desc concept, but the syntax becomes more complicated, which
is going to be a hard sell for some developers.

I'm not against this design, I just think that others might be for
the reasons above. I don't want people shying away from
Boost.Threads because they perceive it to be more complicated to use
than they'd like, even if the usage is a more proper C++ design.

Bill Kempf


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk