Boost logo

Boost :

From: Beman Dawes (bdawes_at_[hidden])
Date: 2001-06-26 18:46:03


At 06:10 PM 6/26/2001, williamkempf_at_[hidden] wrote:

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

This just seems like the usual thing you do in C++; that's what smart
pointers are for.

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

Wouldn't shared_ptr<> work just fine? Am I missing something?

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

All that seems appropriate for some applications? Again I'm missing why
this is a problem.

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

But you only use a smart pointer when you need more than function scope
management, or maybe a variable number. If you had an app that just used
two threads, wouldn't you would just instantiate the two threads, like any
other object? I think of it like files; if you know you need an input file
and an output file you just code something like:

    ifstream input("foo.in");
    ofstream output("foo.out");

However, if their lifetime should be different than function scope, or you
need a variable number of files, then you use a smart point. But only
then.

Is there something different about threads?

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

Well, you could also make the low level handle based interface public
instead of just being an implementation detail. Then people can fool with
handles if they want to. Think of FILE; C++ still has <cstdio> even though
a lot of people prefer to use <iostream>.

--Beman


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