Boost logo

Boost :

From: Braddock Gaskill (braddock_at_[hidden])
Date: 2007-03-10 07:27:53

On Sat, 10 Mar 2007 01:54:57 +0200, Peter Dimov wrote:

> Braddock Gaskill wrote:
> My current proposal for std::future<R> is available at
> and will be part of the pre-meeting mailing. We'll see how it fares.

Thanks Peter,

I coded up a quick straight-forward implementation of your proposal. I'll make
it available as soon as I test it a little. Maybe it can be grafted into the
vault implementation to provide composites, etc.

I have a few questions/comments:

1) void set_exception( exception_ptr p);

This is tricky. I don't really want to pass and throw to the caller an
exception pointer because responsibility for deleting the exception pointer
will be very difficult to get right. Imagine the case where two objects each
hold references to the same future, and so the exception gets re-thrown twice
as they both try to access the value. Which one delete's the exception

Should the future handle deletion responsibilty when the last future<>
reference is gone?

What type should the pointer be? We can't assume that all exceptions are even
derived from std::exception.

Passing by value is a no-go because of slicing issues due to the unknown exact
type of the exception (even the calling code probably won't know).

2) Are multiple calls to set_value() permitted for a single future object?

Your prior proposal (N2096) returned the value by reference, implying that
multiple set_value() calls could not be allowed. This proposal returns by
value, so multiple calls are at least possible.

IMHO, it should not be allowed. The future object does not have any way to
ensure that the "consumer" gets every successive value the "producer" might
set. Too confusing.

3) What should 'timespec' be? I'm using boost::threads::xtime

4) set_cancel_handle(thread::handle )

This thread handle seems to assume that future<> is being used with a
thread-per-invocation, and does not appear to provide a mechanism for canceling
a queued invocaction, which is necessary for at least my application. I'd need
a generic "callback-on-cancel()".

5) join()/try_join() vs wait()/ready()

As far as I can tell, you renamed the wait() and ready() to join() and
try_join(). In my opinion, these names are far less clear, and again my
anti-thread-per-invocation bias doesn't like the implied thread semantics.

In particular, try_join() makes little sense in a polling context. A naive
programmer would be more likely to want to use has_value() instead, which would
be WRONG if the method throws.

while (!has_value()) //infinite loop if has_exception
  do something;

6) operator R() const;

My opinion here, but if I understand this then the semantics of this are far
too subtle.

future<int> x = std::fork(myfunc);
//200 lines later
z = x + y; // this blocks or throws, mystifying young programmers everywhere

I liked your prior proposal N2096 which would have:
z = x() + y; // x is not your grandfather's variable

Also, what is the meaning of:
mysubroutine(x) // Does this block or throw, or just use a future argument?

What is the meaning if mysubroutine is declared:
template<T> mysubroutine(T a);

Braddock Gaskill
Dockside Vision Inc

Boost list run by bdawes at, gregod at, cpdaniel at, john at