Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2007-03-10 08:17:17

Braddock Gaskill wrote:
> 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 one, too; look at the 'Implementability' section for the links.

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

exception_ptr is described in

and is typically a reference-counted smart pointer. If the proposal for
language support doesn't pass, we'll have to live with something along the
lines of

as linked from N2185.

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

Allowed, with the second and subsequent calls ignored.

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

'struct timespec' as described in POSIX <time.h>, basically

struct timespec
    time_t tv_sec;
    long tv_nsec;

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

Yes, you are right that set_cancel_handle is limited to canceling threads. I
was short on time since the pre-mailing deadline was yesterday so I went
with what I already had implemented. set_cancel_callback would've been more
general, but could open the door to deadlocks. I'll probably revise the
paper for the meeting to generalize the cancel support to accept an
arbitrary callback if I'm satisfied with the semantics of such a design.

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

Yes, I could go either way on that one. I opted for consistency with the
join/try_join/timed_join family of thread functions.

> 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

Another tradeoff. I think that the implicit conversion here is worth keeping
because the parallelized syntax is closer to the traditional sequential one.
It's a matter of taste.

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

Whether this is a bug or a feature is also a matter of taste. The conversion
allows some mysubroutines to work on a future<X> as if it were an X, doing
the 'obvious' thing.

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