Boost logo

Boost :

From: braddock (braddock_at_[hidden])
Date: 2007-03-13 23:55:01


I've made a futures implementation in the hopes of combining the best features
from all the proposals and various implementations currently floating
around. It is still rough around the edges, but is mostly covered by
unit tests.

http://braddock.com/~braddock/future/

I'm looking for input. I'd be willing to add additional functionality
needed and progress it to the point where it could be formally submitted into
boost if there is interest. It could perhaps be merged into the existing
futures implementation in the vault to add combined groups, etc.

I used Peter's exception_ptr code, which he said he would post under a boost license.

  -Braddock Gaskill

Below are the README comments:

GOAL:

Provide a definitive future implementation with the best features of the
numerous implementations and proposals floating around, in the hopes to avoid
multiple incompatible future implementations (coroutines, active objects, asio,
etc). Also, to explore the combined implementation of the best future
concepts.

FEATURES:

-split promise<T>/future<T> concept.

-Agnostic to scheduling, any active object implementation, thread model, etc
etc. Basic future which can be used in many contexts.

-promise<T> is reference counted - if the last promise<T> goes out of scope
before the future is set, the future is automatically failed with a
broken_promise exception.

-add_callback() permits arbitrary functions to be called when the future is
set. This is needed to build non-intrusive compound waiting structures, like
future_groups, or to better support continuation scheduling concepts, as in
coroutines.

-Value type does not require a default constructor, and no wasteful excess
default construction is performed. Value type only needs to be copy
constructable.

-set_cancel_handler() permits an arbitrary function to be called to cancel the
future, if possible.

-atomic set_or_throw() permits the caller to detect if a set was successful
(ie, if the caller was the first to transition the future to ready). This
enables promise/future to be used to as a type of atomic semaphore.

-future<void> and promise<void> specializations, as per Dimov proposal

-Pass-by-reference specializations, such as future<int&>, permit return by reference, as per Dimov proposal.

-Uses Peter Dimov's exception_ptr implementation to make a best-effort to pass
exception types between threads.

-implementation of all three of f, f(), an f.get() blocking accessor syntaxes,
for better or for worse.

TODO:

The following class of sub-type assignments should be made possible, as
discussed by Frank Hess and Peter Dimov on the list.

class A {};
class B : public A {};
promise<shared_ptr<B> > p;
future<shared_ptr<A> > f(p);

future_group classes and simple function wrappers should be provided, although
kept seperate from the main future<T> implementation.

RATIONALE:

Some method names were reverted to Peter Dimov's earlier N2096 proposal
because of better semantics, in the author's opinion.

set_value() -> set() - primary use of future
join() -> wait() - more descriptive, less thread-centric
timed_join() -> timed_wait()
try_join() -> ready() - join implies blocking, but this returns state

The user-supplied cancel_handler is called after the future/promise
is unlocked. Otherwise, the cancel_handler could cause a deadlock if
it invokes any methods upon the promise/future. This means that
worker threads COULD call set() upon a canceled future, but these
calls would be ignored.

This is (IMHO) correct behavior. A cancel() invocation sets the
future's state with a future_cancel exception - it does not guarantee
that the work is actually canceled, because in many cases it cannot
be stopped.

-Should set() silently ignore calls on an already set promise, or
should it throw?

Peter Dimov's proposal says ignore, and I'm inclined to agree because
if a user sets up a scenario where a promise is shared between
multiple functions, or where a future is canceled, it is impossible
for the author of the individual function to foresee the exceptional
situation. I offer set_or_throw() to still allow use of future for
atomic signaling.

REFERENCES:

Transporting Values and Exceptions between Threads N2096, Peter Dimov
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2096.html

Proposed Text for Parallel Task Execution, Peter Dimov (DRAFT)
http://www.pdimov.com/cpp/N2185.html

Multithreading API for C++0X - A Layered Approach, Howard Hinnant
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html

Concur and C++ Futures, Herb Sutter, presentation video & slides
http://video.google.com/videoplay?docid=7625918717318948700
http://www.nwcpp.org/Downloads/2006/The_Concur_Project_-_NWCPP.pdf

Language Support for Transporting Exceptions Between Threads N2179, Peter Dimov
http://www.pdimov.com/cpp/N2179.html

Active Object libpoet framework by Frank Mori Hess
http://source.emptycrate.com/projects/activeobjects/
http://www.comedi.org/projects/libpoet/index.html

Boost Coroutine library

Boost Vault future library

Chris Kohlhoff's future implementation, posted to boost-devel list

Enjoy,
Braddock Gaskill
Dockside Vision inc


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