Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2002-08-06 10:32:40


From: "William E. Kempf" <williamkempf_at_[hidden]>
> From: "Peter Dimov" <pdimov_at_[hidden]>
> >
> > Roll-your-own thread<R> is possible, but I definitely don't agree with
its
> > "triviality",
>
> void foo(int& res)
> {
> res = 10;
> }
>
> int result;
>
> boost::thread thread(boost::bind(&foo, boost::ref(result))); // warning,
> done from memory and likely wrong
> thread.join();
> std::cout << result << std::endl;
>
> I'd call this trivial.

The fact that you can create undefined behavior by accessing "result" aside,
this is a toy example. As I said, when you deal with more than one thread,
things aren't that simple, although you could still maintain that they are
trivial.

std::vector<int> results;
std::vector< shared_ptr<thread> > threads;

for(int i = 0; i < N; ++i)
{
    results.push_back(0);
    threads.push_back(shared_ptr<thread>(new thread(bind(foo,
ref(results.back())))));
}

std::for_each(threads.begin(), threads.end(), mem_fn(&thread::join));

std::cout << std::accumulate(results.begin(), results.end(), 0) <<
std::endl;

> Adding a value return to boost::function would only
> allow illimination of two lines above (the declaration of "result" and a
> merging of the join() call and the cout line), neither of which add
anything
> to the clarity of the code, and in fact would make the code less readable,
> IMHO.

To put things in perspective:

int foo()
{
    return 10;
}

std::cout << boost::thread(foo).join() << std::endl;

Less readable? OK, let's attribute this to taste.

> > especially when a thread group (performing a computation in
> > parallel) needs to be joined and the results combined.
>
> I don't see how the above implementation is any less trivial even in this
> case.

I'm not going to debate the precise meaning of "trivial" in this context,
but you could equally well argue that non-void returns are an unnecessary
language feature, since you can trivially emulate them with out arguments.

> > The enumerated exception list is questionable, though. I'd specify
join()
> to
> > throw an implementation-defined exception when f() throws. With compiler
> > magic, it can even be a copy of the real thing. Without, well, it can at
> > least preserve std::exception::what().
>
> Another issue here is, again, how this ties in with current exception
> semantics. Though not necessarily a good application design, current
> threading libraries allow you to join the "main" thread (and the best we
> could do is prohibit this in documentation). As long as you can join the
> main thread we'll have to change the standards required behavior of
> propogating an exception out of main(), and that would be something tricky
> to implement and obviously all implementations would be non-portable.

Yes, a valid concern. This is perhaps the biggest problem with this
proposal, what happens with the exception - if there is one - when join() is
never called.


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