Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r56770 - sandbox/async/boost/futures
From: vicente.botet_at_[hidden]
Date: 2009-10-13 03:02:11


Author: viboes
Date: 2009-10-13 03:02:10 EDT (Tue, 13 Oct 2009)
New Revision: 56770
URL: http://svn.boost.org/trac/boost/changeset/56770

Log:
TBoost.Async:
* Added futures library

Added:
   sandbox/async/boost/futures/
   sandbox/async/boost/futures/boostbook.css (contents, props changed)
   sandbox/async/boost/futures/future.hpp (contents, props changed)
   sandbox/async/boost/futures/index.html (contents, props changed)
   sandbox/async/boost/futures/test_futures.cpp (contents, props changed)

Added: sandbox/async/boost/futures/boostbook.css
==============================================================================
--- (empty file)
+++ sandbox/async/boost/futures/boostbook.css 2009-10-13 03:02:10 EDT (Tue, 13 Oct 2009)
@@ -0,0 +1,588 @@
+/*=============================================================================
+ Copyright (c) 2004 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Distributed under the Boost Software License, Version 1.0. (See accompany-
+ ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+/*=============================================================================
+ Body defaults
+=============================================================================*/
+
+ body
+ {
+ margin: 1em;
+ font-family: sans-serif;
+ }
+
+/*=============================================================================
+ Paragraphs
+=============================================================================*/
+
+ p
+ {
+ text-align: left;
+ font-size: 10pt;
+ line-height: 1.15;
+ }
+
+/*=============================================================================
+ Program listings
+=============================================================================*/
+
+ /* Code on paragraphs */
+ p tt.computeroutput
+ {
+ font-size: 9pt;
+ }
+
+ pre.synopsis
+ {
+ font-size: 90%;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+ .programlisting,
+ .screen
+ {
+ font-size: 9pt;
+ display: block;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+ /* Program listings in tables don't get borders */
+ td .programlisting,
+ td .screen
+ {
+ margin: 0pc 0pc 0pc 0pc;
+ padding: 0pc 0pc 0pc 0pc;
+ }
+
+/*=============================================================================
+ Headings
+=============================================================================*/
+
+ h1, h2, h3, h4, h5, h6
+ {
+ text-align: left;
+ margin: 1em 0em 0.5em 0em;
+ font-weight: bold;
+ }
+
+ h1 { font: 140% }
+ h2 { font: bold 140% }
+ h3 { font: bold 130% }
+ h4 { font: bold 120% }
+ h5 { font: italic 110% }
+ h6 { font: italic 100% }
+
+ /* Top page titles */
+ title,
+ h1.title,
+ h2.title
+ h3.title,
+ h4.title,
+ h5.title,
+ h6.title,
+ .refentrytitle
+ {
+ font-weight: bold;
+ margin-bottom: 1pc;
+ }
+
+ h1.title { font-size: 140% }
+ h2.title { font-size: 140% }
+ h3.title { font-size: 130% }
+ h4.title { font-size: 120% }
+ h5.title { font-size: 110% }
+ h6.title { font-size: 100% }
+
+ .section h1
+ {
+ margin: 0em 0em 0.5em 0em;
+ font-size: 140%;
+ }
+
+ .section h2 { font-size: 140% }
+ .section h3 { font-size: 130% }
+ .section h4 { font-size: 120% }
+ .section h5 { font-size: 110% }
+ .section h6 { font-size: 100% }
+
+ /* Code on titles */
+ h1 tt.computeroutput { font-size: 140% }
+ h2 tt.computeroutput { font-size: 140% }
+ h3 tt.computeroutput { font-size: 130% }
+ h4 tt.computeroutput { font-size: 120% }
+ h5 tt.computeroutput { font-size: 110% }
+ h6 tt.computeroutput { font-size: 100% }
+
+/*=============================================================================
+ Author
+=============================================================================*/
+
+ h3.author
+ {
+ font-size: 100%
+ }
+
+/*=============================================================================
+ Lists
+=============================================================================*/
+
+ li
+ {
+ font-size: 10pt;
+ line-height: 1.3;
+ }
+
+ /* Unordered lists */
+ ul
+ {
+ text-align: left;
+ }
+
+ /* Ordered lists */
+ ol
+ {
+ text-align: left;
+ }
+
+/*=============================================================================
+ Links
+=============================================================================*/
+
+ a
+ {
+ text-decoration: none; /* no underline */
+ }
+
+ a:hover
+ {
+ text-decoration: underline;
+ }
+
+/*=============================================================================
+ Spirit style navigation
+=============================================================================*/
+
+ .spirit-nav
+ {
+ text-align: right;
+ }
+
+ .spirit-nav a
+ {
+ color: white;
+ padding-left: 0.5em;
+ }
+
+ .spirit-nav img
+ {
+ border-width: 0px;
+ }
+
+/*=============================================================================
+ Copyright footer
+=============================================================================*/
+ .copyright-footer
+ {
+ text-align: right;
+ font-size: 70%;
+ }
+
+ .copyright-footer p
+ {
+ text-align: right;
+ font-size: 80%;
+ }
+
+/*=============================================================================
+ Table of contents
+=============================================================================*/
+
+ .toc
+ {
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.1pc 1pc 0.1pc 1pc;
+ font-size: 80%;
+ line-height: 1.15;
+ }
+
+ .boost-toc
+ {
+ float: right;
+ padding: 0.5pc;
+ }
+
+/*=============================================================================
+ Tables
+=============================================================================*/
+
+ .table-title,
+ div.table p.title
+ {
+ margin-left: 4%;
+ padding-right: 0.5em;
+ padding-left: 0.5em;
+ }
+
+ .informaltable table,
+ .table table
+ {
+ width: 92%;
+ margin-left: 4%;
+ margin-right: 4%;
+ }
+
+ div.informaltable table,
+ div.table table
+ {
+ padding: 4px;
+ }
+
+ /* Table Cells */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ padding: 0.5em;
+ text-align: left;
+ font-size: 9pt;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ padding: 0.5em 0.5em 0.5em 0.5em;
+ border: 1pt solid white;
+ font-size: 80%;
+ }
+
+ table.simplelist
+ {
+ width: auto !important;
+ margin: 0em !important;
+ padding: 0em !important;
+ border: none !important;
+ }
+ table.simplelist td
+ {
+ margin: 0em !important;
+ padding: 0em !important;
+ text-align: left !important;
+ font-size: 9pt !important;
+ border: none !important;
+ }
+
+/*=============================================================================
+ Blurbs
+=============================================================================*/
+
+ div.note,
+ div.tip,
+ div.important,
+ div.caution,
+ div.warning,
+ p.blurb
+ {
+ font-size: 9pt; /* A little bit smaller than the main text */
+ line-height: 1.2;
+ display: block;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+ p.blurb img
+ {
+ padding: 1pt;
+ }
+
+/*=============================================================================
+ Variable Lists
+=============================================================================*/
+
+ /* Make the terms in definition lists bold */
+ div.variablelist dl dt,
+ span.term
+ {
+ font-weight: bold;
+ font-size: 10pt;
+ }
+
+ div.variablelist table tbody tr td
+ {
+ text-align: left;
+ vertical-align: top;
+ padding: 0em 2em 0em 0em;
+ font-size: 10pt;
+ margin: 0em 0em 0.5em 0em;
+ line-height: 1;
+ }
+
+ div.variablelist dl dt
+ {
+ margin-bottom: 0.2em;
+ }
+
+ div.variablelist dl dd
+ {
+ margin: 0em 0em 0.5em 2em;
+ font-size: 10pt;
+ }
+
+ div.variablelist table tbody tr td p,
+ div.variablelist dl dd p
+ {
+ margin: 0em 0em 0.5em 0em;
+ line-height: 1;
+ }
+
+/*=============================================================================
+ Misc
+=============================================================================*/
+
+ /* Title of books and articles in bibliographies */
+ span.title
+ {
+ font-style: italic;
+ }
+
+ span.underline
+ {
+ text-decoration: underline;
+ }
+
+ span.strikethrough
+ {
+ text-decoration: line-through;
+ }
+
+ /* Copyright, Legal Notice */
+ div div.legalnotice p
+ {
+ text-align: left
+ }
+
+/*=============================================================================
+ Colors
+=============================================================================*/
+
+ @media screen
+ {
+ body {
+ background-color: #FFFFFF;
+ }
+
+ /* Links */
+ a
+ {
+ color: #005a9c;
+ }
+
+ a:visited
+ {
+ color: #9c5a9c;
+ }
+
+ h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
+ h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
+ h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
+ {
+ text-decoration: none; /* no underline */
+ color: #000000;
+ }
+
+ /* Syntax Highlighting */
+ .keyword { color: #0000AA; }
+ .identifier { color: #000000; }
+ .special { color: #707070; }
+ .preprocessor { color: #402080; }
+ .char { color: teal; }
+ .comment { color: #800000; }
+ .string { color: teal; }
+ .number { color: teal; }
+ .white_bkd { background-color: #FFFFFF; }
+ .dk_grey_bkd { background-color: #999999; }
+
+ /* Copyright, Legal Notice */
+ .copyright
+ {
+ color: #666666;
+ font-size: small;
+ }
+
+ div div.legalnotice p
+ {
+ color: #666666;
+ }
+
+ /* Program listing */
+ pre.synopsis
+ {
+ border: 1px solid #DCDCDC;
+ }
+
+ .programlisting,
+ .screen
+ {
+ border: 1px solid #DCDCDC;
+ }
+
+ td .programlisting,
+ td .screen
+ {
+ border: 0px solid #DCDCDC;
+ }
+
+ /* Blurbs */
+ div.note,
+ div.tip,
+ div.important,
+ div.caution,
+ div.warning,
+ p.blurb
+ {
+ border: 1px solid #DCDCDC;
+ }
+
+ /* Table of contents */
+ .toc
+ {
+ border: 1px solid #DCDCDC;
+ }
+
+ /* Tables */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ border: 1px solid #DCDCDC;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ background-color: #F0F0F0;
+ border: 1px solid #DCDCDC;
+ }
+
+ .copyright-footer
+ {
+ color: #8F8F8F;
+ }
+
+ /* Misc */
+ span.highlight
+ {
+ color: #00A000;
+ }
+ }
+
+ @media print
+ {
+ /* Links */
+ a
+ {
+ color: black;
+ }
+
+ a:visited
+ {
+ color: black;
+ }
+
+ .spirit-nav
+ {
+ display: none;
+ }
+
+ /* Program listing */
+ pre.synopsis
+ {
+ border: 1px solid gray;
+ }
+
+ .programlisting,
+ .screen
+ {
+ border: 1px solid gray;
+ }
+
+ td .programlisting,
+ td .screen
+ {
+ border: 0px solid #DCDCDC;
+ }
+
+ /* Table of contents */
+ .toc
+ {
+ border: 1px solid gray;
+ }
+
+ .informaltable table,
+ .table table
+ {
+ border: 1px solid gray;
+ border-collapse: collapse;
+ }
+
+ /* Tables */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ border: 1px solid gray;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ border: 1px solid gray;
+ }
+
+ table.simplelist tr td
+ {
+ border: none !important;
+ }
+
+ /* Misc */
+ span.highlight
+ {
+ font-weight: bold;
+ }
+ }
+
+/*=============================================================================
+ Images
+=============================================================================*/
+
+ span.inlinemediaobject img
+ {
+ vertical-align: middle;
+ }
+
+/*==============================================================================
+ Super and Subscript: style so that line spacing isn't effected, see
+ http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=1&postId=5341
+==============================================================================*/
+
+sup,
+sub {
+ height: 0;
+ line-height: 1;
+ vertical-align: baseline;
+ _vertical-align: bottom;
+ position: relative;
+
+}
+
+sup {
+ bottom: 1ex;
+}
+
+sub {
+ top: .5ex;
+}
+

Added: sandbox/async/boost/futures/future.hpp
==============================================================================
--- (empty file)
+++ sandbox/async/boost/futures/future.hpp 2009-10-13 03:02:10 EDT (Tue, 13 Oct 2009)
@@ -0,0 +1,1377 @@
+// (C) Copyright 2008 Anthony Williams
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef N2561_FUTURE_HPP
+#define N2561_FUTURE_HPP
+#include <stdexcept>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/config.hpp>
+#include <algorithm>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/ref.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <list>
+#include <boost/next_prior.hpp>
+
+namespace boost
+{
+ class future_uninitialized:
+ public std::logic_error
+ {
+ public:
+ future_uninitialized():
+ std::logic_error("Future Uninitialized")
+ {}
+ };
+ class broken_promise:
+ public std::logic_error
+ {
+ public:
+ broken_promise():
+ std::logic_error("Broken promise")
+ {}
+ };
+ class future_already_retrieved:
+ public std::logic_error
+ {
+ public:
+ future_already_retrieved():
+ std::logic_error("Future already retrieved")
+ {}
+ };
+ class promise_already_satisfied:
+ public std::logic_error
+ {
+ public:
+ promise_already_satisfied():
+ std::logic_error("Promise already satisfied")
+ {}
+ };
+
+ class task_already_started:
+ public std::logic_error
+ {
+ public:
+ task_already_started():
+ std::logic_error("Task already started")
+ {}
+ };
+
+ class task_moved:
+ public std::logic_error
+ {
+ public:
+ task_moved():
+ std::logic_error("Task moved")
+ {}
+ };
+
+ namespace future_state
+ {
+ enum state { uninitialized, waiting, ready, moved };
+ }
+
+ namespace detail
+ {
+ struct future_object_base
+ {
+ boost::exception_ptr exception;
+ bool done;
+ boost::mutex mutex;
+ boost::condition_variable waiters;
+ typedef std::list<boost::condition_variable_any*> waiter_list;
+ waiter_list external_waiters;
+ boost::function<void()> callback;
+
+ future_object_base():
+ done(false)
+ {}
+ virtual ~future_object_base()
+ {}
+
+ waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv)
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ do_callback(lock);
+ return external_waiters.insert(external_waiters.end(),&cv);
+ }
+
+ void remove_external_waiter(waiter_list::iterator it)
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ external_waiters.erase(it);
+ }
+
+ void mark_finished_internal()
+ {
+ done=true;
+ waiters.notify_all();
+ for(waiter_list::const_iterator it=external_waiters.begin(),
+ end=external_waiters.end();it!=end;++it)
+ {
+ (*it)->notify_all();
+ }
+ }
+
+ struct relocker
+ {
+ boost::unique_lock<boost::mutex>& lock;
+
+ relocker(boost::unique_lock<boost::mutex>& lock_):
+ lock(lock_)
+ {
+ lock.unlock();
+ }
+ ~relocker()
+ {
+ lock.lock();
+ }
+ };
+
+ void do_callback(boost::unique_lock<boost::mutex>& lock)
+ {
+ if(callback && !done)
+ {
+ boost::function<void()> local_callback=callback;
+ relocker relock(lock);
+ local_callback();
+ }
+ }
+
+
+ void wait(bool rethrow=true)
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ do_callback(lock);
+ while(!done)
+ {
+ waiters.wait(lock);
+ }
+ if(rethrow && exception)
+ {
+ boost::rethrow_exception(exception);
+ }
+ }
+
+ bool timed_wait_until(boost::system_time const& target_time)
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ do_callback(lock);
+ while(!done)
+ {
+ bool const success=waiters.timed_wait(lock,target_time);
+ if(!success && !done)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void mark_exceptional_finish_internal(boost::exception_ptr const& e)
+ {
+ exception=e;
+ mark_finished_internal();
+ }
+ void mark_exceptional_finish()
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ mark_exceptional_finish_internal(boost::current_exception());
+ }
+
+ bool has_value()
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ return done && !exception;
+ }
+ bool has_exception()
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ return done && exception;
+ }
+
+ template<typename F,typename U>
+ void set_wait_callback(F f,U* u)
+ {
+ callback=boost::bind(f,boost::ref(*u));
+ }
+
+ private:
+ future_object_base(future_object_base const&);
+ future_object_base& operator=(future_object_base const&);
+ };
+
+ template<typename T>
+ struct future_traits
+ {
+ typedef boost::scoped_ptr<T> storage_type;
+#ifdef BOOST_HAS_RVALUE_REFS
+ typedef T const& source_reference_type;
+ struct dummy;
+ typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,T&&>::type rvalue_source_type;
+ typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,T&&>::type move_dest_type;
+#else
+ typedef T& source_reference_type;
+ typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T const&>::type rvalue_source_type;
+ typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T>::type move_dest_type;
+#endif
+
+ static void init(storage_type& storage,source_reference_type t)
+ {
+ storage.reset(new T(t));
+ }
+
+ static void init(storage_type& storage,rvalue_source_type t)
+ {
+ storage.reset(new T(static_cast<rvalue_source_type>(t)));
+ }
+
+ static void cleanup(storage_type& storage)
+ {
+ storage.reset();
+ }
+ };
+
+ template<typename T>
+ struct future_traits<T&>
+ {
+ typedef T* storage_type;
+ typedef T& source_reference_type;
+ struct rvalue_source_type
+ {};
+ typedef T& move_dest_type;
+
+ static void init(storage_type& storage,T& t)
+ {
+ storage=&t;
+ }
+
+ static void cleanup(storage_type& storage)
+ {
+ storage=0;
+ }
+ };
+
+ template<>
+ struct future_traits<void>
+ {
+ typedef bool storage_type;
+ typedef void move_dest_type;
+
+ static void init(storage_type& storage)
+ {
+ storage=true;
+ }
+
+ static void cleanup(storage_type& storage)
+ {
+ storage=false;
+ }
+
+ };
+
+ template<typename T>
+ struct future_object:
+ detail::future_object_base
+ {
+ typedef typename future_traits<T>::storage_type storage_type;
+ typedef typename future_traits<T>::source_reference_type source_reference_type;
+ typedef typename future_traits<T>::rvalue_source_type rvalue_source_type;
+ typedef typename future_traits<T>::move_dest_type move_dest_type;
+
+ storage_type result;
+
+ future_object():
+ result(0)
+ {}
+
+ void mark_finished_with_result_internal(source_reference_type result_)
+ {
+ future_traits<T>::init(result,result_);
+ mark_finished_internal();
+ }
+ void mark_finished_with_result_internal(rvalue_source_type result_)
+ {
+ future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
+ mark_finished_internal();
+ }
+
+ void mark_finished_with_result(source_reference_type result_)
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ mark_finished_with_result_internal(result_);
+ }
+ void mark_finished_with_result(rvalue_source_type result_)
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ mark_finished_with_result_internal(result_);
+ }
+
+ move_dest_type get()
+ {
+ wait();
+ return *result;
+ }
+
+ future_state::state get_state()
+ {
+ boost::lock_guard<boost::mutex> guard(mutex);
+ if(!done)
+ {
+ return future_state::waiting;
+ }
+ else
+ {
+ return future_state::ready;
+ }
+ }
+
+ private:
+ future_object(future_object const&);
+ future_object& operator=(future_object const&);
+ };
+
+ template<>
+ struct future_object<void>:
+ detail::future_object_base
+ {
+ future_object()
+ {}
+
+ void mark_finished_with_result_internal()
+ {
+ mark_finished_internal();
+ }
+
+ void mark_finished_with_result()
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ mark_finished_with_result_internal();
+ }
+
+ void get()
+ {
+ wait();
+ }
+
+ future_state::state get_state()
+ {
+ boost::lock_guard<boost::mutex> guard(mutex);
+ if(!done)
+ {
+ return future_state::waiting;
+ }
+ else
+ {
+ return future_state::ready;
+ }
+ }
+
+ private:
+ future_object(future_object const&);
+ future_object& operator=(future_object const&);
+ };
+
+ class future_waiter
+ {
+ struct registered_waiter
+ {
+ boost::shared_ptr<detail::future_object_base> future;
+ detail::future_object_base::waiter_list::iterator wait_iterator;
+ unsigned index;
+
+ registered_waiter(boost::shared_ptr<detail::future_object_base> const& future_,
+ detail::future_object_base::waiter_list::iterator wait_iterator_,
+ unsigned index_):
+ future(future_),wait_iterator(wait_iterator_),index(index_)
+ {}
+
+ };
+
+ struct all_futures_lock
+ {
+ unsigned count;
+ boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
+
+ all_futures_lock(std::vector<registered_waiter>& futures):
+ count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
+ {
+ for(unsigned i=0;i<count;++i)
+ {
+ locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex);
+ }
+ }
+
+ void lock()
+ {
+ boost::lock(locks.get(),locks.get()+count);
+ }
+
+ void unlock()
+ {
+ for(unsigned i=0;i<count;++i)
+ {
+ locks[i].unlock();
+ }
+ }
+ };
+
+ boost::condition_variable_any cv;
+ std::vector<registered_waiter> futures;
+ unsigned future_count;
+
+ public:
+ future_waiter():
+ future_count(0)
+ {}
+
+ template<typename F>
+ void add(F& f)
+ {
+ if(f.future)
+ {
+ futures.push_back(registered_waiter(f.future,f.future->register_external_waiter(cv),future_count));
+ }
+ ++future_count;
+ }
+
+ unsigned wait()
+ {
+ all_futures_lock lk(futures);
+ for(;;)
+ {
+ for(unsigned i=0;i<futures.size();++i)
+ {
+ if(futures[i].future->done)
+ {
+ return futures[i].index;
+ }
+ }
+ cv.wait(lk);
+ }
+ }
+
+ ~future_waiter()
+ {
+ for(unsigned i=0;i<futures.size();++i)
+ {
+ futures[i].future->remove_external_waiter(futures[i].wait_iterator);
+ }
+ }
+
+ };
+
+ }
+
+ template <typename R>
+ class unique_future;
+
+ template <typename R>
+ class shared_future;
+
+ template<typename T>
+ struct is_future_type
+ {
+ BOOST_STATIC_CONSTANT(bool, value=false);
+ };
+
+ template<typename T>
+ struct is_future_type<unique_future<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value=true);
+ };
+
+ template<typename T>
+ struct is_future_type<shared_future<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value=true);
+ };
+
+ template<typename Iterator>
+ typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end)
+ {
+ for(Iterator current=begin;current!=end;++current)
+ {
+ current->wait();
+ }
+ }
+
+ template<typename F1,typename F2>
+ typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2)
+ {
+ f1.wait();
+ f2.wait();
+ }
+
+ template<typename F1,typename F2,typename F3>
+ void wait_for_all(F1& f1,F2& f2,F3& f3)
+ {
+ f1.wait();
+ f2.wait();
+ f3.wait();
+ }
+
+ template<typename F1,typename F2,typename F3,typename F4>
+ void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4)
+ {
+ f1.wait();
+ f2.wait();
+ f3.wait();
+ f4.wait();
+ }
+
+ template<typename F1,typename F2,typename F3,typename F4,typename F5>
+ void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
+ {
+ f1.wait();
+ f2.wait();
+ f3.wait();
+ f4.wait();
+ f5.wait();
+ }
+
+ template<typename Iterator>
+ typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
+ {
+ detail::future_waiter waiter;
+ for(Iterator current=begin;current!=end;++current)
+ {
+ waiter.add(*current);
+ }
+ return boost::next(begin,waiter.wait());
+ }
+
+ template<typename F1,typename F2>
+ typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2)
+ {
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ return waiter.wait();
+ }
+
+ template<typename F1,typename F2,typename F3>
+ unsigned wait_for_any(F1& f1,F2& f2,F3& f3)
+ {
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ waiter.add(f3);
+ return waiter.wait();
+ }
+
+ template<typename F1,typename F2,typename F3,typename F4>
+ unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
+ {
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ waiter.add(f3);
+ waiter.add(f4);
+ return waiter.wait();
+ }
+
+ template<typename F1,typename F2,typename F3,typename F4,typename F5>
+ unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
+ {
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ waiter.add(f3);
+ waiter.add(f4);
+ waiter.add(f5);
+ return waiter.wait();
+ }
+
+ template <typename R>
+ class promise;
+
+ template <typename R>
+ class packaged_task;
+
+ template <typename R>
+ class unique_future
+ {
+ unique_future(unique_future & rhs);// = delete;
+ unique_future& operator=(unique_future& rhs);// = delete;
+
+ typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
+
+ future_ptr future;
+
+ friend class shared_future<R>;
+ friend class promise<R>;
+ friend class packaged_task<R>;
+ friend class detail::future_waiter;
+
+ typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
+
+ unique_future(future_ptr future_):
+ future(future_)
+ {}
+
+ public:
+ typedef future_state::state state;
+
+ unique_future()
+ {}
+
+ ~unique_future()
+ {}
+
+#ifdef BOOST_HAS_RVALUE_REFS
+ unique_future(unique_future && other)
+ {
+ future.swap(other.future);
+ }
+ unique_future& operator=(unique_future && other)
+ {
+ future=other.future;
+ other.future.reset();
+ return *this;
+ }
+#else
+ unique_future(boost::detail::thread_move_t<unique_future> other):
+ future(other->future)
+ {
+ other->future.reset();
+ }
+
+ unique_future& operator=(boost::detail::thread_move_t<unique_future> other)
+ {
+ future=other->future;
+ other->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<unique_future>()
+ {
+ return boost::detail::thread_move_t<unique_future>(*this);
+ }
+#endif
+
+ void swap(unique_future& other)
+ {
+ future.swap(other.future);
+ }
+
+ // retrieving the value
+ move_dest_type get()
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+
+ return future->get();
+ }
+
+ // functions to check state, and wait for ready
+ state get_state() const
+ {
+ if(!future)
+ {
+ return future_state::uninitialized;
+ }
+ return future->get_state();
+ }
+
+
+ bool is_ready() const
+ {
+ return get_state()==future_state::ready;
+ }
+
+ bool has_exception() const
+ {
+ return future && future->has_exception();
+ }
+
+ bool has_value() const
+ {
+ return future && future->has_value();
+ }
+
+ void wait() const
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+ future->wait(false);
+ }
+
+ template<typename Duration>
+ bool timed_wait(Duration const& rel_time) const
+ {
+ return timed_wait_until(boost::get_system_time()+rel_time);
+ }
+
+ bool timed_wait_until(boost::system_time const& abs_time) const
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+ return future->timed_wait_until(abs_time);
+ }
+
+ };
+
+ template <typename R>
+ class shared_future
+ {
+ typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
+
+ future_ptr future;
+
+// shared_future(const unique_future<R>& other);
+// shared_future& operator=(const unique_future<R>& other);
+
+ friend class detail::future_waiter;
+ friend class promise<R>;
+ friend class packaged_task<R>;
+
+ shared_future(future_ptr future_):
+ future(future_)
+ {}
+
+ public:
+ shared_future(shared_future const& other):
+ future(other.future)
+ {}
+
+ typedef future_state::state state;
+
+ shared_future()
+ {}
+
+ ~shared_future()
+ {}
+
+ shared_future& operator=(shared_future const& other)
+ {
+ future=other.future;
+ return *this;
+ }
+#ifdef BOOST_HAS_RVALUE_REFS
+ shared_future(shared_future && other)
+ {
+ future.swap(other.future);
+ }
+ shared_future(unique_future<R> && other)
+ {
+ future.swap(other.future);
+ }
+ shared_future& operator=(shared_future && other)
+ {
+ future.swap(other.future);
+ other.future.reset();
+ return *this;
+ }
+ shared_future& operator=(unique_future<R> && other)
+ {
+ future.swap(other.future);
+ other.future.reset();
+ return *this;
+ }
+#else
+ shared_future(boost::detail::thread_move_t<shared_future> other):
+ future(other->future)
+ {
+ other->future.reset();
+ }
+// shared_future(const unique_future<R> &) = delete;
+ shared_future(boost::detail::thread_move_t<unique_future<R> > other):
+ future(other->future)
+ {
+ other->future.reset();
+ }
+ shared_future& operator=(boost::detail::thread_move_t<shared_future> other)
+ {
+ future.swap(other->future);
+ other->future.reset();
+ return *this;
+ }
+ shared_future& operator=(boost::detail::thread_move_t<unique_future<R> > other)
+ {
+ future.swap(other->future);
+ other->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<shared_future>()
+ {
+ return boost::detail::thread_move_t<shared_future>(*this);
+ }
+
+#endif
+
+ void swap(shared_future& other)
+ {
+ future.swap(other.future);
+ }
+
+ // retrieving the value
+ R get()
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+
+ return future->get();
+ }
+
+ // functions to check state, and wait for ready
+ state get_state() const
+ {
+ if(!future)
+ {
+ return future_state::uninitialized;
+ }
+ return future->get_state();
+ }
+
+
+ bool is_ready() const
+ {
+ return get_state()==future_state::ready;
+ }
+
+ bool has_exception() const
+ {
+ return future && future->has_exception();
+ }
+
+ bool has_value() const
+ {
+ return future && future->has_value();
+ }
+
+ void wait() const
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+ future->wait(false);
+ }
+
+ template<typename Duration>
+ bool timed_wait(Duration const& rel_time) const
+ {
+ return timed_wait_until(boost::get_system_time()+rel_time);
+ }
+
+ bool timed_wait_until(boost::system_time const& abs_time) const
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+ return future->timed_wait_until(abs_time);
+ }
+
+ };
+
+ template <typename R>
+ class promise
+ {
+ typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
+
+ future_ptr future;
+ bool future_obtained;
+
+ promise(promise & rhs);// = delete;
+ promise & operator=(promise & rhs);// = delete;
+
+ void lazy_init()
+ {
+ if(!future)
+ {
+ future_obtained=false;
+ future.reset(new detail::future_object<R>);
+ }
+ }
+
+ public:
+// template <class Allocator> explicit promise(Allocator a);
+
+ promise():
+ future(),future_obtained(false)
+ {}
+
+ ~promise()
+ {
+ if(future)
+ {
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+
+ if(!future->done)
+ {
+ future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ }
+ }
+ }
+
+ // Assignment
+#ifdef BOOST_HAS_RVALUE_REFS
+ promise(promise && rhs):
+ future_obtained(rhs.future_obtained)
+ {
+ future.swap(rhs.future);
+ }
+ promise & operator=(promise&& rhs)
+ {
+ future.swap(rhs.future);
+ future_obtained=rhs.future_obtained;
+ rhs.future.reset();
+ return *this;
+ }
+#else
+ promise(boost::detail::thread_move_t<promise> rhs):
+ future(rhs->future),future_obtained(rhs->future_obtained)
+ {
+ rhs->future.reset();
+ }
+ promise & operator=(boost::detail::thread_move_t<promise> rhs)
+ {
+ future=rhs->future;
+ future_obtained=rhs->future_obtained;
+ rhs->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<promise>()
+ {
+ return boost::detail::thread_move_t<promise>(*this);
+ }
+#endif
+
+ void swap(promise& other)
+ {
+ future.swap(other.future);
+ std::swap(future_obtained,other.future_obtained);
+ }
+
+ // Result retrieval
+ unique_future<R> get_future()
+ {
+ lazy_init();
+ if(future_obtained)
+ {
+ throw future_already_retrieved();
+ }
+ future_obtained=true;
+ return unique_future<R>(future);
+ }
+
+ void set_value(typename detail::future_traits<R>::source_reference_type r)
+ {
+ lazy_init();
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_finished_with_result_internal(r);
+ }
+
+// void set_value(R && r);
+ void set_value(typename detail::future_traits<R>::rvalue_source_type r)
+ {
+ lazy_init();
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r));
+ }
+
+ void set_exception(boost::exception_ptr p)
+ {
+ lazy_init();
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_exceptional_finish_internal(p);
+ }
+
+ template<typename F>
+ void set_wait_callback(F f)
+ {
+ lazy_init();
+ future->set_wait_callback(f,this);
+ }
+
+ };
+
+ template <>
+ class promise<void>
+ {
+ typedef boost::shared_ptr<detail::future_object<void> > future_ptr;
+
+ future_ptr future;
+ bool future_obtained;
+
+ promise(promise & rhs);// = delete;
+ promise & operator=(promise & rhs);// = delete;
+
+ void lazy_init()
+ {
+ if(!future)
+ {
+ future_obtained=false;
+ future.reset(new detail::future_object<void>);
+ }
+ }
+ public:
+// template <class Allocator> explicit promise(Allocator a);
+
+ promise():
+ future(),future_obtained(false)
+ {}
+
+ ~promise()
+ {
+ if(future)
+ {
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+
+ if(!future->done)
+ {
+ future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ }
+ }
+ }
+
+ // Assignment
+#ifdef BOOST_HAS_RVALUE_REFS
+ promise(promise && rhs):
+ future_obtained(rhs.future_obtained)
+ {
+ future.swap(rhs.future);
+ }
+ promise & operator=(promise&& rhs)
+ {
+ future.swap(rhs.future);
+ future_obtained=rhs.future_obtained;
+ rhs.future.reset();
+ return *this;
+ }
+#else
+ promise(boost::detail::thread_move_t<promise> rhs):
+ future(rhs->future),future_obtained(rhs->future_obtained)
+ {
+ rhs->future.reset();
+ }
+ promise & operator=(boost::detail::thread_move_t<promise> rhs)
+ {
+ future=rhs->future;
+ future_obtained=rhs->future_obtained;
+ rhs->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<promise>()
+ {
+ return boost::detail::thread_move_t<promise>(*this);
+ }
+#endif
+
+ void swap(promise& other)
+ {
+ future.swap(other.future);
+ std::swap(future_obtained,other.future_obtained);
+ }
+
+ // Result retrieval
+ unique_future<void> get_future()
+ {
+ lazy_init();
+
+ if(future_obtained)
+ {
+ throw future_already_retrieved();
+ }
+ future_obtained=true;
+ return unique_future<void>(future);
+ }
+
+ void set_value()
+ {
+ lazy_init();
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_finished_with_result_internal();
+ }
+
+ void set_exception(boost::exception_ptr p)
+ {
+ lazy_init();
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_exceptional_finish_internal(p);
+ }
+
+ template<typename F>
+ void set_wait_callback(F f)
+ {
+ lazy_init();
+ future->set_wait_callback(f,this);
+ }
+
+ };
+
+ namespace detail
+ {
+ template<typename R>
+ struct task_base:
+ detail::future_object<R>
+ {
+ bool started;
+
+ task_base():
+ started(false)
+ {}
+
+ void run()
+ {
+ {
+ boost::lock_guard<boost::mutex> lk(this->mutex);
+ if(started)
+ {
+ throw task_already_started();
+ }
+ started=true;
+ }
+ do_run();
+ }
+
+ void owner_destroyed()
+ {
+ boost::lock_guard<boost::mutex> lk(this->mutex);
+ if(!started)
+ {
+ started=true;
+ this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()));
+ }
+ }
+
+
+ virtual void do_run()=0;
+ };
+
+
+ template<typename R,typename F>
+ struct task_object:
+ task_base<R>
+ {
+ F f;
+ task_object(F const& f_):
+ f(f_)
+ {}
+ task_object(boost::detail::thread_move_t<F> f_):
+ f(f_)
+ {}
+
+ void do_run()
+ {
+ try
+ {
+ this->mark_finished_with_result(f());
+ }
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+ };
+
+ template<typename F>
+ struct task_object<void,F>:
+ task_base<void>
+ {
+ F f;
+ task_object(F const& f_):
+ f(f_)
+ {}
+ task_object(boost::detail::thread_move_t<F> f_):
+ f(f_)
+ {}
+
+ void do_run()
+ {
+ try
+ {
+ f();
+ this->mark_finished_with_result();
+ }
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+ };
+
+ }
+
+
+ template<typename R>
+ class packaged_task
+ {
+ boost::shared_ptr<detail::task_base<R> > task;
+ bool future_obtained;
+
+ packaged_task(packaged_task&);// = delete;
+ packaged_task& operator=(packaged_task&);// = delete;
+
+ public:
+ packaged_task():
+ future_obtained(false)
+ {}
+
+ // construction and destruction
+ template <class F>
+ explicit packaged_task(F const& f):
+ task(new detail::task_object<R,F>(f)),future_obtained(false)
+ {}
+ explicit packaged_task(R(*f)()):
+ task(new detail::task_object<R,R(*)()>(f)),future_obtained(false)
+ {}
+
+ template <class F>
+ explicit packaged_task(boost::detail::thread_move_t<F> f):
+ task(new detail::task_object<R,F>(f)),future_obtained(false)
+ {}
+
+// template <class F, class Allocator>
+// explicit packaged_task(F const& f, Allocator a);
+// template <class F, class Allocator>
+// explicit packaged_task(F&& f, Allocator a);
+
+
+ ~packaged_task()
+ {
+ if(task)
+ {
+ task->owner_destroyed();
+ }
+ }
+
+ // assignment
+#ifdef BOOST_HAS_RVALUE_REFS
+ packaged_task(packaged_task&& other):
+ future_obtained(other.future_obtained)
+ {
+ task.swap(other.task);
+ other.future_obtained=false;
+ }
+ packaged_task& operator=(packaged_task&& other)
+ {
+ packaged_task temp(static_cast<packaged_task&&>(other));
+ swap(temp);
+ return *this;
+ }
+#else
+ packaged_task(boost::detail::thread_move_t<packaged_task> other):
+ future_obtained(other->future_obtained)
+ {
+ task.swap(other->task);
+ other->future_obtained=false;
+ }
+ packaged_task& operator=(boost::detail::thread_move_t<packaged_task> other)
+ {
+ packaged_task temp(other);
+ swap(temp);
+ return *this;
+ }
+ operator boost::detail::thread_move_t<packaged_task>()
+ {
+ return boost::detail::thread_move_t<packaged_task>(*this);
+ }
+#endif
+
+ void swap(packaged_task& other)
+ {
+ task.swap(other.task);
+ std::swap(future_obtained,other.future_obtained);
+ }
+
+ // result retrieval
+ unique_future<R> get_future()
+ {
+ if(!task)
+ {
+ throw task_moved();
+ }
+ else if(!future_obtained)
+ {
+ future_obtained=true;
+ return unique_future<R>(task);
+ }
+ else
+ {
+ throw future_already_retrieved();
+ }
+ }
+
+
+ // execution
+ void operator()()
+ {
+ if(!task)
+ {
+ throw task_moved();
+ }
+ task->run();
+ }
+
+ template<typename F>
+ void set_wait_callback(F f)
+ {
+ task->set_wait_callback(f,this);
+ }
+
+ };
+
+}
+#if 1
+namespace boost
+{
+ template<typename T>
+ detail::thread_move_t<boost::packaged_task<T> > move(boost::packaged_task<T>& t)
+ {
+ return detail::thread_move_t<boost::packaged_task<T> >(t);
+ }
+}
+
+#endif
+
+
+
+#endif

Added: sandbox/async/boost/futures/index.html
==============================================================================
--- (empty file)
+++ sandbox/async/boost/futures/index.html 2009-10-13 03:02:10 EDT (Tue, 13 Oct 2009)
@@ -0,0 +1,1806 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Futures</title>
+<link rel="stylesheet" href="boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
+<link rel="start" href="index.html" title="Futures">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="http://www.boost.org/boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</tr></table>
+<hr>
+<div class="spirit-nav"></div>
+<div class="article" lang="en">
+<div class="titlepage">
+<div>
+<div><h2 class="title">
+<a name="futures"></a>Futures</h2></div>
+<div><div class="authorgroup"><div class="author"><h3 class="author">
+<span class="firstname">Anthony</span> <span class="surname">Williams</span>
+</h3></div></div></div>
+<div><p class="copyright">Copyright © 2008 Anthony Williams</p></div>
+<div><div class="legalnotice">
+<a name="id437295"></a><p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ </p>
+</div></div>
+</div>
+<hr>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="section"> Overview</span></dt>
+<dt><span class="section"> Creating asynchronous values</span></dt>
+<dt><span class="section"> Wait Callbacks and Lazy Futures</span></dt>
+<dt><span class="section"> Reference</span></dt>
+<dd><dl>
+<dt><span class="section"><a href="index.html#futures.reference.future_state"> <code class="computeroutput"><span class="identifier">state</span></code>
+ enum</a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future"> <code class="computeroutput"><span class="identifier">unique_future</span></code>
+ class template</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.default_constructor">
+ Default Constructor</a></span></dt>
+<dt><span class="section"> Destructor</span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.move_constructor">
+ Move Constructor</a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.move_assignment"> Move
+ Assignment Operator</a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.swap"> Member function
+ <code class="computeroutput"><span class="identifier">swap</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.get"> Member function
+ <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.wait"> Member function
+ <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.timed_wait_duration">
+ Member function <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.timed_wait_absolute">
+ Member function <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.is_ready"> Member function
+ <code class="computeroutput"><span class="identifier">is_ready</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.has_value"> Member
+ function <code class="computeroutput"><span class="identifier">has_value</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.has_exception"> Member
+ function <code class="computeroutput"><span class="identifier">has_exception</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.unique_future.get_state"> Member
+ function <code class="computeroutput"><span class="identifier">get_state</span><span class="special">()</span></code></a></span></dt>
+</dl></dd>
+<dt><span class="section"><a href="index.html#futures.reference.shared_future"> <code class="computeroutput"><span class="identifier">shared_future</span></code>
+ class template</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="index.html#futures.reference.shared_future.default_constructor">
+ Default Constructor</a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.shared_future.get"> Member function
+ <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.shared_future.wait"> Member function
+ <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.shared_future.timed_wait_duration">
+ Member function <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.shared_future.timed_wait_absolute">
+ Member function <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.shared_future.is_ready"> Member function
+ <code class="computeroutput"><span class="identifier">is_ready</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.shared_future.has_value"> Member
+ function <code class="computeroutput"><span class="identifier">has_value</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.shared_future.has_exception"> Member
+ function <code class="computeroutput"><span class="identifier">has_exception</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.shared_future.get_state"> Member
+ function <code class="computeroutput"><span class="identifier">get_state</span><span class="special">()</span></code></a></span></dt>
+</dl></dd>
+<dt><span class="section"><a href="index.html#futures.reference.promise"> <code class="computeroutput"><span class="identifier">promise</span></code>
+ class template</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="index.html#futures.reference.promise.default_constructor"> Default
+ Constructor</a></span></dt>
+<dt><span class="section"> Move Constructor</span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.promise.move_assignment"> Move Assignment
+ Operator</a></span></dt>
+<dt><span class="section"> Destructor</span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.promise.get_future"> Member Function
+ <code class="computeroutput"><span class="identifier">get_future</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.promise.set_value"> Member Function
+ <code class="computeroutput"><span class="identifier">set_value</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.promise.set_exception"> Member Function
+ <code class="computeroutput"><span class="identifier">set_exception</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.promise.set_wait_callback"> Member
+ Function <code class="computeroutput"><span class="identifier">set_wait_callback</span><span class="special">()</span></code></a></span></dt>
+</dl></dd>
+<dt><span class="section"><a href="index.html#futures.reference.packaged_task"> <code class="computeroutput"><span class="identifier">packaged_task</span></code>
+ class template</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="index.html#futures.reference.packaged_task.task_constructor">
+ Task Constructor</a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.packaged_task.move_constructor">
+ Move Constructor</a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.packaged_task.move_assignment"> Move
+ Assignment Operator</a></span></dt>
+<dt><span class="section"> Destructor</span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.packaged_task.get_future"> Member
+ Function <code class="computeroutput"><span class="identifier">get_future</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.packaged_task.call_operator"> Member
+ Function <code class="computeroutput"><span class="keyword">operator</span><span class="special">()()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.packaged_task.set_wait_callback">
+ Member Function <code class="computeroutput"><span class="identifier">set_wait_callback</span><span class="special">()</span></code></a></span></dt>
+</dl></dd>
+<dt><span class="section"><a href="index.html#futures.reference.wait_for_any"> Non-member function
+ <code class="computeroutput"><span class="identifier">wait_for_any</span><span class="special">()</span></code></a></span></dt>
+<dt><span class="section"><a href="index.html#futures.reference.wait_for_all"> Non-member function
+ <code class="computeroutput"><span class="identifier">wait_for_all</span><span class="special">()</span></code></a></span></dt>
+</dl></dd>
+</dl>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="futures.overview"></a> Overview</h2></div></div></div>
+<p>
+ The futures library provides a means of handling synchronous future values,
+ whether those values are generated by another thread, or on a single thread
+ in response to external stimuli, or on-demand.
+ </p>
+<p>
+ This is done through the provision of four class templates: jss::unique_future
+ and jss::shared_future
+ which are used to retrieve the asynchronous results, and jss::promise
+ and jss::packaged_task
+ which are used to generate the asynchronous results.
+ </p>
+<p>
+ An instance of jss::unique_future
+ holds the one and only reference to a result. Ownership can be transferred
+ between instances using the move constructor or move-assignment operator, but
+ at most one instance holds a reference to a given asynchronous result. When
+ the result is ready, it is returned from jss::unique_future<R>::get()
+ by rvalue-reference to allow the result to be moved or copied as appropriate
+ for the type.
+ </p>
+<p>
+ On the other hand, many instances of jss::shared_future
+ may reference the same result. Instances can be freely copied and assigned,
+ and jss::shared_future<R>::get()
+ returns a <code class="computeroutput"><span class="keyword">const</span></code> reference so that
+ multiple calls to jss::shared_future<R>::get()
+ are safe. You can move an instance of jss::unique_future
+ into an instance of jss::shared_future,
+ thus transferring ownership of the associated asynchronous result, but not
+ vice-versa.
+ </p>
+<p>
+ You can wait for futures either individually or with one of the jss::wait_for_any() and jss::wait_for_all() functions.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="futures.creating"></a> Creating asynchronous values</h2></div></div></div>
+<p>
+ You can set the value in a future with either a jss::promise
+ or a jss::packaged_task.
+ A jss::packaged_task
+ is a callable object that wraps a function or callable object. When the packaged
+ task is invoked, it invokes the contained function in turn, and populates a
+ future with the return value. This is an answer to the perennial question:
+ "how do I return a value from a thread?": package the function you
+ wish to run as a jss::packaged_task
+ and pass the packaged task to the thread constructor. The future retrieved
+ from the packaged task can then be used to obtain the return value. If the
+ function throws an exception, that is stored in the future in place of the
+ return value.
+ </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">calculate_the_answer_to_life_the_universe_and_everything</span><span class="special">()</span>
+<span class="special">{</span>
+ <span class="keyword">return</span> <span class="number">42</span><span class="special">;</span>
+<span class="special">}</span>
+
+<span class="identifier">jss</span><span class="special">::</span><span class="identifier">packaged_task</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">pt</span><span class="special">(</span><span class="identifier">calculate_the_answer_to_life_the_universe_and_everything</span><span class="special">);</span>
+<span class="identifier">jss</span><span class="special">::</span><span class="identifier">unique_future</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">fi</span><span class="special">=</span><span class="identifier">pt</span><span class="special">.</span><span class="identifier">get_future</span><span class="special">();</span>
+
+<span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread</span> <span class="identifier">task</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">pt</span><span class="special">));</span> <span class="comment">// launch task on a thread
+</span>
+<span class="identifier">fi</span><span class="special">.</span><span class="identifier">wait</span><span class="special">();</span> <span class="comment">// wait for it to finish
+</span>
+<span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">is_ready</span><span class="special">());</span>
+<span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">has_value</span><span class="special">());</span>
+<span class="identifier">assert</span><span class="special">(!</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">has_exception</span><span class="special">());</span>
+<span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">get_state</span><span class="special">()==</span><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_state</span><span class="special">::</span><span class="identifier">ready</span><span class="special">);</span>
+<span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">get</span><span class="special">()==</span><span class="number">42</span><span class="special">);</span>
+</pre>
+<p>
+ A jss::promise
+ is a bit more low level: it just provides explicit functions to store a value
+ or an exception in the associated future. A promise can therefore be used where
+ the value may come from more than one possible source, or where a single operation
+ may produce multiple values.
+ </p>
+<pre class="programlisting">
+<span class="identifier">jss</span><span class="special">::</span><span class="identifier">promise</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">pi</span><span class="special">;</span>
+<span class="identifier">jss</span><span class="special">::</span><span class="identifier">unique_future</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">fi</span><span class="special">;</span>
+<span class="identifier">fi</span><span class="special">=</span><span class="identifier">pi</span><span class="special">.</span><span class="identifier">get_future</span><span class="special">();</span>
+
+<span class="identifier">pi</span><span class="special">.</span><span class="identifier">set_value</span><span class="special">(</span><span class="number">42</span><span class="special">);</span>
+
+<span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">is_ready</span><span class="special">());</span>
+<span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">has_value</span><span class="special">());</span>
+<span class="identifier">assert</span><span class="special">(!</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">has_exception</span><span class="special">());</span>
+<span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">get_state</span><span class="special">()==</span><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_state</span><span class="special">::</span><span class="identifier">ready</span><span class="special">);</span>
+<span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">get</span><span class="special">()==</span><span class="number">42</span><span class="special">);</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="futures.lazy_futures"></a> Wait Callbacks and Lazy Futures</h2></div></div></div>
+<p>
+ Both jss::promise
+ and jss::packaged_task
+ support <span class="emphasis"><em>wait callbacks</em></span> that are invoked when a thread
+ blocks in a call to <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code>
+ or <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code>
+ on a future that is waiting for the result from the jss::promise
+ or jss::packaged_task,
+ in the thread that is doing the waiting. These can be set using the <code class="computeroutput"><span class="identifier">set_wait_callback</span><span class="special">()</span></code>
+ member function on the jss::promise
+ or jss::packaged_task
+ in question.
+ </p>
+<p>
+ This allows <span class="emphasis"><em>lazy futures</em></span> where the result is not actually
+ computed until it is needed by some thread. In the example below, the call
+ to <code class="computeroutput"><span class="identifier">f</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span></code> invokes
+ the callback <code class="computeroutput"><span class="identifier">invoke_lazy_task</span></code>,
+ which runs the task to set the value. If you remove the call to <code class="computeroutput"><span class="identifier">f</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span></code>, the task is not ever run.
+ </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">calculate_the_answer_to_life_the_universe_and_everything</span><span class="special">()</span>
+<span class="special">{</span>
+ <span class="keyword">return</span> <span class="number">42</span><span class="special">;</span>
+<span class="special">}</span>
+
+<span class="keyword">void</span> <span class="identifier">invoke_lazy_task</span><span class="special">(</span><span class="identifier">jss</span><span class="special">::</span><span class="identifier">packaged_task</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;&amp;</span> <span class="identifier">task</span><span class="special">)</span>
+<span class="special">{</span>
+ <span class="keyword">try</span>
+ <span class="special">{</span>
+ <span class="identifier">task</span><span class="special">();</span>
+ <span class="special">}</span>
+ <span class="keyword">catch</span><span class="special">(</span><span class="identifier">jss</span><span class="special">::</span><span class="identifier">task_already_started</span><span class="special">&amp;)</span>
+ <span class="special">{}</span>
+<span class="special">}</span>
+
+<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
+<span class="special">{</span>
+ <span class="identifier">jss</span><span class="special">::</span><span class="identifier">packaged_task</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">task</span><span class="special">(</span><span class="identifier">calculate_the_answer_to_life_the_universe_and_everything</span><span class="special">);</span>
+ <span class="identifier">task</span><span class="special">.</span><span class="identifier">set_wait_callback</span><span class="special">(</span><span class="identifier">invoke_lazy_task</span><span class="special">);</span>
+ <span class="identifier">jss</span><span class="special">::</span><span class="identifier">unique_future</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">task</span><span class="special">.</span><span class="identifier">get_future</span><span class="special">());</span>
+
+ <span class="identifier">assert</span><span class="special">(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">get</span><span class="special">()==</span><span class="number">42</span><span class="special">);</span>
+<span class="special">}</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="futures.reference"></a> Reference</h2></div></div></div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="futures.reference.future_state"></a><a href="index.html#futures.reference.future_state" title="state enum"> <code class="computeroutput"><span class="identifier">state</span></code>
+ enum</a></h3></div></div></div>
+<pre class="programlisting">
+<span class="keyword">namespace</span> <span class="identifier">future_state</span>
+<span class="special">{</span>
+ <span class="keyword">enum</span> <span class="identifier">state</span> <span class="special">{</span><span class="identifier">uninitialized</span><span class="special">,</span> <span class="identifier">waiting</span><span class="special">,</span> <span class="identifier">ready</span><span class="special">};</span>
+<span class="special">}</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="futures.reference.unique_future"></a><a href="index.html#futures.reference.unique_future" title="unique_future class template"> <code class="computeroutput"><span class="identifier">unique_future</span></code>
+ class template</a></h3></div></div></div>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">R</span><span class="special">&gt;</span>
+<span class="keyword">class</span> <span class="identifier">unique_future</span>
+<span class="special">{</span>
+ <span class="identifier">unique_future</span><span class="special">(</span><span class="identifier">unique_future</span> <span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);//</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span>
+ <span class="identifier">unique_future</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">unique_future</span><span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);//</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span>
+
+<span class="keyword">public</span><span class="special">:</span>
+ <span class="keyword">typedef</span> <span class="identifier">future_state</span><span class="special">::</span><span class="identifier">state</span> <span class="identifier">state</span><span class="special">;</span>
+
+ <span class="identifier">unique_future</span><span class="special">();</span>
+ <span class="special">~</span><span class="identifier">unique_future</span><span class="special">();</span>
+
+ <span class="comment">// move support
+</span> <span class="identifier">unique_future</span><span class="special">(</span><span class="identifier">unique_future</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+ <span class="identifier">unique_future</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">unique_future</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+
+ <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">unique_future</span><span class="special">&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+
+ <span class="comment">// retrieving the value
+</span> <span class="identifier">R</span><span class="special">&amp;&amp;</span> <span class="identifier">get</span><span class="special">();</span>
+
+ <span class="comment">// functions to check state
+</span> <span class="identifier">state</span> <span class="identifier">get_state</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+ <span class="keyword">bool</span> <span class="identifier">is_ready</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+ <span class="keyword">bool</span> <span class="identifier">has_exception</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+ <span class="keyword">bool</span> <span class="identifier">has_value</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+
+ <span class="comment">// waiting for the result to be ready
+</span> <span class="keyword">void</span> <span class="identifier">wait</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+ <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Duration</span><span class="special">&gt;</span>
+ <span class="keyword">bool</span> <span class="identifier">timed_wait</span><span class="special">(</span><span class="identifier">Duration</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rel_time</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+ <span class="keyword">bool</span> <span class="identifier">timed_wait_until</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">system_time</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">abs_time</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+<span class="special">};</span>
+</pre>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.default_constructor"></a><a href="index.html#futures.reference.unique_future.default_constructor" title="Default Constructor">
+ Default Constructor</a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">unique_future</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Constructs an uninitialized future.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ this->is_ready returns <code class="computeroutput"><span class="keyword">false</span></code>. this->get_state()
+ returns jss::future_state::uninitialized.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.destructor"></a> Destructor</h4></div></div></div>
+<pre class="programlisting">
+<span class="special">~</span><span class="identifier">unique_future</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Destroys <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.move_constructor"></a><a href="index.html#futures.reference.unique_future.move_constructor" title="Move Constructor">
+ Move Constructor</a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">unique_future</span><span class="special">(</span><span class="identifier">unique_future</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Constructs a new future, and transfers ownership of the asynchronous
+ result associated with <code class="computeroutput"><span class="identifier">other</span></code>
+ to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ this->get_state()
+ returns the value of <code class="computeroutput"><span class="identifier">other</span><span class="special">-&gt;</span><span class="identifier">get_state</span><span class="special">()</span></code> prior to the call. <code class="computeroutput"><span class="identifier">other</span><span class="special">-&gt;</span><span class="identifier">get_state</span><span class="special">()</span></code>
+ returns jss::future_state::uninitialized. If <code class="computeroutput"><span class="identifier">other</span></code> was associated with an asynchronous
+ result, that result is now associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. <code class="computeroutput"><span class="identifier">other</span></code>
+ is not associated with any asynchronous result.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ If the compiler does not support rvalue-references, this is implemented
+ using the boost.thread move emulation.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.move_assignment"></a><a href="index.html#futures.reference.unique_future.move_assignment" title="Move Assignment Operator"> Move
+ Assignment Operator</a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">unique_future</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">unique_future</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Transfers ownership of the asynchronous result associated with <code class="computeroutput"><span class="identifier">other</span></code> to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ this->get_state()
+ returns the value of <code class="computeroutput"><span class="identifier">other</span><span class="special">-&gt;</span><span class="identifier">get_state</span><span class="special">()</span></code> prior to the call. <code class="computeroutput"><span class="identifier">other</span><span class="special">-&gt;</span><span class="identifier">get_state</span><span class="special">()</span></code>
+ returns jss::future_state::uninitialized. If <code class="computeroutput"><span class="identifier">other</span></code> was associated with an asynchronous
+ result, that result is now associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. <code class="computeroutput"><span class="identifier">other</span></code>
+ is not associated with any asynchronous result. If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> was associated with an asynchronous
+ result prior to the call, that result no longer has an associated
+ jss::unique_future
+ instance.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ If the compiler does not support rvalue-references, this is implemented
+ using the boost.thread move emulation.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.swap"></a><a href="index.html#futures.reference.unique_future.swap" title="Member function swap()"> Member function
+ <code class="computeroutput"><span class="identifier">swap</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">unique_future</span> <span class="special">&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Swaps ownership of the asynchronous results associated with <code class="computeroutput"><span class="identifier">other</span></code> and <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ this->get_state()
+ returns the value of <code class="computeroutput"><span class="identifier">other</span><span class="special">-&gt;</span><span class="identifier">get_state</span><span class="special">()</span></code> prior to the call. <code class="computeroutput"><span class="identifier">other</span><span class="special">-&gt;</span><span class="identifier">get_state</span><span class="special">()</span></code>
+ returns the value of <code class="computeroutput"><span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_state</span><span class="special">()</span></code> prior to the call. If <code class="computeroutput"><span class="identifier">other</span></code> was associated with an asynchronous
+ result, that result is now associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>, otherwise <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> has no associated result. If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ was associated with an asynchronous result, that result is now associated
+ with <code class="computeroutput"><span class="identifier">other</span></code>, otherwise
+ <code class="computeroutput"><span class="identifier">other</span></code> has no associated
+ result.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.get"></a><a href="index.html#futures.reference.unique_future.get" title="Member function get()"> Member function
+ <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">R</span><span class="special">&amp;&amp;</span> <span class="identifier">get</span><span class="special">();</span>
+<span class="identifier">R</span><span class="special">&amp;</span> <span class="identifier">unique_future</span><span class="special">&lt;</span><span class="identifier">R</span><span class="special">&amp;&gt;::</span><span class="identifier">get</span><span class="special">();</span>
+<span class="keyword">void</span> <span class="identifier">unique_future</span><span class="special">&lt;</span><span class="keyword">void</span><span class="special">&gt;::</span><span class="identifier">get</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, waits until the result is
+ ready as-if by a call to jss::unique_future<R>::wait(),
+ and retrieves the result (whether that is a value or an exception).
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ If the result type <code class="computeroutput"><span class="identifier">R</span></code>
+ is a reference, returns the stored reference. If <code class="computeroutput"><span class="identifier">R</span></code>
+ is <code class="computeroutput"><span class="keyword">void</span></code>, there is no return
+ value. Otherwise, returns an rvalue-reference to the value stored in
+ the asynchronous result.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ this->is_ready()
+ returns <code class="computeroutput"><span class="keyword">true</span></code>. this->get_state()
+ returns jss::future_state::ready.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_uninitialized</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is not associated with an asynchronous result. <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread_interrupted</span></code>
+ if the result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is not ready at the point of the
+ call, and the current thread is interrupted. Any exception stored in
+ the asynchronous result in place of a value.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code>
+ is an <span class="emphasis"><em>interruption point</em></span>.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.wait"></a><a href="index.html#futures.reference.unique_future.wait" title="Member function wait()"> Member function
+ <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">void</span> <span class="identifier">wait</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, waits until the result is
+ ready. If the result is not ready on entry, and the result has a <span class="emphasis"><em>wait
+ callback</em></span> set, that callback is invoked prior to waiting.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_uninitialized</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is not associated with an asynchronous result. <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread_interrupted</span></code>
+ if the result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is not ready at the point of the
+ call, and the current thread is interrupted. Any exception thrown by
+ the <span class="emphasis"><em>wait callback</em></span> if such a callback is called.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ this->is_ready()
+ returns <code class="computeroutput"><span class="keyword">true</span></code>. this->get_state()
+ returns jss::future_state::ready.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code>
+ is an <span class="emphasis"><em>interruption point</em></span>.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.timed_wait_duration"></a><a href="index.html#futures.reference.unique_future.timed_wait_duration" title="Member function timed_wait()">
+ Member function <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Duration</span><span class="special">&gt;</span>
+<span class="keyword">bool</span> <span class="identifier">timed_wait</span><span class="special">(</span><span class="identifier">Duration</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">wait_duration</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, waits until the result is
+ ready, or the time specified by <code class="computeroutput"><span class="identifier">wait_duration</span></code>
+ has elapsed. If the result is not ready on entry, and the result has
+ a <span class="emphasis"><em>wait callback</em></span> set, that callback is invoked
+ prior to waiting.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, and that result is ready
+ before the specified time has elapsed, <code class="computeroutput"><span class="keyword">false</span></code>
+ otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_uninitialized</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is not associated with an asynchronous result. <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread_interrupted</span></code>
+ if the result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is not ready at the point of the
+ call, and the current thread is interrupted. Any exception thrown by
+ the <span class="emphasis"><em>wait callback</em></span> if such a callback is called.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ If this call returned <code class="computeroutput"><span class="keyword">true</span></code>,
+ then this->is_ready()
+ returns <code class="computeroutput"><span class="keyword">true</span></code> and this->get_state() returns jss::future_state::ready.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code>
+ is an <span class="emphasis"><em>interruption point</em></span>. <code class="computeroutput"><span class="identifier">Duration</span></code>
+ must be a type that meets the Boost.DateTime time duration requirements.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.timed_wait_absolute"></a><a href="index.html#futures.reference.unique_future.timed_wait_absolute" title="Member function timed_wait()">
+ Member function <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">bool</span> <span class="identifier">timed_wait</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">system_time</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">wait_timeout</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, waits until the result is
+ ready, or the time point specified by <code class="computeroutput"><span class="identifier">wait_timeout</span></code>
+ has passed. If the result is not ready on entry, and the result has
+ a <span class="emphasis"><em>wait callback</em></span> set, that callback is invoked
+ prior to waiting.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, and that result is ready
+ before the specified time has passed, <code class="computeroutput"><span class="keyword">false</span></code>
+ otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_uninitialized</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is not associated with an asynchronous result. <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread_interrupted</span></code>
+ if the result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is not ready at the point of the
+ call, and the current thread is interrupted. Any exception thrown by
+ the <span class="emphasis"><em>wait callback</em></span> if such a callback is called.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ If this call returned <code class="computeroutput"><span class="keyword">true</span></code>,
+ then this->is_ready()
+ returns <code class="computeroutput"><span class="keyword">true</span></code> and this->get_state() returns jss::future_state::ready.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code>
+ is an <span class="emphasis"><em>interruption point</em></span>.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.is_ready"></a><a href="index.html#futures.reference.unique_future.is_ready" title="Member function is_ready()"> Member function
+ <code class="computeroutput"><span class="identifier">is_ready</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">bool</span> <span class="identifier">is_ready</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Checks to see if the asynchronous result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is set.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, and that result is ready
+ for retrieval, <code class="computeroutput"><span class="keyword">false</span></code> otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.has_value"></a><a href="index.html#futures.reference.unique_future.has_value" title="Member function has_value()"> Member
+ function <code class="computeroutput"><span class="identifier">has_value</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">bool</span> <span class="identifier">has_value</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Checks to see if the asynchronous result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is set with a value rather than an exception.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, that result is ready for
+ retrieval, and the result is a stored value, <code class="computeroutput"><span class="keyword">false</span></code>
+ otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.has_exception"></a><a href="index.html#futures.reference.unique_future.has_exception" title="Member function has_exception()"> Member
+ function <code class="computeroutput"><span class="identifier">has_exception</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">bool</span> <span class="identifier">has_exception</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Checks to see if the asynchronous result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is set with an exception rather than a value.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, that result is ready for
+ retrieval, and the result is a stored exception, <code class="computeroutput"><span class="keyword">false</span></code>
+ otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.unique_future.get_state"></a><a href="index.html#futures.reference.unique_future.get_state" title="Member function get_state()"> Member
+ function <code class="computeroutput"><span class="identifier">get_state</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">future_state</span><span class="special">::</span><span class="identifier">state</span> <span class="identifier">get_state</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Determine the state of the asynchronous result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>,
+ if any.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ jss::future_state::uninitialized
+ if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is not associated with an asynchronous result. jss::future_state::ready if the asynchronous
+ result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is ready for retrieval, jss::future_state::waiting otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="futures.reference.shared_future"></a><a href="index.html#futures.reference.shared_future" title="shared_future class template"> <code class="computeroutput"><span class="identifier">shared_future</span></code>
+ class template</a></h3></div></div></div>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">R</span><span class="special">&gt;</span>
+<span class="keyword">class</span> <span class="identifier">shared_future</span>
+<span class="special">{</span>
+<span class="keyword">public</span><span class="special">:</span>
+ <span class="keyword">typedef</span> <span class="identifier">future_state</span><span class="special">::</span><span class="identifier">state</span> <span class="identifier">state</span><span class="special">;</span>
+
+ <span class="identifier">shared_future</span><span class="special">();</span>
+ <span class="special">~</span><span class="identifier">shared_future</span><span class="special">();</span>
+
+ <span class="comment">// copy support
+</span> <span class="identifier">shared_future</span><span class="special">(</span><span class="identifier">shared_future</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+ <span class="identifier">shared_future</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">shared_future</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+
+ <span class="comment">// move support
+</span> <span class="identifier">shared_future</span><span class="special">(</span><span class="identifier">shared_future</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+ <span class="identifier">shared_future</span><span class="special">(</span><span class="identifier">unique_future</span><span class="special">&lt;</span><span class="identifier">R</span><span class="special">&gt;</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+ <span class="identifier">shared_future</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">shared_future</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+ <span class="identifier">shared_future</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">unique_future</span><span class="special">&lt;</span><span class="identifier">R</span><span class="special">&gt;</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+
+ <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">shared_future</span><span class="special">&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+
+ <span class="comment">// retrieving the value
+</span> <span class="identifier">R</span> <span class="identifier">get</span><span class="special">();</span>
+
+ <span class="comment">// functions to check state, and wait for ready
+</span> <span class="identifier">state</span> <span class="identifier">get_state</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+ <span class="keyword">bool</span> <span class="identifier">is_ready</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+ <span class="keyword">bool</span> <span class="identifier">has_exception</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+ <span class="keyword">bool</span> <span class="identifier">has_value</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+
+ <span class="comment">// waiting for the result to be ready
+</span> <span class="keyword">void</span> <span class="identifier">wait</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+ <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Duration</span><span class="special">&gt;</span>
+ <span class="keyword">bool</span> <span class="identifier">timed_wait</span><span class="special">(</span><span class="identifier">Duration</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rel_time</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+ <span class="keyword">bool</span> <span class="identifier">timed_wait_until</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">system_time</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">abs_time</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+<span class="special">};</span>
+</pre>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.shared_future.default_constructor"></a><a href="index.html#futures.reference.shared_future.default_constructor" title="Default Constructor">
+ Default Constructor</a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">shared_future</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Constructs an uninitialized future.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ this->is_ready returns <code class="computeroutput"><span class="keyword">false</span></code>. this->get_state()
+ returns jss::future_state::uninitialized.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.shared_future.get"></a><a href="index.html#futures.reference.shared_future.get" title="Member function get()"> Member function
+ <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">const</span> <span class="identifier">R</span><span class="special">&amp;</span> <span class="identifier">get</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, waits until the result is
+ ready as-if by a call to jss::shared_future<R>::wait(),
+ and returns a <code class="computeroutput"><span class="keyword">const</span></code> reference
+ to the result.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ If the result type <code class="computeroutput"><span class="identifier">R</span></code>
+ is a reference, returns the stored reference. If <code class="computeroutput"><span class="identifier">R</span></code>
+ is <code class="computeroutput"><span class="keyword">void</span></code>, there is no return
+ value. Otherwise, returns a <code class="computeroutput"><span class="keyword">const</span></code>
+ reference to the value stored in the asynchronous result.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_uninitialized</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is not associated with an asynchronous result. <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread_interrupted</span></code>
+ if the result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is not ready at the point of the
+ call, and the current thread is interrupted.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code>
+ is an <span class="emphasis"><em>interruption point</em></span>.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.shared_future.wait"></a><a href="index.html#futures.reference.shared_future.wait" title="Member function wait()"> Member function
+ <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">void</span> <span class="identifier">wait</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, waits until the result is
+ ready. If the result is not ready on entry, and the result has a <span class="emphasis"><em>wait
+ callback</em></span> set, that callback is invoked prior to waiting.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_uninitialized</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is not associated with an asynchronous result. <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread_interrupted</span></code>
+ if the result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is not ready at the point of the
+ call, and the current thread is interrupted. Any exception thrown by
+ the <span class="emphasis"><em>wait callback</em></span> if such a callback is called.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ this->is_ready()
+ returns <code class="computeroutput"><span class="keyword">true</span></code>. this->get_state()
+ returns jss::future_state::ready.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code>
+ is an <span class="emphasis"><em>interruption point</em></span>.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.shared_future.timed_wait_duration"></a><a href="index.html#futures.reference.shared_future.timed_wait_duration" title="Member function timed_wait()">
+ Member function <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Duration</span><span class="special">&gt;</span>
+<span class="keyword">bool</span> <span class="identifier">timed_wait</span><span class="special">(</span><span class="identifier">Duration</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">wait_duration</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, waits until the result is
+ ready, or the time specified by <code class="computeroutput"><span class="identifier">wait_duration</span></code>
+ has elapsed. If the result is not ready on entry, and the result has
+ a <span class="emphasis"><em>wait callback</em></span> set, that callback is invoked
+ prior to waiting.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, and that result is ready
+ before the specified time has elapsed, <code class="computeroutput"><span class="keyword">false</span></code>
+ otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_uninitialized</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is not associated with an asynchronous result. <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread_interrupted</span></code>
+ if the result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is not ready at the point of the
+ call, and the current thread is interrupted. Any exception thrown by
+ the <span class="emphasis"><em>wait callback</em></span> if such a callback is called.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ If this call returned <code class="computeroutput"><span class="keyword">true</span></code>,
+ then this->is_ready()
+ returns <code class="computeroutput"><span class="keyword">true</span></code> and this->get_state() returns jss::future_state::ready.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code>
+ is an <span class="emphasis"><em>interruption point</em></span>. <code class="computeroutput"><span class="identifier">Duration</span></code>
+ must be a type that meets the Boost.DateTime time duration requirements.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.shared_future.timed_wait_absolute"></a><a href="index.html#futures.reference.shared_future.timed_wait_absolute" title="Member function timed_wait()">
+ Member function <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">bool</span> <span class="identifier">timed_wait</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">system_time</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">wait_timeout</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, waits until the result is
+ ready, or the time point specified by <code class="computeroutput"><span class="identifier">wait_timeout</span></code>
+ has passed. If the result is not ready on entry, and the result has
+ a <span class="emphasis"><em>wait callback</em></span> set, that callback is invoked
+ prior to waiting.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, and that result is ready
+ before the specified time has passed, <code class="computeroutput"><span class="keyword">false</span></code>
+ otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_uninitialized</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is not associated with an asynchronous result. <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread_interrupted</span></code>
+ if the result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is not ready at the point of the
+ call, and the current thread is interrupted. Any exception thrown by
+ the <span class="emphasis"><em>wait callback</em></span> if such a callback is called.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ If this call returned <code class="computeroutput"><span class="keyword">true</span></code>,
+ then this->is_ready()
+ returns <code class="computeroutput"><span class="keyword">true</span></code> and this->get_state() returns jss::future_state::ready.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">timed_wait</span><span class="special">()</span></code>
+ is an <span class="emphasis"><em>interruption point</em></span>.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.shared_future.is_ready"></a><a href="index.html#futures.reference.shared_future.is_ready" title="Member function is_ready()"> Member function
+ <code class="computeroutput"><span class="identifier">is_ready</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">bool</span> <span class="identifier">is_ready</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Checks to see if the asynchronous result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is set.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, and that result is ready
+ for retrieval, <code class="computeroutput"><span class="keyword">false</span></code> otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.shared_future.has_value"></a><a href="index.html#futures.reference.shared_future.has_value" title="Member function has_value()"> Member
+ function <code class="computeroutput"><span class="identifier">has_value</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">bool</span> <span class="identifier">has_value</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Checks to see if the asynchronous result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is set with a value rather than an exception.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, that result is ready for
+ retrieval, and the result is a stored value, <code class="computeroutput"><span class="keyword">false</span></code>
+ otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.shared_future.has_exception"></a><a href="index.html#futures.reference.shared_future.has_exception" title="Member function has_exception()"> Member
+ function <code class="computeroutput"><span class="identifier">has_exception</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">bool</span> <span class="identifier">has_exception</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Checks to see if the asynchronous result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is set with an exception rather than a value.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is associated with an asynchronous result, that result is ready for
+ retrieval, and the result is a stored exception, <code class="computeroutput"><span class="keyword">false</span></code>
+ otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.shared_future.get_state"></a><a href="index.html#futures.reference.shared_future.get_state" title="Member function get_state()"> Member
+ function <code class="computeroutput"><span class="identifier">get_state</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">future_state</span><span class="special">::</span><span class="identifier">state</span> <span class="identifier">get_state</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Determine the state of the asynchronous result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>,
+ if any.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ jss::future_state::uninitialized
+ if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ is not associated with an asynchronous result. jss::future_state::ready if the asynchronous
+ result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is ready for retrieval, jss::future_state::waiting otherwise.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="futures.reference.promise"></a><a href="index.html#futures.reference.promise" title="promise class template"> <code class="computeroutput"><span class="identifier">promise</span></code>
+ class template</a></h3></div></div></div>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">R</span><span class="special">&gt;</span>
+<span class="keyword">class</span> <span class="identifier">promise</span>
+<span class="special">{</span>
+ <span class="identifier">promise</span><span class="special">(</span><span class="identifier">promise</span> <span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);//</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span>
+ <span class="identifier">promise</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">promise</span> <span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">);//</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span>
+<span class="keyword">public</span><span class="special">:</span>
+ <span class="comment">// template &lt;class Allocator&gt; explicit promise(Allocator a);
+</span>
+ <span class="identifier">promise</span><span class="special">();</span>
+ <span class="special">~</span><span class="identifier">promise</span><span class="special">();</span>
+
+ <span class="comment">// Move support
+</span> <span class="identifier">promise</span><span class="special">(</span><span class="identifier">promise</span> <span class="special">&amp;&amp;</span> <span class="identifier">rhs</span><span class="special">);</span>
+ <span class="identifier">promise</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">promise</span><span class="special">&amp;&amp;</span> <span class="identifier">rhs</span><span class="special">);</span>
+
+ <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">promise</span><span class="special">&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+ <span class="comment">// Result retrieval
+</span> <span class="identifier">unique_future</span><span class="special">&lt;</span><span class="identifier">R</span><span class="special">&gt;</span> <span class="identifier">get_future</span><span class="special">();</span>
+
+ <span class="comment">// Set the value
+</span> <span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">(</span><span class="identifier">R</span><span class="special">&amp;</span> <span class="identifier">r</span><span class="special">);</span>
+ <span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">(</span><span class="identifier">R</span><span class="special">&amp;&amp;</span> <span class="identifier">r</span><span class="special">);</span>
+ <span class="keyword">void</span> <span class="identifier">set_exception</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">exception_ptr</span> <span class="identifier">e</span><span class="special">);</span>
+
+ <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F</span><span class="special">&gt;</span>
+ <span class="keyword">void</span> <span class="identifier">set_wait_callback</span><span class="special">(</span><span class="identifier">F</span> <span class="identifier">f</span><span class="special">);</span>
+<span class="special">};</span>
+</pre>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.promise.default_constructor"></a><a href="index.html#futures.reference.promise.default_constructor" title="Default Constructor"> Default
+ Constructor</a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">promise</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Constructs a new jss::promise with no associated
+ result.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.promise.move_constructor"></a> Move Constructor</h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">promise</span><span class="special">(</span><span class="identifier">promise</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Constructs a new jss::promise, and transfers ownership
+ of the result associated with <code class="computeroutput"><span class="identifier">other</span></code>
+ to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>,
+ leaving <code class="computeroutput"><span class="identifier">other</span></code> with
+ no associated result.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ If the compiler does not support rvalue-references, this is implemented
+ using the boost.thread move emulation.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.promise.move_assignment"></a><a href="index.html#futures.reference.promise.move_assignment" title="Move Assignment Operator"> Move Assignment
+ Operator</a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">promise</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">promise</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Transfers ownership of the result associated with <code class="computeroutput"><span class="identifier">other</span></code>
+ to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>,
+ leaving <code class="computeroutput"><span class="identifier">other</span></code> with
+ no associated result. If there was already a result associated with
+ <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>,
+ and that result was not <span class="emphasis"><em>ready</em></span>, sets any futures
+ associated with that result to <span class="emphasis"><em>ready</em></span> with a <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">broken_promise</span></code> exception as the result.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ If the compiler does not support rvalue-references, this is implemented
+ using the boost.thread move emulation.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.promise.destructor"></a> Destructor</h4></div></div></div>
+<pre class="programlisting">
+<span class="special">~</span><span class="identifier">promise</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Destroys <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+ If there was a result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>, and that result is not <span class="emphasis"><em>ready</em></span>,
+ sets any futures associated with that task to <span class="emphasis"><em>ready</em></span>
+ with a <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">broken_promise</span></code> exception as the result.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.promise.get_future"></a><a href="index.html#futures.reference.promise.get_future" title="Member Function get_future()"> Member Function
+ <code class="computeroutput"><span class="identifier">get_future</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">unique_future</span><span class="special">&lt;</span><span class="identifier">R</span><span class="special">&gt;</span> <span class="identifier">get_future</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ was not associated with a result, allocate storage for a new asynchronous
+ result and associate it with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. Returns a jss::unique_future associated with
+ the result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_already_retrieved</span></code> if the future
+ associated with the task has already been retrieved. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code> if any memory necessary
+ could not be allocated.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.promise.set_value"></a><a href="index.html#futures.reference.promise.set_value" title="Member Function set_value()"> Member Function
+ <code class="computeroutput"><span class="identifier">set_value</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">(</span><span class="identifier">R</span><span class="special">&amp;&amp;</span> <span class="identifier">r</span><span class="special">);</span>
+<span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">R</span><span class="special">&amp;</span> <span class="identifier">r</span><span class="special">);</span>
+<span class="keyword">void</span> <span class="identifier">promise</span><span class="special">&lt;</span><span class="identifier">R</span><span class="special">&amp;&gt;::</span><span class="identifier">set_value</span><span class="special">(</span><span class="identifier">R</span><span class="special">&amp;</span> <span class="identifier">r</span><span class="special">);</span>
+<span class="keyword">void</span> <span class="identifier">promise</span><span class="special">&lt;</span><span class="keyword">void</span><span class="special">&gt;::</span><span class="identifier">set_value</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ was not associated with a result, allocate storage for a new asynchronous
+ result and associate it with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. Store the value <code class="computeroutput"><span class="identifier">r</span></code> in the asynchronous result associated
+ with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+ Any threads blocked waiting for the asynchronous result are woken.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ All futures waiting on the asynchronous result are <span class="emphasis"><em>ready</em></span>
+ and jss::unique_future<R>::has_value()
+ or jss::shared_future<R>::has_value()
+ for those futures shall return <code class="computeroutput"><span class="keyword">true</span></code>.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">promise_already_satisfied</span></code> if the
+ result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is already <span class="emphasis"><em>ready</em></span>.
+ <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code> if the memory required
+ for storage of the result cannot be allocated. Any exception thrown
+ by the copy or move-constructor of <code class="computeroutput"><span class="identifier">R</span></code>.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.promise.set_exception"></a><a href="index.html#futures.reference.promise.set_exception" title="Member Function set_exception()"> Member Function
+ <code class="computeroutput"><span class="identifier">set_exception</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">void</span> <span class="identifier">set_exception</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">exception_ptr</span> <span class="identifier">e</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ was not associated with a result, allocate storage for a new asynchronous
+ result and associate it with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. Store the exception <code class="computeroutput"><span class="identifier">e</span></code> in the asynchronous result associated
+ with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+ Any threads blocked waiting for the asynchronous result are woken.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ All futures waiting on the asynchronous result are <span class="emphasis"><em>ready</em></span>
+ and jss::unique_future<R>::has_exception()
+ or jss::shared_future<R>::has_exception()
+ for those futures shall return <code class="computeroutput"><span class="keyword">true</span></code>.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">promise_already_satisfied</span></code> if the
+ result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is already <span class="emphasis"><em>ready</em></span>.
+ <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code> if the memory required
+ for storage of the result cannot be allocated.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.promise.set_wait_callback"></a><a href="index.html#futures.reference.promise.set_wait_callback" title="Member Function set_wait_callback()"> Member
+ Function <code class="computeroutput"><span class="identifier">set_wait_callback</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F</span><span class="special">&gt;</span>
+<span class="keyword">void</span> <span class="identifier">set_wait_callback</span><span class="special">(</span><span class="identifier">F</span> <span class="identifier">f</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Preconditions:</span></dt>
+<dd><p>
+ The expression <code class="computeroutput"><span class="identifier">f</span><span class="special">(</span><span class="identifier">t</span><span class="special">)</span></code>
+ where <code class="computeroutput"><span class="identifier">t</span></code> is a lvalue
+ of type jss::packaged_task shall be well-formed.
+ Invoking a copy of <code class="computeroutput"><span class="identifier">f</span></code>
+ shall have the same effect as invoking <code class="computeroutput"><span class="identifier">f</span></code>
+ </p></dd>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Store a copy of <code class="computeroutput"><span class="identifier">f</span></code> with
+ the asynchronous result associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> as a <span class="emphasis"><em>wait callback</em></span>.
+ This will replace any existing wait callback store alongside that result.
+ If a thread subsequently calls one of the wait functions on a jss::unique_future
+ or jss::shared_future
+ associated with this result, and the result is not <span class="emphasis"><em>ready</em></span>,
+ <code class="computeroutput"><span class="identifier">f</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)</span></code>
+ shall be invoked.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code> if memory cannot be allocated
+ for the required storage.
+ </p></dd>
+</dl>
+</div>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="futures.reference.packaged_task"></a><a href="index.html#futures.reference.packaged_task" title="packaged_task class template"> <code class="computeroutput"><span class="identifier">packaged_task</span></code>
+ class template</a></h3></div></div></div>
+<pre class="programlisting">
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">R</span><span class="special">&gt;</span>
+<span class="keyword">class</span> <span class="identifier">packaged_task</span>
+<span class="special">{</span>
+ <span class="identifier">packaged_task</span><span class="special">(</span><span class="identifier">packaged_task</span><span class="special">&amp;);//</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span>
+ <span class="identifier">packaged_task</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">packaged_task</span><span class="special">&amp;);//</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span>
+
+<span class="keyword">public</span><span class="special">:</span>
+ <span class="comment">// construction and destruction
+</span> <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">&gt;</span>
+ <span class="keyword">explicit</span> <span class="identifier">packaged_task</span><span class="special">(</span><span class="identifier">F</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">f</span><span class="special">);</span>
+
+ <span class="keyword">explicit</span> <span class="identifier">packaged_task</span><span class="special">(</span><span class="identifier">R</span><span class="special">(*</span><span class="identifier">f</span><span class="special">)());</span>
+
+ <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">&gt;</span>
+ <span class="keyword">explicit</span> <span class="identifier">packaged_task</span><span class="special">(</span><span class="identifier">F</span><span class="special">&amp;&amp;</span> <span class="identifier">f</span><span class="special">);</span>
+
+ <span class="comment">// template &lt;class F, class Allocator&gt;
+</span> <span class="comment">// explicit packaged_task(F const&amp; f, Allocator a);
+</span> <span class="comment">// template &lt;class F, class Allocator&gt;
+</span> <span class="comment">// explicit packaged_task(F&amp;&amp; f, Allocator a);
+</span>
+ <span class="special">~</span><span class="identifier">packaged_task</span><span class="special">()</span>
+ <span class="special">{}</span>
+
+ <span class="comment">// move support
+</span> <span class="identifier">packaged_task</span><span class="special">(</span><span class="identifier">packaged_task</span><span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+ <span class="identifier">packaged_task</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">packaged_task</span><span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+
+ <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">packaged_task</span><span class="special">&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+ <span class="comment">// result retrieval
+</span> <span class="identifier">unique_future</span><span class="special">&lt;</span><span class="identifier">R</span><span class="special">&gt;</span> <span class="identifier">get_future</span><span class="special">();</span>
+
+ <span class="comment">// execution
+</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()();</span>
+
+ <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F</span><span class="special">&gt;</span>
+ <span class="keyword">void</span> <span class="identifier">set_wait_callback</span><span class="special">(</span><span class="identifier">F</span> <span class="identifier">f</span><span class="special">);</span>
+<span class="special">};</span>
+</pre>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.packaged_task.task_constructor"></a><a href="index.html#futures.reference.packaged_task.task_constructor" title="Task Constructor">
+ Task Constructor</a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F</span><span class="special">&gt;</span>
+<span class="identifier">packaged_task</span><span class="special">(</span><span class="identifier">F</span> <span class="keyword">const</span> <span class="special">&amp;</span><span class="identifier">f</span><span class="special">);</span>
+
+<span class="identifier">packaged_task</span><span class="special">(</span><span class="identifier">R</span><span class="special">(*</span><span class="identifier">f</span><span class="special">)());</span>
+
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F</span><span class="special">&gt;</span>
+<span class="identifier">packaged_task</span><span class="special">(</span><span class="identifier">F</span><span class="special">&amp;&amp;</span><span class="identifier">f</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Preconditions:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">f</span><span class="special">()</span></code>
+ is a valid expression with a return type convertible to <code class="computeroutput"><span class="identifier">R</span></code>. Invoking a copy of <code class="computeroutput"><span class="identifier">f</span></code> shall behave the same as invoking
+ <code class="computeroutput"><span class="identifier">f</span></code>.
+ </p></dd>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Constructs a new jss::packaged_task with a copy
+ of <code class="computeroutput"><span class="identifier">f</span></code> stored as the
+ associated task.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Any exceptions thrown by the copy (or move) constructor of <code class="computeroutput"><span class="identifier">f</span></code>. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>
+ if memory for the internal data structures could not be allocated.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.packaged_task.move_constructor"></a><a href="index.html#futures.reference.packaged_task.move_constructor" title="Move Constructor">
+ Move Constructor</a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">packaged_task</span><span class="special">(</span><span class="identifier">packaged_task</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Constructs a new jss::packaged_task, and transfers
+ ownership of the task associated with <code class="computeroutput"><span class="identifier">other</span></code>
+ to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>,
+ leaving <code class="computeroutput"><span class="identifier">other</span></code> with
+ no associated task.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ If the compiler does not support rvalue-references, this is implemented
+ using the boost.thread move emulation.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.packaged_task.move_assignment"></a><a href="index.html#futures.reference.packaged_task.move_assignment" title="Move Assignment Operator"> Move
+ Assignment Operator</a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">packaged_task</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">packaged_task</span> <span class="special">&amp;&amp;</span> <span class="identifier">other</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Transfers ownership of the task associated with <code class="computeroutput"><span class="identifier">other</span></code>
+ to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>,
+ leaving <code class="computeroutput"><span class="identifier">other</span></code> with
+ no associated task. If there was already a task associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>,
+ and that task has not been invoked, sets any futures associated with
+ that task to <span class="emphasis"><em>ready</em></span> with a <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">broken_promise</span></code>
+ exception as the result.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ If the compiler does not support rvalue-references, this is implemented
+ using the boost.thread move emulation.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.packaged_task.destructor"></a> Destructor</h4></div></div></div>
+<pre class="programlisting">
+<span class="special">~</span><span class="identifier">packaged_task</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Destroys <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+ If there was a task associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>, and that task has not been invoked,
+ sets any futures associated with that task to <span class="emphasis"><em>ready</em></span>
+ with a <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">broken_promise</span></code> exception as the result.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Nothing.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.packaged_task.get_future"></a><a href="index.html#futures.reference.packaged_task.get_future" title="Member Function get_future()"> Member
+ Function <code class="computeroutput"><span class="identifier">get_future</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">unique_future</span><span class="special">&lt;</span><span class="identifier">R</span><span class="special">&gt;</span> <span class="identifier">get_future</span><span class="special">();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Returns a jss::unique_future associated with
+ the result of the task associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">task_moved</span></code> if ownership of the task
+ associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ has been moved to another instance of jss::packaged_task. <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">future_already_retrieved</span></code> if the future
+ associated with the task has already been retrieved.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.packaged_task.call_operator"></a><a href="index.html#futures.reference.packaged_task.call_operator" title="Member Function operator()()"> Member
+ Function <code class="computeroutput"><span class="keyword">operator</span><span class="special">()()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()();</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Invoke the task associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> and store the result in the corresponding
+ future. If the task returns normally, the return value is stored as
+ the asynchronous result, otherwise the exception thrown is stored.
+ Any threads blocked waiting for the asynchronous result associated
+ with this task are woken.
+ </p></dd>
+<dt><span class="term">Postconditions:</span></dt>
+<dd><p>
+ All futures waiting on the asynchronous result are <span class="emphasis"><em>ready</em></span>
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">task_moved</span></code> if ownership of the task
+ associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ has been moved to another instance of jss::packaged_task. <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">task_already_started</span></code> if the task
+ has already been invoked.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="futures.reference.packaged_task.set_wait_callback"></a><a href="index.html#futures.reference.packaged_task.set_wait_callback" title="Member Function set_wait_callback()">
+ Member Function <code class="computeroutput"><span class="identifier">set_wait_callback</span><span class="special">()</span></code></a></h4></div></div></div>
+<pre class="programlisting">
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F</span><span class="special">&gt;</span>
+<span class="keyword">void</span> <span class="identifier">set_wait_callback</span><span class="special">(</span><span class="identifier">F</span> <span class="identifier">f</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Preconditions:</span></dt>
+<dd><p>
+ The expression <code class="computeroutput"><span class="identifier">f</span><span class="special">(</span><span class="identifier">t</span><span class="special">)</span></code>
+ where <code class="computeroutput"><span class="identifier">t</span></code> is a lvalue
+ of type jss::packaged_task shall be well-formed.
+ Invoking a copy of <code class="computeroutput"><span class="identifier">f</span></code>
+ shall have the same effect as invoking <code class="computeroutput"><span class="identifier">f</span></code>
+ </p></dd>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Store a copy of <code class="computeroutput"><span class="identifier">f</span></code> with
+ the task associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> as a <span class="emphasis"><em>wait callback</em></span>.
+ This will replace any existing wait callback store alongside that task.
+ If a thread subsequently calls one of the wait functions on a jss::unique_future
+ or jss::shared_future
+ associated with this task, and the result of the task is not <span class="emphasis"><em>ready</em></span>,
+ <code class="computeroutput"><span class="identifier">f</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)</span></code>
+ shall be invoked.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">jss</span><span class="special">::</span><span class="identifier">task_moved</span></code> if ownership of the task
+ associated with <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+ has been moved to another instance of jss::packaged_task.
+ </p></dd>
+</dl>
+</div>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="futures.reference.wait_for_any"></a><a href="index.html#futures.reference.wait_for_any" title="Non-member function wait_for_any()"> Non-member function
+ <code class="computeroutput"><span class="identifier">wait_for_any</span><span class="special">()</span></code></a></h3></div></div></div>
+<pre class="programlisting">
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Iterator</span><span class="special">&gt;</span>
+<span class="identifier">Iterator</span> <span class="identifier">wait_for_any</span><span class="special">(</span><span class="identifier">Iterator</span> <span class="identifier">begin</span><span class="special">,</span><span class="identifier">Iterator</span> <span class="identifier">end</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F1</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F2</span><span class="special">&gt;</span>
+<span class="keyword">unsigned</span> <span class="identifier">wait_for_any</span><span class="special">(</span><span class="identifier">F1</span><span class="special">&amp;</span> <span class="identifier">f1</span><span class="special">,</span><span class="identifier">F2</span><span class="special">&amp;</span> <span class="identifier">f2</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F1</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F2</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F3</span><span class="special">&gt;</span>
+<span class="keyword">unsigned</span> <span class="identifier">wait_for_any</span><span class="special">(</span><span class="identifier">F1</span><span class="special">&amp;</span> <span class="identifier">f1</span><span class="special">,</span><span class="identifier">F2</span><span class="special">&amp;</span> <span class="identifier">f2</span><span class="special">,</span><span class="identifier">F3</span><span class="special">&amp;</span> <span class="identifier">f3</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F1</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F2</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F3</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F4</span><span class="special">&gt;</span>
+<span class="keyword">unsigned</span> <span class="identifier">wait_for_any</span><span class="special">(</span><span class="identifier">F1</span><span class="special">&amp;</span> <span class="identifier">f1</span><span class="special">,</span><span class="identifier">F2</span><span class="special">&amp;</span> <span class="identifier">f2</span><span class="special">,</span><span class="identifier">F3</span><span class="special">&amp;</span> <span class="identifier">f3</span><span class="special">,</span><span class="identifier">F4</span><span class="special">&amp;</span> <span class="identifier">f4</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F1</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F2</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F3</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F4</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F5</span><span class="special">&gt;</span>
+<span class="keyword">unsigned</span> <span class="identifier">wait_for_any</span><span class="special">(</span><span class="identifier">F1</span><span class="special">&amp;</span> <span class="identifier">f1</span><span class="special">,</span><span class="identifier">F2</span><span class="special">&amp;</span> <span class="identifier">f2</span><span class="special">,</span><span class="identifier">F3</span><span class="special">&amp;</span> <span class="identifier">f3</span><span class="special">,</span><span class="identifier">F4</span><span class="special">&amp;</span> <span class="identifier">f4</span><span class="special">,</span><span class="identifier">F5</span><span class="special">&amp;</span> <span class="identifier">f5</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Preconditions:</span></dt>
+<dd><p>
+ The types <code class="computeroutput"><span class="identifier">Fn</span></code> shall be
+ specializations of jss::unique_future or jss::shared_future, and <code class="computeroutput"><span class="identifier">Iterator</span></code> shall be a forward iterator
+ with a <code class="computeroutput"><span class="identifier">value_type</span></code> which
+ is a specialization of jss::unique_future or jss::shared_future.
+ </p></dd>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Waits until at least one of the specified futures is <span class="emphasis"><em>ready</em></span>.
+ </p></dd>
+<dt><span class="term">Returns:</span></dt>
+<dd><p>
+ The range-based overload returns an <code class="computeroutput"><span class="identifier">Iterator</span></code>
+ identifying the first future in the range that was detected as <span class="emphasis"><em>ready</em></span>.
+ The remaining overloads return the zero-based index of the first future
+ that was detected as <span class="emphasis"><em>ready</em></span> (first parameter =&gt;
+ 0, second parameter =&gt; 1, etc.).
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">thread_interrupted</span></code> if the current thread
+ is interrupted. Any exception thrown by the <span class="emphasis"><em>wait callback</em></span>
+ associated with any of the futures being waited for. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>
+ if memory could not be allocated for the internal wait structures.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">wait_for_any</span><span class="special">()</span></code>
+ is an <span class="emphasis"><em>interruption point</em></span>.
+ </p></dd>
+</dl>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="futures.reference.wait_for_all"></a><a href="index.html#futures.reference.wait_for_all" title="Non-member function wait_for_all()"> Non-member function
+ <code class="computeroutput"><span class="identifier">wait_for_all</span><span class="special">()</span></code></a></h3></div></div></div>
+<pre class="programlisting">
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Iterator</span><span class="special">&gt;</span>
+<span class="keyword">void</span> <span class="identifier">wait_for_all</span><span class="special">(</span><span class="identifier">Iterator</span> <span class="identifier">begin</span><span class="special">,</span><span class="identifier">Iterator</span> <span class="identifier">end</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F1</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F2</span><span class="special">&gt;</span>
+<span class="keyword">void</span> <span class="identifier">wait_for_all</span><span class="special">(</span><span class="identifier">F1</span><span class="special">&amp;</span> <span class="identifier">f1</span><span class="special">,</span><span class="identifier">F2</span><span class="special">&amp;</span> <span class="identifier">f2</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F1</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F2</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F3</span><span class="special">&gt;</span>
+<span class="keyword">void</span> <span class="identifier">wait_for_all</span><span class="special">(</span><span class="identifier">F1</span><span class="special">&amp;</span> <span class="identifier">f1</span><span class="special">,</span><span class="identifier">F2</span><span class="special">&amp;</span> <span class="identifier">f2</span><span class="special">,</span><span class="identifier">F3</span><span class="special">&amp;</span> <span class="identifier">f3</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F1</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F2</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F3</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F4</span><span class="special">&gt;</span>
+<span class="keyword">void</span> <span class="identifier">wait_for_all</span><span class="special">(</span><span class="identifier">F1</span><span class="special">&amp;</span> <span class="identifier">f1</span><span class="special">,</span><span class="identifier">F2</span><span class="special">&amp;</span> <span class="identifier">f2</span><span class="special">,</span><span class="identifier">F3</span><span class="special">&amp;</span> <span class="identifier">f3</span><span class="special">,</span><span class="identifier">F4</span><span class="special">&amp;</span> <span class="identifier">f4</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">F1</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F2</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F3</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F4</span><span class="special">,</span><span class="keyword">typename</span> <span class="identifier">F5</span><span class="special">&gt;</span>
+<span class="keyword">void</span> <span class="identifier">wait_for_all</span><span class="special">(</span><span class="identifier">F1</span><span class="special">&amp;</span> <span class="identifier">f1</span><span class="special">,</span><span class="identifier">F2</span><span class="special">&amp;</span> <span class="identifier">f2</span><span class="special">,</span><span class="identifier">F3</span><span class="special">&amp;</span> <span class="identifier">f3</span><span class="special">,</span><span class="identifier">F4</span><span class="special">&amp;</span> <span class="identifier">f4</span><span class="special">,</span><span class="identifier">F5</span><span class="special">&amp;</span> <span class="identifier">f5</span><span class="special">);</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">Preconditions:</span></dt>
+<dd><p>
+ The types <code class="computeroutput"><span class="identifier">Fn</span></code> shall be
+ specializations of jss::unique_future or jss::shared_future, and <code class="computeroutput"><span class="identifier">Iterator</span></code> shall be a forward iterator
+ with a <code class="computeroutput"><span class="identifier">value_type</span></code> which
+ is a specialization of jss::unique_future or jss::shared_future.
+ </p></dd>
+<dt><span class="term">Effects:</span></dt>
+<dd><p>
+ Waits until all of the specified futures are <span class="emphasis"><em>ready</em></span>.
+ </p></dd>
+<dt><span class="term">Throws:</span></dt>
+<dd><p>
+ Any exceptions thrown by a call to <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code> on the specified futures.
+ </p></dd>
+<dt><span class="term">Notes:</span></dt>
+<dd><p>
+ <code class="computeroutput"><span class="identifier">wait_for_all</span><span class="special">()</span></code>
+ is an <span class="emphasis"><em>interruption point</em></span>.
+ </p></dd>
+</dl>
+</div>
+</div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"><p><small>Last revised: May 30, 2008 at 09:30:07 GMT</small></p></td>
+<td align="right"><div class="copyright-footer"></div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav"></div>
+</body>
+</html>

Added: sandbox/async/boost/futures/test_futures.cpp
==============================================================================
--- (empty file)
+++ sandbox/async/boost/futures/test_futures.cpp 2009-10-13 03:02:10 EDT (Tue, 13 Oct 2009)
@@ -0,0 +1,1214 @@
+// (C) Copyright 2008 Anthony Williams
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "boost/thread/thread.hpp"
+#include "boost/thread/mutex.hpp"
+#include "boost/thread/condition.hpp"
+#include "future.hpp"
+#include <assert.h>
+#include <utility>
+#include <memory>
+#include <string>
+
+#ifdef BOOST_HAS_RVALUE_REFS
+ template<typename T>
+ typename boost::remove_reference<T>::type&& move(T&& t)
+ {
+ return t;
+ }
+#else
+ template<typename T>
+ boost::detail::thread_move_t<T> move(T& t)
+ {
+ return boost::move(t);
+ }
+#endif
+
+struct X
+{
+private:
+
+ X(X& other);
+
+public:
+
+ int i;
+
+ X():
+ i(42)
+ {}
+#ifdef BOOST_HAS_RVALUE_REFS
+ X(X&& other):
+ i(other.i)
+ {
+ other.i=0;
+ }
+#else
+ X(boost::detail::thread_move_t<X> other):
+ i(other->i)
+ {
+ other->i=0;
+ }
+ operator boost::detail::thread_move_t<X>()
+ {
+ return boost::detail::thread_move_t<X>(*this);
+ }
+#endif
+ ~X()
+ {}
+};
+
+int make_int()
+{
+ return 42;
+}
+
+int throw_runtime_error()
+{
+ throw std::runtime_error("42");
+}
+
+void set_promise_thread(jss::promise<int>* p)
+{
+ p->set_value(42);
+}
+
+struct my_exception
+{};
+
+void set_promise_exception_thread(jss::promise<int>* p)
+{
+ p->set_exception(boost::copy_exception(my_exception()));
+}
+
+
+void test_store_value_from_thread()
+{
+ jss::promise<int> pi2;
+ jss::unique_future<int> fi2=pi2.get_future();
+ boost::thread(set_promise_thread,&pi2);
+ int j=fi2.get();
+ assert(j==42);
+ assert(fi2.is_ready());
+ assert(fi2.has_value());
+ assert(!fi2.has_exception());
+ assert(fi2.get_state()==jss::future_state::ready);
+}
+
+
+void test_store_exception()
+{
+ jss::promise<int> pi3;
+ jss::unique_future<int> fi3=pi3.get_future();
+ boost::thread(set_promise_exception_thread,&pi3);
+ try
+ {
+ fi3.get();
+ assert(false);
+ }
+ catch(my_exception)
+ {
+ assert(true);
+ }
+
+ assert(fi3.is_ready());
+ assert(!fi3.has_value());
+ assert(fi3.has_exception());
+ assert(fi3.get_state()==jss::future_state::ready);
+}
+
+void test_initial_state()
+{
+ jss::unique_future<int> fi;
+ assert(!fi.is_ready());
+ assert(!fi.has_value());
+ assert(!fi.has_exception());
+ assert(fi.get_state()==jss::future_state::uninitialized);
+ int i;
+ try
+ {
+ i=fi.get();
+ assert(false);
+ }
+ catch(jss::future_uninitialized)
+ {
+ assert(true);
+ }
+}
+
+void test_waiting_future()
+{
+ jss::promise<int> pi;
+ jss::unique_future<int> fi;
+ fi=pi.get_future();
+
+ int i=0;
+ assert(!fi.is_ready());
+ assert(!fi.has_value());
+ assert(!fi.has_exception());
+ assert(fi.get_state()==jss::future_state::waiting);
+ assert(i==0);
+}
+
+void test_cannot_get_future_twice()
+{
+ jss::promise<int> pi;
+ pi.get_future();
+
+ try
+ {
+ pi.get_future();
+ assert(false);
+ }
+ catch(jss::future_already_retrieved&)
+ {
+ assert(true);
+ }
+}
+
+void test_set_value_updates_future_state()
+{
+ jss::promise<int> pi;
+ jss::unique_future<int> fi;
+ fi=pi.get_future();
+
+ pi.set_value(42);
+
+ assert(fi.is_ready());
+ assert(fi.has_value());
+ assert(!fi.has_exception());
+ assert(fi.get_state()==jss::future_state::ready);
+}
+
+void test_set_value_can_be_retrieved()
+{
+ jss::promise<int> pi;
+ jss::unique_future<int> fi;
+ fi=pi.get_future();
+
+ pi.set_value(42);
+
+ int i=0;
+ assert(i=fi.get());
+ assert(i==42);
+ assert(fi.is_ready());
+ assert(fi.has_value());
+ assert(!fi.has_exception());
+ assert(fi.get_state()==jss::future_state::ready);
+}
+
+void test_set_value_can_be_moved()
+{
+// jss::promise<int> pi;
+// jss::unique_future<int> fi;
+// fi=pi.get_future();
+
+// pi.set_value(42);
+
+// int i=0;
+// assert(i=fi.get());
+// assert(i==42);
+// assert(fi.is_ready());
+// assert(fi.has_value());
+// assert(!fi.has_exception());
+// assert(fi.get_state()==jss::future_state::ready);
+}
+
+void test_future_from_packaged_task_is_waiting()
+{
+ jss::packaged_task<int> pt(make_int);
+ jss::unique_future<int> fi=pt.get_future();
+ int i=0;
+ assert(!fi.is_ready());
+ assert(!fi.has_value());
+ assert(!fi.has_exception());
+ assert(fi.get_state()==jss::future_state::waiting);
+ assert(i==0);
+}
+
+void test_invoking_a_packaged_task_populates_future()
+{
+ jss::packaged_task<int> pt(make_int);
+ jss::unique_future<int> fi=pt.get_future();
+
+ pt();
+
+ int i=0;
+ assert(fi.is_ready());
+ assert(fi.has_value());
+ assert(!fi.has_exception());
+ assert(fi.get_state()==jss::future_state::ready);
+ assert(i=fi.get());
+ assert(i==42);
+}
+
+void test_invoking_a_packaged_task_twice_throws()
+{
+ jss::packaged_task<int> pt(make_int);
+
+ pt();
+ try
+ {
+ pt();
+ assert(false);
+ }
+ catch(jss::task_already_started)
+ {
+ assert(true);
+ }
+}
+
+
+void test_cannot_get_future_twice_from_task()
+{
+ jss::packaged_task<int> pt(make_int);
+ pt.get_future();
+ try
+ {
+ pt.get_future();
+ assert(false);
+ }
+ catch(jss::future_already_retrieved)
+ {
+ assert(true);
+ }
+}
+
+void test_task_stores_exception_if_function_throws()
+{
+ jss::packaged_task<int> pt(throw_runtime_error);
+ jss::unique_future<int> fi=pt.get_future();
+
+ pt();
+
+ int i=0;
+ assert(fi.is_ready());
+ assert(!fi.has_value());
+ assert(fi.has_exception());
+ assert(fi.get_state()==jss::future_state::ready);
+ try
+ {
+ fi.get();
+ assert(false);
+ }
+ catch(std::exception&)
+ {
+ assert(true);
+ }
+ catch(...)
+ {
+ assert(!"Unknown exception thrown");
+ }
+
+}
+
+void test_void_promise()
+{
+ jss::promise<void> p;
+ jss::unique_future<void> f=p.get_future();
+ p.set_value();
+ assert(f.is_ready());
+ assert(f.has_value());
+ assert(!f.has_exception());
+ assert(f.get_state()==jss::future_state::ready);
+ f.get();
+}
+
+void test_reference_promise()
+{
+ jss::promise<int&> p;
+ jss::unique_future<int&> f=p.get_future();
+ int i=42;
+ p.set_value(i);
+ assert(f.is_ready());
+ assert(f.has_value());
+ assert(!f.has_exception());
+ assert(f.get_state()==jss::future_state::ready);
+ assert(&f.get()==&i);
+}
+
+void do_nothing()
+{}
+
+void test_task_returning_void()
+{
+ jss::packaged_task<void> pt(do_nothing);
+ jss::unique_future<void> fi=pt.get_future();
+
+ pt();
+
+ assert(fi.is_ready());
+ assert(fi.has_value());
+ assert(!fi.has_exception());
+ assert(fi.get_state()==jss::future_state::ready);
+}
+
+int global_ref_target=0;
+
+int& return_ref()
+{
+ return global_ref_target;
+}
+
+void test_task_returning_reference()
+{
+ jss::packaged_task<int&> pt(return_ref);
+ jss::unique_future<int&> fi=pt.get_future();
+
+ pt();
+
+ assert(fi.is_ready());
+ assert(fi.has_value());
+ assert(!fi.has_exception());
+ assert(fi.get_state()==jss::future_state::ready);
+ int& i=fi.get();
+ assert(&i==&global_ref_target);
+}
+
+void test_shared_future()
+{
+ jss::packaged_task<int> pt(make_int);
+ jss::unique_future<int> fi=pt.get_future();
+
+ jss::shared_future<int> sf(::move(fi));
+ assert(fi.get_state()==jss::future_state::uninitialized);
+
+ pt();
+
+ int i=0;
+ assert(sf.is_ready());
+ assert(sf.has_value());
+ assert(!sf.has_exception());
+ assert(sf.get_state()==jss::future_state::ready);
+ assert(i=sf.get());
+ assert(i==42);
+}
+
+void test_copies_of_shared_future_become_ready_together()
+{
+ jss::packaged_task<int> pt(make_int);
+ jss::unique_future<int> fi=pt.get_future();
+
+ jss::shared_future<int> sf(::move(fi));
+ jss::shared_future<int> sf2(sf);
+ jss::shared_future<int> sf3;
+ sf3=sf;
+ assert(sf.get_state()==jss::future_state::waiting);
+ assert(sf2.get_state()==jss::future_state::waiting);
+ assert(sf3.get_state()==jss::future_state::waiting);
+
+ pt();
+
+ int i=0;
+ assert(sf.is_ready());
+ assert(sf.has_value());
+ assert(!sf.has_exception());
+ assert(sf.get_state()==jss::future_state::ready);
+ assert(i=sf.get());
+ assert(i==42);
+ i=0;
+ assert(sf2.is_ready());
+ assert(sf2.has_value());
+ assert(!sf2.has_exception());
+ assert(sf2.get_state()==jss::future_state::ready);
+ assert(i=sf2.get());
+ assert(i==42);
+ i=0;
+ assert(sf3.is_ready());
+ assert(sf3.has_value());
+ assert(!sf3.has_exception());
+ assert(sf3.get_state()==jss::future_state::ready);
+ assert(i=sf3.get());
+ assert(i==42);
+}
+
+void test_shared_future_can_be_move_assigned_from_unique_future()
+{
+ jss::packaged_task<int> pt(make_int);
+ jss::unique_future<int> fi=pt.get_future();
+
+ jss::shared_future<int> sf;
+ sf=::move(fi);
+ assert(fi.get_state()==jss::future_state::uninitialized);
+
+ int i=0;
+ assert(!sf.is_ready());
+ assert(!sf.has_value());
+ assert(!sf.has_exception());
+ assert(sf.get_state()==jss::future_state::waiting);
+}
+
+void test_shared_future_void()
+{
+ jss::packaged_task<void> pt(do_nothing);
+ jss::unique_future<void> fi=pt.get_future();
+
+ jss::shared_future<void> sf(::move(fi));
+ assert(fi.get_state()==jss::future_state::uninitialized);
+
+ pt();
+
+ assert(sf.is_ready());
+ assert(sf.has_value());
+ assert(!sf.has_exception());
+ assert(sf.get_state()==jss::future_state::ready);
+ sf.get();
+}
+
+void test_shared_future_ref()
+{
+ jss::promise<int&> p;
+ jss::shared_future<int&> f(p.get_future());
+ int i=42;
+ p.set_value(i);
+ assert(f.is_ready());
+ assert(f.has_value());
+ assert(!f.has_exception());
+ assert(f.get_state()==jss::future_state::ready);
+ assert(&f.get()==&i);
+}
+
+void test_can_get_a_second_future_from_a_moved_promise()
+{
+ jss::promise<int> pi;
+ jss::unique_future<int> fi=pi.get_future();
+
+ jss::promise<int> pi2(::move(pi));
+ jss::unique_future<int> fi2=pi.get_future();
+
+ pi2.set_value(3);
+ assert(fi.is_ready());
+ assert(!fi2.is_ready());
+ assert(fi.get()==3);
+ pi.set_value(42);
+ assert(fi2.is_ready());
+ assert(fi2.get()==42);
+}
+
+void test_can_get_a_second_future_from_a_moved_void_promise()
+{
+ jss::promise<void> pi;
+ jss::unique_future<void> fi=pi.get_future();
+
+ jss::promise<void> pi2(::move(pi));
+ jss::unique_future<void> fi2=pi.get_future();
+
+ pi2.set_value();
+ assert(fi.is_ready());
+ assert(!fi2.is_ready());
+ pi.set_value();
+ assert(fi2.is_ready());
+}
+
+void test_unique_future_for_move_only_udt()
+{
+ jss::promise<X> pt;
+ jss::unique_future<X> fi=pt.get_future();
+
+ pt.set_value(X());
+ X res(fi.get());
+ assert(res.i==42);
+}
+
+void test_unique_future_for_string()
+{
+ jss::promise<std::string> pt;
+ jss::unique_future<std::string> fi=pt.get_future();
+
+ pt.set_value(std::string("hello"));
+ std::string res(fi.get());
+ assert(res=="hello");
+
+ jss::promise<std::string> pt2;
+ fi=pt2.get_future();
+
+ std::string const s="goodbye";
+
+ pt2.set_value(s);
+ res=fi.get();
+ assert(res=="goodbye");
+
+ jss::promise<std::string> pt3;
+ fi=pt3.get_future();
+
+ std::string s2="foo";
+
+ pt3.set_value(s2);
+ res=fi.get();
+ assert(res=="foo");
+}
+
+boost::mutex callback_mutex;
+unsigned callback_called=0;
+
+void wait_callback(jss::promise<int>& pi)
+{
+ boost::lock_guard<boost::mutex> lk(callback_mutex);
+ ++callback_called;
+ try
+ {
+ pi.set_value(42);
+ }
+ catch(...)
+ {
+ }
+}
+
+void do_nothing_callback(jss::promise<int>& pi)
+{
+ boost::lock_guard<boost::mutex> lk(callback_mutex);
+ ++callback_called;
+}
+
+void test_wait_callback()
+{
+ callback_called=0;
+ jss::promise<int> pi;
+ jss::unique_future<int> fi=pi.get_future();
+ pi.set_wait_callback(wait_callback);
+ fi.wait();
+ assert(callback_called);
+ assert(fi.get()==42);
+ fi.wait();
+ fi.wait();
+ assert(callback_called==1);
+}
+
+void test_wait_callback_with_timed_wait()
+{
+ callback_called=0;
+ jss::promise<int> pi;
+ jss::unique_future<int> fi=pi.get_future();
+ pi.set_wait_callback(do_nothing_callback);
+ bool success=fi.timed_wait(boost::posix_time::milliseconds(10));
+ assert(callback_called);
+ assert(!success);
+ success=fi.timed_wait(boost::posix_time::milliseconds(10));
+ assert(!success);
+ success=fi.timed_wait(boost::posix_time::milliseconds(10));
+ assert(!success);
+ assert(callback_called==3);
+ pi.set_value(42);
+ success=fi.timed_wait(boost::posix_time::milliseconds(10));
+ assert(success);
+ assert(callback_called==3);
+ assert(fi.get()==42);
+ assert(callback_called==3);
+}
+
+
+void wait_callback_for_task(jss::packaged_task<int>& pt)
+{
+ boost::lock_guard<boost::mutex> lk(callback_mutex);
+ ++callback_called;
+ try
+ {
+ pt();
+ }
+ catch(...)
+ {
+ }
+}
+
+
+void test_wait_callback_for_packaged_task()
+{
+ callback_called=0;
+ jss::packaged_task<int> pt(make_int);
+ jss::unique_future<int> fi=pt.get_future();
+ pt.set_wait_callback(wait_callback_for_task);
+ fi.wait();
+ assert(callback_called);
+ assert(fi.get()==42);
+ fi.wait();
+ fi.wait();
+ assert(callback_called==1);
+}
+
+void test_packaged_task_can_be_moved()
+{
+ jss::packaged_task<int> pt(make_int);
+
+ jss::unique_future<int> fi=pt.get_future();
+
+ assert(!fi.is_ready());
+
+ jss::packaged_task<int> pt2=::move(pt);
+
+ assert(!fi.is_ready());
+ try
+ {
+ pt();
+ assert(!"Can invoke moved task!");
+ }
+ catch(jss::task_moved&)
+ {
+ }
+
+ assert(!fi.is_ready());
+
+ pt2();
+
+ assert(fi.is_ready());
+}
+
+void test_destroying_a_promise_stores_broken_promise()
+{
+ jss::unique_future<int> f;
+
+ {
+ jss::promise<int> p;
+ f=p.get_future();
+ }
+ assert(f.is_ready());
+ assert(f.has_exception());
+ try
+ {
+ f.get();
+ }
+ catch(jss::broken_promise&)
+ {
+ }
+}
+
+void test_destroying_a_packaged_task_stores_broken_promise()
+{
+ jss::unique_future<int> f;
+
+ {
+ jss::packaged_task<int> p(make_int);
+ f=p.get_future();
+ }
+ assert(f.is_ready());
+ assert(f.has_exception());
+ try
+ {
+ f.get();
+ }
+ catch(jss::broken_promise&)
+ {
+ }
+}
+
+int make_int_slowly()
+{
+ boost::this_thread::sleep(boost::posix_time::seconds(1));
+ return 42;
+}
+
+void test_wait_for_either_of_two_futures_1()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+
+ boost::thread(::move(pt));
+
+ unsigned const future=jss::wait_for_any(f1,f2);
+
+ assert(future==0);
+ assert(f1.is_ready());
+ assert(!f2.is_ready());
+ assert(f1.get()==42);
+}
+
+void test_wait_for_either_of_two_futures_2()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+
+ boost::thread(::move(pt2));
+
+ unsigned const future=jss::wait_for_any(f1,f2);
+
+ assert(future==1);
+ assert(!f1.is_ready());
+ assert(f2.is_ready());
+ assert(f2.get()==42);
+}
+
+void test_wait_for_either_of_three_futures_1()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+
+ boost::thread(::move(pt));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3);
+
+ assert(future==0);
+ assert(f1.is_ready());
+ assert(!f2.is_ready());
+ assert(!f3.is_ready());
+ assert(f1.get()==42);
+}
+
+void test_wait_for_either_of_three_futures_2()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+
+ boost::thread(::move(pt2));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3);
+
+ assert(future==1);
+ assert(!f1.is_ready());
+ assert(f2.is_ready());
+ assert(!f3.is_ready());
+ assert(f2.get()==42);
+}
+
+void test_wait_for_either_of_three_futures_3()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+
+ boost::thread(::move(pt3));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3);
+
+ assert(future==2);
+ assert(!f1.is_ready());
+ assert(!f2.is_ready());
+ assert(f3.is_ready());
+ assert(f3.get()==42);
+}
+
+void test_wait_for_either_of_four_futures_1()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+ jss::packaged_task<int> pt4(make_int_slowly);
+ jss::unique_future<int> f4(pt4.get_future());
+
+ boost::thread(::move(pt));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3,f4);
+
+ assert(future==0);
+ assert(f1.is_ready());
+ assert(!f2.is_ready());
+ assert(!f3.is_ready());
+ assert(!f4.is_ready());
+ assert(f1.get()==42);
+}
+
+void test_wait_for_either_of_four_futures_2()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+ jss::packaged_task<int> pt4(make_int_slowly);
+ jss::unique_future<int> f4(pt4.get_future());
+
+ boost::thread(::move(pt2));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3,f4);
+
+ assert(future==1);
+ assert(!f1.is_ready());
+ assert(f2.is_ready());
+ assert(!f3.is_ready());
+ assert(!f4.is_ready());
+ assert(f2.get()==42);
+}
+
+void test_wait_for_either_of_four_futures_3()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+ jss::packaged_task<int> pt4(make_int_slowly);
+ jss::unique_future<int> f4(pt4.get_future());
+
+ boost::thread(::move(pt3));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3,f4);
+
+ assert(future==2);
+ assert(!f1.is_ready());
+ assert(!f2.is_ready());
+ assert(f3.is_ready());
+ assert(!f4.is_ready());
+ assert(f3.get()==42);
+}
+
+void test_wait_for_either_of_four_futures_4()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+ jss::packaged_task<int> pt4(make_int_slowly);
+ jss::unique_future<int> f4(pt4.get_future());
+
+ boost::thread(::move(pt4));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3,f4);
+
+ assert(future==3);
+ assert(!f1.is_ready());
+ assert(!f2.is_ready());
+ assert(!f3.is_ready());
+ assert(f4.is_ready());
+ assert(f4.get()==42);
+}
+
+void test_wait_for_either_of_five_futures_1()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+ jss::packaged_task<int> pt4(make_int_slowly);
+ jss::unique_future<int> f4(pt4.get_future());
+ jss::packaged_task<int> pt5(make_int_slowly);
+ jss::unique_future<int> f5(pt5.get_future());
+
+ boost::thread(::move(pt));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3,f4,f5);
+
+ assert(future==0);
+ assert(f1.is_ready());
+ assert(!f2.is_ready());
+ assert(!f3.is_ready());
+ assert(!f4.is_ready());
+ assert(!f5.is_ready());
+ assert(f1.get()==42);
+}
+
+void test_wait_for_either_of_five_futures_2()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+ jss::packaged_task<int> pt4(make_int_slowly);
+ jss::unique_future<int> f4(pt4.get_future());
+ jss::packaged_task<int> pt5(make_int_slowly);
+ jss::unique_future<int> f5(pt5.get_future());
+
+ boost::thread(::move(pt2));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3,f4,f5);
+
+ assert(future==1);
+ assert(!f1.is_ready());
+ assert(f2.is_ready());
+ assert(!f3.is_ready());
+ assert(!f4.is_ready());
+ assert(!f5.is_ready());
+ assert(f2.get()==42);
+}
+void test_wait_for_either_of_five_futures_3()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+ jss::packaged_task<int> pt4(make_int_slowly);
+ jss::unique_future<int> f4(pt4.get_future());
+ jss::packaged_task<int> pt5(make_int_slowly);
+ jss::unique_future<int> f5(pt5.get_future());
+
+ boost::thread(::move(pt3));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3,f4,f5);
+
+ assert(future==2);
+ assert(!f1.is_ready());
+ assert(!f2.is_ready());
+ assert(f3.is_ready());
+ assert(!f4.is_ready());
+ assert(!f5.is_ready());
+ assert(f3.get()==42);
+}
+void test_wait_for_either_of_five_futures_4()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+ jss::packaged_task<int> pt4(make_int_slowly);
+ jss::unique_future<int> f4(pt4.get_future());
+ jss::packaged_task<int> pt5(make_int_slowly);
+ jss::unique_future<int> f5(pt5.get_future());
+
+ boost::thread(::move(pt4));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3,f4,f5);
+
+ assert(future==3);
+ assert(!f1.is_ready());
+ assert(!f2.is_ready());
+ assert(!f3.is_ready());
+ assert(f4.is_ready());
+ assert(!f5.is_ready());
+ assert(f4.get()==42);
+}
+void test_wait_for_either_of_five_futures_5()
+{
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> f1(pt.get_future());
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> f2(pt2.get_future());
+ jss::packaged_task<int> pt3(make_int_slowly);
+ jss::unique_future<int> f3(pt3.get_future());
+ jss::packaged_task<int> pt4(make_int_slowly);
+ jss::unique_future<int> f4(pt4.get_future());
+ jss::packaged_task<int> pt5(make_int_slowly);
+ jss::unique_future<int> f5(pt5.get_future());
+
+ boost::thread(::move(pt5));
+
+ unsigned const future=jss::wait_for_any(f1,f2,f3,f4,f5);
+
+ assert(future==4);
+ assert(!f1.is_ready());
+ assert(!f2.is_ready());
+ assert(!f3.is_ready());
+ assert(!f4.is_ready());
+ assert(f5.is_ready());
+ assert(f5.get()==42);
+}
+
+void test_wait_for_either_invokes_callbacks()
+{
+ callback_called=0;
+ jss::packaged_task<int> pt(make_int_slowly);
+ jss::unique_future<int> fi=pt.get_future();
+ jss::packaged_task<int> pt2(make_int_slowly);
+ jss::unique_future<int> fi2=pt2.get_future();
+ pt.set_wait_callback(wait_callback_for_task);
+
+ boost::thread(::move(pt));
+
+ jss::wait_for_any(fi,fi2);
+ assert(callback_called==1);
+ assert(fi.get()==42);
+}
+
+void test_wait_for_any_from_range()
+{
+ unsigned const count=10;
+ for(unsigned i=0;i<count;++i)
+ {
+ jss::packaged_task<int> tasks[count];
+ jss::unique_future<int> futures[count];
+ for(unsigned j=0;j<count;++j)
+ {
+ tasks[j]=jss::packaged_task<int>(make_int_slowly);
+ futures[j]=tasks[j].get_future();
+ }
+ boost::thread(::move(tasks[i]));
+
+ jss::unique_future<int>* const future=jss::wait_for_any(futures,futures+count);
+
+ assert(future==(futures+i));
+ for(unsigned j=0;j<count;++j)
+ {
+ if(j!=i)
+ {
+ assert(!futures[j].is_ready());
+ }
+ else
+ {
+ assert(futures[j].is_ready());
+ }
+ }
+ assert(futures[i].get()==42);
+ }
+}
+
+void test_wait_for_all_from_range()
+{
+ unsigned const count=10;
+ jss::unique_future<int> futures[count];
+ for(unsigned j=0;j<count;++j)
+ {
+ jss::packaged_task<int> task(make_int_slowly);
+ futures[j]=task.get_future();
+ boost::thread(::move(task));
+ }
+
+ jss::wait_for_all(futures,futures+count);
+
+ for(unsigned j=0;j<count;++j)
+ {
+ assert(futures[j].is_ready());
+ }
+}
+
+void test_wait_for_all_two_futures()
+{
+ unsigned const count=2;
+ jss::unique_future<int> futures[count];
+ for(unsigned j=0;j<count;++j)
+ {
+ jss::packaged_task<int> task(make_int_slowly);
+ futures[j]=task.get_future();
+ boost::thread(::move(task));
+ }
+
+ jss::wait_for_all(futures[0],futures[1]);
+
+ for(unsigned j=0;j<count;++j)
+ {
+ assert(futures[j].is_ready());
+ }
+}
+
+void test_wait_for_all_three_futures()
+{
+ unsigned const count=3;
+ jss::unique_future<int> futures[count];
+ for(unsigned j=0;j<count;++j)
+ {
+ jss::packaged_task<int> task(make_int_slowly);
+ futures[j]=task.get_future();
+ boost::thread(::move(task));
+ }
+
+ jss::wait_for_all(futures[0],futures[1],futures[2]);
+
+ for(unsigned j=0;j<count;++j)
+ {
+ assert(futures[j].is_ready());
+ }
+}
+
+void test_wait_for_all_four_futures()
+{
+ unsigned const count=4;
+ jss::unique_future<int> futures[count];
+ for(unsigned j=0;j<count;++j)
+ {
+ jss::packaged_task<int> task(make_int_slowly);
+ futures[j]=task.get_future();
+ boost::thread(::move(task));
+ }
+
+ jss::wait_for_all(futures[0],futures[1],futures[2],futures[3]);
+
+ for(unsigned j=0;j<count;++j)
+ {
+ assert(futures[j].is_ready());
+ }
+}
+
+void test_wait_for_all_five_futures()
+{
+ unsigned const count=5;
+ jss::unique_future<int> futures[count];
+ for(unsigned j=0;j<count;++j)
+ {
+ jss::packaged_task<int> task(make_int_slowly);
+ futures[j]=task.get_future();
+ boost::thread(::move(task));
+ }
+
+ jss::wait_for_all(futures[0],futures[1],futures[2],futures[3],futures[4]);
+
+ for(unsigned j=0;j<count;++j)
+ {
+ assert(futures[j].is_ready());
+ }
+}
+
+
+int main()
+{
+ test_initial_state();
+ test_waiting_future();
+ test_cannot_get_future_twice();
+ test_set_value_updates_future_state();
+ test_set_value_can_be_retrieved();
+ test_set_value_can_be_moved();
+ test_store_value_from_thread();
+ test_store_exception();
+ test_future_from_packaged_task_is_waiting();
+ test_invoking_a_packaged_task_populates_future();
+ test_invoking_a_packaged_task_twice_throws();
+ test_cannot_get_future_twice_from_task();
+ test_task_stores_exception_if_function_throws();
+ test_void_promise();
+ test_reference_promise();
+ test_task_returning_void();
+ test_task_returning_reference();
+ test_shared_future();
+ test_copies_of_shared_future_become_ready_together();
+ test_shared_future_can_be_move_assigned_from_unique_future();
+ test_shared_future_void();
+ test_shared_future_ref();
+ test_can_get_a_second_future_from_a_moved_promise();
+ test_can_get_a_second_future_from_a_moved_void_promise();
+ test_unique_future_for_move_only_udt();
+ test_unique_future_for_string();
+ test_wait_callback();
+ test_wait_callback_with_timed_wait();
+ test_wait_callback_for_packaged_task();
+ test_packaged_task_can_be_moved();
+ test_destroying_a_promise_stores_broken_promise();
+ test_destroying_a_packaged_task_stores_broken_promise();
+ test_wait_for_either_of_two_futures_1();
+ test_wait_for_either_of_two_futures_2();
+ test_wait_for_either_of_three_futures_1();
+ test_wait_for_either_of_three_futures_2();
+ test_wait_for_either_of_three_futures_3();
+ test_wait_for_either_of_four_futures_1();
+ test_wait_for_either_of_four_futures_2();
+ test_wait_for_either_of_four_futures_3();
+ test_wait_for_either_of_four_futures_4();
+ test_wait_for_either_of_five_futures_1();
+ test_wait_for_either_of_five_futures_2();
+ test_wait_for_either_of_five_futures_3();
+ test_wait_for_either_of_five_futures_4();
+ test_wait_for_either_of_five_futures_5();
+ test_wait_for_either_invokes_callbacks();
+ test_wait_for_any_from_range();
+ test_wait_for_all_from_range();
+ test_wait_for_all_two_futures();
+ test_wait_for_all_three_futures();
+ test_wait_for_all_four_futures();
+ test_wait_for_all_five_futures();
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk