Boost logo

Boost :

From: vicente.botet (vicente.botet_at_[hidden])
Date: 2008-04-13 22:06:08


----- Original Message -----
From: "Braddock Gaskill" <braddock_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Monday, April 14, 2008 12:33 AM
Subject: Re: [boost] Review Request: future library (Gaskill version)

> On Thu, 10 Apr 2008 21:53:33 +0200, vicente.botet wrote:
>> How do your library positions with respect to the standard proposals?
>> N2561 Anthony Williams: An Asynchronous Future Value
>
> I've now taken a good look at the recent C++0X N2561 "An Asynchronous
> Future
> Value" proposal.
>
> Both my library and N2561 are heavily based on Peter Dimov's earlier
> API... I
> dare say a few method name changes would make N2561 a proper subset of my
> future and promise classes and future_wrapper helper.

I thought that the future and promise separation was proposed by Christopher
Kohlhoff
http://www.nabble.com/-futures--composite-or-to9069443.html#a9473680 :)
I think that you should add the reference to his post.

> I'm disregarding the future C++ move semantics, of course.
> We need a future<C++0x>::wait() for that... :)
>
> unique_future<T> is an interesting concept. Still wrapping my head around
> that.

Me too.

There is still the packaged_task class. What do you think about?

> My base classes offer two features which N2561 does not (and which I would
> really hope to see in any C++0X standard).
>
> --
> 1) First - future<T>::add_callback(f).
>
> add_callback is a hook called when the future is fulfilled. End
> users probably shouldn't have to touch it, but framework authors (who
> write schedulers, asio, co-routines, etc) will DEFINITELY need it.
>
> add_callback() enables the following:
>
> -Future Operators ((f1 && f2) || (f3 && f2) etc) - With add_callback,
> custom
> future_operators can be written by users.

>From the new documentation these operators are already provided by your
library.
I don't like too much the overloading of the && and || operators when they
don't have logical semantics, but this is only a question of style and
taste. maybe & and | are less controversal. And find very strange the
function op()

> -Guarded Schedulers (See my library doc "Future Concept Tutorial" section
> at
> http://braddock.com/~braddock/future) - Guards are a fundamental concept
> in the
> academic future languages I've studied (see some of Ian Foster's papers on
> Strand and PCN, for example). I have found you can do some amazing things
> with
> a guarded task scheduler (I've implemented one outside the future lib).

I like this usage of guards. Interesting. Could you add the reference in the
documentation?
I'll take a look.

> -Basic "future fulfillment" event notification (ie, just use add_callback
> as an
> event handler). Gives you essentially a signals/slot capability. Not a
> fan.
>
> An alternative to add_callback() would be to provide just the operators
> themselves - Guards can reasonably be derived from the combination ops.
>
> Any of these mechanisms solve the busy wait in the N2561 motivating
> example.

I have not found the use of wait in the example ...

> --
> 2) Second - Lazy Futures.
>
> This is something I picked up from the Oz language future implementation,
> and
> have found very useful.
Could you add the referece.
A Lazy Future essentially flags itself when it is
> "needed" - ie, when someone is blocked on a f.wait(), and f.get(), or has
> explicitly called "f.set_is_needed()". This allows, for example, a task
> to
> only process _IF_ the result is actually needed.
>
> Again, see my library doc Tutorial where I show how to easily create a
> "Lazy
> Job Queue". Permits nice Memoization patterns as well.
>
> Lazy Futures are also needed for "Lazy Future Streams". A Stream is the
> primary means of inter-task communication in future-related academic
> languages.
> It permits producer/consumer patterns and one-to-many channels. A Lazy
> stream
> allows the producer task to produce new items only as fast as his fastest
> consumer needs them (See Ian T. Foster's work again - or my
> test_future.hpp unit test code).
>
> Note I provide an easy-to-use future stream library with std iterator
> interface.
>
> I also provide a future::cancel(), which has been discussed in the other
> posts and which I'm not terribly attached to.

IMO, the fact cancel can not really ensure the function is stopped makes
this operation not very safe. But maybe useful in some cases ...

> I really like seeing the N2561 C++ proposal uses a split
> future/promise. Broken_promise exceptions have saved me many times in
> real-world applications. And I like that you aren't using the implicit
> type conversion (which has bitten me many times in real-world
> applications! I only use my future::get() method now).
>
> (I still provide implicit conversion, but would take it out very fast if
> others
> are no longer attached to it).

I have just a question why there are three ways to get the value from a
future.
f, f() and f.get()?

I don't like too much the implicit conversion. N2561 has removed the
implicit conversion only from the unique_future but preserved it for
shared_future. Can some one explain why?

template <>
class unique_future<void>
{
public:
    // ...
    void move(); // <<<<<<<<<
    // ...
};
template <typename R>
class shared_future
{
public:
    // ...
    // retrieving the value
    operator R const & () const; // <<<<<<<<<
    R const & get() const;
    // ...
};

If this implicit conversion is definitively removed, the operators || and &&
will not need any more the op function wich is quite odd.

Best
_____________________
Vicente Juan Botet Escriba


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