$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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