|
Boost : |
From: Braddock Gaskill (braddock_at_[hidden])
Date: 2008-04-13 18:33:09
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'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.
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. -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). -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. -- 2) Second - Lazy Futures. This is something I picked up from the Oz language future implementation, and have found very useful. 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. 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). Braddock Gaskill
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk