$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r57064 - in trunk: boost boost/thread libs/thread/doc libs/thread/test
From: anthony_at_[hidden]
Date: 2009-10-22 05:33:23
Author: anthonyw
Date: 2009-10-22 05:33:21 EDT (Thu, 22 Oct 2009)
New Revision: 57064
URL: http://svn.boost.org/trac/boost/changeset/57064
Log:
Added futures to boost.thread
Added:
   trunk/boost/thread/future.hpp   (contents, props changed)
   trunk/libs/thread/doc/future_ref.qbk   (contents, props changed)
   trunk/libs/thread/doc/futures.qbk   (contents, props changed)
   trunk/libs/thread/test/test_futures.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/thread.hpp            |     3 ++-                                     
   trunk/libs/thread/doc/changes.qbk |     6 +++++-                                  
   trunk/libs/thread/doc/thread.qbk  |     1 +                                       
   trunk/libs/thread/test/Jamfile.v2 |     1 +                                       
   4 files changed, 9 insertions(+), 2 deletions(-)
Modified: trunk/boost/thread.hpp
==============================================================================
--- trunk/boost/thread.hpp	(original)
+++ trunk/boost/thread.hpp	2009-10-22 05:33:21 EDT (Thu, 22 Oct 2009)
@@ -1,6 +1,6 @@
 // Copyright (C) 2001-2003
 // William E. Kempf
-// (C) Copyright 2008 Anthony Williams
+// (C) Copyright 2008-9 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)
@@ -21,5 +21,6 @@
 #include <boost/thread/locks.hpp>
 #include <boost/thread/shared_mutex.hpp>
 #include <boost/thread/barrier.hpp>
+#include <boost/thread/future.hpp>
 
 #endif
Added: trunk/boost/thread/future.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/future.hpp	2009-10-22 05:33:21 EDT (Thu, 22 Oct 2009)
@@ -0,0 +1,1364 @@
+//  (C) Copyright 2008-9 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 BOOST_THREAD_FUTURE_HPP
+#define BOOST_THREAD_FUTURE_HPP
+#include <stdexcept>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/thread_time.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>
+#include <vector>
+
+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);
+        }
+        
+    };
+
+}
+
+
+#endif
Modified: trunk/libs/thread/doc/changes.qbk
==============================================================================
--- trunk/libs/thread/doc/changes.qbk	(original)
+++ trunk/libs/thread/doc/changes.qbk	2009-10-22 05:33:21 EDT (Thu, 22 Oct 2009)
@@ -5,7 +5,11 @@
   http://www.boost.org/LICENSE_1_0.txt).
 ]
 
-[section:changes Changes since boost 1.35]
+[section:changes Changes since boost 1.40]
+
+The 1.41.0 release of Boost adds futures to the thread library. There are also a few minor changes.
+
+[heading Changes since boost 1.35]
 
 The 1.36.0 release of Boost includes a few new features in the thread library:
 
Added: trunk/libs/thread/doc/future_ref.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/thread/doc/future_ref.qbk	2009-10-22 05:33:21 EDT (Thu, 22 Oct 2009)
@@ -0,0 +1,968 @@
+[/
+  (C) Copyright 2008-9 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).
+]
+
+[section:reference Futures Reference]
+
+[section:future_state `state` enum]
+
+    namespace future_state
+    {
+        enum state {uninitialized, waiting, ready};
+    }
+
+[endsect]
+
+[section:unique_future `unique_future` class template]
+
+    template <typename R>
+    class unique_future
+    {
+        unique_future(unique_future & rhs);// = delete;
+        unique_future& operator=(unique_future& rhs);// = delete;
+
+    public:
+        typedef future_state::state state;
+
+        unique_future();
+        ~unique_future();
+
+        // move support
+        unique_future(unique_future && other);
+        unique_future& operator=(unique_future && other);
+
+        void swap(unique_future& other);
+
+        // retrieving the value
+        R&& get();        
+
+        // functions to check state
+        state get_state() const;
+        bool is_ready() const;        
+        bool has_exception() const;        
+        bool has_value() const;        
+
+        // waiting for the result to be ready
+        void wait() const;        
+        template<typename Duration>
+        bool timed_wait(Duration const& rel_time) const;
+        bool timed_wait_until(boost::system_time const& abs_time) const;
+    };
+
+[section:default_constructor Default Constructor]
+
+    unique_future();
+
+[variablelist
+
+[[Effects:] [Constructs an uninitialized future.]]
+
+[[Postconditions:] [[unique_future_is_ready_link `this->is_ready`] returns `false`. [unique_future_get_state_link
+`this->get_state()`] returns __uninitialized__.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:destructor Destructor]
+
+    ~unique_future();
+
+[variablelist
+
+[[Effects:] [Destroys `*this`.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:move_constructor Move Constructor]
+
+    unique_future(unique_future && other);
+
+[variablelist
+
+[[Effects:] [Constructs a new future, and transfers ownership of the asynchronous result associated with `other` to `*this`.]]
+
+[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
+call. `other->get_state()` returns __uninitialized__. If `other` was associated with an asynchronous result, that result is now
+associated with `*this`. `other` is not associated with any asynchronous result.]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:move_assignment Move Assignment Operator]
+
+    unique_future& operator=(unique_future && other);
+
+[variablelist
+
+[[Effects:] [Transfers ownership of the asynchronous result associated with `other` to `*this`.]]
+
+[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
+call. `other->get_state()` returns __uninitialized__. If `other` was associated with an asynchronous result, that result is now
+associated with `*this`. `other` is not associated with any asynchronous result. If `*this` was associated with an asynchronous
+result prior to the call, that result no longer has an associated __unique_future__ instance.]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:swap Member function `swap()`]
+
+    void swap(unique_future & other);
+
+[variablelist
+
+[[Effects:] [Swaps ownership of the asynchronous results associated with `other` and `*this`.]]
+
+[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
+call. `other->get_state()` returns the value of `this->get_state()` prior to the call. If `other` was associated with an
+asynchronous result, that result is now associated with `*this`, otherwise `*this` has no associated result. If `*this` was
+associated with an asynchronous result, that result is now associated with `other`, otherwise `other` has no associated result.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
+[section:get Member function `get()`]
+
+    R&& get();
+    R& unique_future<R&>::get();
+    void unique_future<void>::get();
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready as-if by a call to
+__unique_future_wait__, and retrieves the result (whether that is a value or an exception).]]
+
+[[Returns:] [If the result type `R` is a reference, returns the stored reference. If `R` is `void`, there is no return
+value. Otherwise, returns an rvalue-reference to the value stored in the asynchronous result.]]
+
+[[Postconditions:] [[unique_future_is_ready_link `this->is_ready()`] returns `true`. [unique_future_get_state_link
+`this->get_state()`] returns __ready__.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` 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.]]
+
+[[Notes:] [`get()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+[section:wait Member function `wait()`]
+
+    void wait();
+
+[variablelist
+
+[[Effects:] [If `*this` 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 ['wait callback] set, that callback is invoked prior to waiting.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [[unique_future_is_ready_link `this->is_ready()`] returns `true`. [unique_future_get_state_link
+`this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`wait()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+[section:timed_wait_duration Member function `timed_wait()`]
+
+    template<typename Duration>
+    bool timed_wait(Duration const& wait_duration);
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time specified by
+`wait_duration` has elapsed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is
+invoked prior to waiting.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
+elapsed, `false` otherwise.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [If this call returned `true`, then [unique_future_is_ready_link `this->is_ready()`] returns `true` and
+[unique_future_get_state_link `this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`timed_wait()` is an ['interruption point]. `Duration` must be a type that meets the Boost.DateTime time duration requirements.]]
+
+]
+
+[endsect]
+
+[section:timed_wait_absolute Member function `timed_wait()`]
+
+    bool timed_wait(boost::system_time const& wait_timeout);
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time point specified by
+`wait_timeout` has passed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is invoked
+prior to waiting.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
+passed, `false` otherwise.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [If this call returned `true`, then [unique_future_is_ready_link `this->is_ready()`] returns `true` and
+[unique_future_get_state_link `this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`timed_wait()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+
+[section:is_ready Member function `is_ready()`]
+
+    bool is_ready();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready for retrieval, `false`
+otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:has_value Member function `has_value()`]
+
+    bool has_value();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with a value rather than an exception.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
+stored value, `false` otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:has_exception Member function `has_exception()`]
+
+    bool has_exception();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with an exception rather than a value.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
+stored exception, `false` otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:get_state Member function `get_state()`]
+
+    future_state::state get_state();
+
+[variablelist
+
+[[Effects:] [Determine the state of the asynchronous result associated with `*this`, if any.]]
+
+[[Returns:] [__uninitialized__ if `*this` is not associated with an asynchronous result. __ready__ if the asynchronous result
+associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
+[endsect]
+
+[section:shared_future `shared_future` class template]
+
+    template <typename R>
+    class shared_future
+    {
+    public:
+        typedef future_state::state state;
+
+        shared_future();
+        ~shared_future();
+
+        // copy support
+        shared_future(shared_future const& other);
+        shared_future& operator=(shared_future const& other);
+
+        // move support
+        shared_future(shared_future && other);
+        shared_future(unique_future<R> && other);
+        shared_future& operator=(shared_future && other);
+        shared_future& operator=(unique_future<R> && other);
+
+        void swap(shared_future& other);
+
+        // retrieving the value
+        R get();
+        
+        // functions to check state, and wait for ready
+        state get_state() const;
+        bool is_ready() const;
+        bool has_exception() const;
+        bool has_value() const;
+
+        // waiting for the result to be ready
+        void wait() const;        
+        template<typename Duration>
+        bool timed_wait(Duration const& rel_time) const;
+        bool timed_wait_until(boost::system_time const& abs_time) const;        
+    };
+
+[section:default_constructor Default Constructor]
+
+    shared_future();
+
+[variablelist
+
+[[Effects:] [Constructs an uninitialized future.]]
+
+[[Postconditions:] [[shared_future_is_ready_link `this->is_ready`] returns `false`. [shared_future_get_state_link
+`this->get_state()`] returns __uninitialized__.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:get Member function `get()`]
+
+    const R& get();
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready as-if by a call to
+__shared_future_wait__, and returns a `const` reference to the result.]]
+
+[[Returns:] [If the result type `R` is a reference, returns the stored reference. If `R` is `void`, there is no return
+value. Otherwise, returns a `const` reference to the value stored in the asynchronous result.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the
+result associated with `*this` is not ready at the point of the call, and the current thread is interrupted.]]
+
+[[Notes:] [`get()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+[section:wait Member function `wait()`]
+
+    void wait();
+
+[variablelist
+
+[[Effects:] [If `*this` 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 ['wait callback] set, that callback is invoked prior to waiting.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [[shared_future_is_ready_link `this->is_ready()`] returns `true`. [shared_future_get_state_link
+`this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`wait()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+[section:timed_wait_duration Member function `timed_wait()`]
+
+    template<typename Duration>
+    bool timed_wait(Duration const& wait_duration);
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time specified by
+`wait_duration` has elapsed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is
+invoked prior to waiting.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
+elapsed, `false` otherwise.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [If this call returned `true`, then [shared_future_is_ready_link `this->is_ready()`] returns `true` and
+[shared_future_get_state_link `this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`timed_wait()` is an ['interruption point]. `Duration` must be a type that meets the Boost.DateTime time duration requirements.]]
+
+]
+
+[endsect]
+
+[section:timed_wait_absolute Member function `timed_wait()`]
+
+    bool timed_wait(boost::system_time const& wait_timeout);
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time point specified by
+`wait_timeout` has passed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is invoked
+prior to waiting.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
+passed, `false` otherwise.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [If this call returned `true`, then [shared_future_is_ready_link `this->is_ready()`] returns `true` and
+[shared_future_get_state_link `this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`timed_wait()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+[section:is_ready Member function `is_ready()`]
+
+    bool is_ready();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready for retrieval, `false`
+otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:has_value Member function `has_value()`]
+
+    bool has_value();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with a value rather than an exception.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
+stored value, `false` otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:has_exception Member function `has_exception()`]
+
+    bool has_exception();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with an exception rather than a value.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
+stored exception, `false` otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:get_state Member function `get_state()`]
+
+    future_state::state get_state();
+
+[variablelist
+
+[[Effects:] [Determine the state of the asynchronous result associated with `*this`, if any.]]
+
+[[Returns:] [__uninitialized__ if `*this` is not associated with an asynchronous result. __ready__ if the asynchronous result
+associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
+[endsect]
+
+[section:promise `promise` class template]
+
+    template <typename R>
+    class promise
+    {
+        promise(promise & rhs);// = delete;
+        promise & operator=(promise & rhs);// = delete;
+    public:
+        // template <class Allocator> explicit promise(Allocator a);
+
+        promise();
+        ~promise();
+
+        // Move support
+        promise(promise && rhs);
+        promise & operator=(promise&& rhs);
+        
+        void swap(promise& other);
+        // Result retrieval
+        unique_future<R> get_future();
+
+        // Set the value
+        void set_value(R& r);
+        void set_value(R&& r);
+        void set_exception(boost::exception_ptr e);
+
+        template<typename F>
+        void set_wait_callback(F f);        
+    };
+
+[section:default_constructor Default Constructor]
+
+    promise();
+
+[variablelist
+
+[[Effects:] [Constructs a new __promise__ with no associated result.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:move_constructor Move Constructor]
+
+    promise(promise && other);
+
+[variablelist
+
+[[Effects:] [Constructs a new __promise__, and transfers ownership of the result associated with `other` to `*this`, leaving `other`
+with no associated result.]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:move_assignment Move Assignment Operator]
+
+    promise& operator=(promise && other);
+
+[variablelist
+
+[[Effects:] [Transfers ownership of the result associated with `other` to `*this`, leaving `other` with no associated result. If there
+was already a result associated with `*this`, and that result was not ['ready], sets any futures associated with that result to
+['ready] with a __broken_promise__ exception as the result. ]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:destructor Destructor]
+
+    ~promise();
+
+[variablelist
+
+[[Effects:] [Destroys `*this`. If there was a result associated with `*this`, and that result is not ['ready], sets any futures
+associated with that task to ['ready] with a __broken_promise__ exception as the result.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:get_future Member Function `get_future()`]
+
+    unique_future<R> get_future();
+
+[variablelist
+
+[[Effects:] [If `*this` was not associated with a result, allocate storage for a new asynchronous result and associate it with
+`*this`. Returns a __unique_future__ associated with the result associated with `*this`. ]]
+
+[[Throws:] [__future_already_retrieved__ if the future associated with the task has already been retrieved. `std::bad_alloc` if any
+memory necessary could not be allocated.]]
+
+]
+
+[endsect]
+
+[section:set_value Member Function `set_value()`]
+
+    void set_value(R&& r);
+    void set_value(const R& r);
+    void promise<R&>::set_value(R& r);
+    void promise<void>::set_value();
+
+[variablelist
+
+[[Effects:] [If `*this` was not associated with a result, allocate storage for a new asynchronous result and associate it with
+`*this`. Store the value `r` in the asynchronous result associated with `*this`. Any threads blocked waiting for the asynchronous
+result are woken.]]
+
+[[Postconditions:] [All futures waiting on the asynchronous result are ['ready] and __unique_future_has_value__ or
+__shared_future_has_value__ for those futures shall return `true`.]]
+
+[[Throws:] [__promise_already_satisfied__ if the result associated with `*this` is already ['ready]. `std::bad_alloc` if the memory
+required for storage of the result cannot be allocated. Any exception thrown by the copy or move-constructor of `R`.]]
+
+]
+
+[endsect]
+
+[section:set_exception Member Function `set_exception()`]
+
+    void set_exception(boost::exception_ptr e);
+
+[variablelist
+
+[[Effects:] [If `*this` was not associated with a result, allocate storage for a new asynchronous result and associate it with
+`*this`. Store the exception `e` in the asynchronous result associated with `*this`. Any threads blocked waiting for the asynchronous
+result are woken.]]
+
+[[Postconditions:] [All futures waiting on the asynchronous result are ['ready] and __unique_future_has_exception__ or
+__shared_future_has_exception__ for those futures shall return `true`.]]
+
+[[Throws:] [__promise_already_satisfied__ if the result associated with `*this` is already ['ready]. `std::bad_alloc` if the memory
+required for storage of the result cannot be allocated.]]
+
+]
+
+[endsect]
+
+[section:set_wait_callback Member Function `set_wait_callback()`]
+
+    template<typename F>
+    void set_wait_callback(F f);
+
+[variablelist
+
+[[Preconditions:] [The expression `f(t)` where `t` is a lvalue of type __packaged_task__ shall be well-formed. Invoking a copy of
+`f` shall have the same effect as invoking `f`]]
+
+[[Effects:] [Store a copy of `f` with the asynchronous result associated with `*this` as a ['wait callback]. This will replace any
+existing wait callback store alongside that result. If a thread subsequently calls one of the wait functions on a __unique_future__
+or __shared_future__ associated with this result, and the result is not ['ready], `f(*this)` shall be invoked.]]
+
+[[Throws:] [`std::bad_alloc` if memory cannot be allocated for the required storage.]]
+
+]
+
+[endsect]
+
+[endsect]
+
+[section:packaged_task `packaged_task` class template]
+
+    template<typename R>
+    class packaged_task
+    {
+        packaged_task(packaged_task&);// = delete;
+        packaged_task& operator=(packaged_task&);// = delete;
+        
+    public:
+        // construction and destruction
+        template <class F>
+        explicit packaged_task(F const& f);
+
+        explicit packaged_task(R(*f)());
+        
+        template <class F>
+        explicit packaged_task(F&& f);
+
+        // 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()
+        {}
+
+        // move support
+        packaged_task(packaged_task&& other);
+        packaged_task& operator=(packaged_task&& other);
+
+        void swap(packaged_task& other);
+        // result retrieval
+        unique_future<R> get_future();        
+
+        // execution
+        void operator()();
+
+        template<typename F>
+        void set_wait_callback(F f);        
+    };
+
+[section:task_constructor Task Constructor]
+
+    template<typename F>
+    packaged_task(F const &f);
+
+    packaged_task(R(*f)());
+
+    template<typename F>
+    packaged_task(F&&f);
+
+[variablelist
+
+[[Preconditions:] [`f()` is a valid expression with a return type convertible to `R`. Invoking a copy of `f` shall behave the same
+as invoking `f`.]]
+
+[[Effects:] [Constructs a new __packaged_task__ with a copy of `f` stored as the associated task.]]
+
+[[Throws:] [Any exceptions thrown by the copy (or move) constructor of `f`. `std::bad_alloc` if memory for the internal data
+structures could not be allocated.]]
+
+]
+
+[endsect]
+
+[section:move_constructor Move Constructor]
+
+    packaged_task(packaged_task && other);
+
+[variablelist
+
+[[Effects:] [Constructs a new __packaged_task__, and transfers ownership of the task associated with `other` to `*this`, leaving `other`
+with no associated task.]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:move_assignment Move Assignment Operator]
+
+    packaged_task& operator=(packaged_task && other);
+
+[variablelist
+
+[[Effects:] [Transfers ownership of the task associated with `other` to `*this`, leaving `other` with no associated task. If there
+was already a task associated with `*this`, and that task has not been invoked, sets any futures associated with that task to
+['ready] with a __broken_promise__ exception as the result. ]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:destructor Destructor]
+
+    ~packaged_task();
+
+[variablelist
+
+[[Effects:] [Destroys `*this`. If there was a task associated with `*this`, and that task has not been invoked, sets any futures
+associated with that task to ['ready] with a __broken_promise__ exception as the result.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:get_future Member Function `get_future()`]
+
+    unique_future<R> get_future();
+
+[variablelist
+
+[[Effects:] [Returns a __unique_future__ associated with the result of the task associated with `*this`. ]]
+
+[[Throws:] [__task_moved__ if ownership of the task associated with `*this` has been moved to another instance of
+__packaged_task__. __future_already_retrieved__ if the future associated with the task has already been retrieved.]]
+
+]
+
+[endsect]
+
+[section:call_operator Member Function `operator()()`]
+
+    void operator()();
+
+[variablelist
+
+[[Effects:] [Invoke the task associated with `*this` 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.]]
+
+[[Postconditions:] [All futures waiting on the asynchronous result are ['ready]]]
+
+[[Throws:] [__task_moved__ if ownership of the task associated with `*this` has been moved to another instance of
+__packaged_task__. __task_already_started__ if the task has already been invoked.]]
+
+]
+
+[endsect]
+
+[section:set_wait_callback Member Function `set_wait_callback()`]
+
+    template<typename F>
+    void set_wait_callback(F f);
+
+[variablelist
+
+[[Preconditions:] [The expression `f(t)` where `t` is a lvalue of type __packaged_task__ shall be well-formed. Invoking a copy of
+`f` shall have the same effect as invoking `f`]]
+
+[[Effects:] [Store a copy of `f` with the task associated with `*this` as a ['wait callback]. This will replace any existing wait
+callback store alongside that task. If a thread subsequently calls one of the wait functions on a __unique_future__ or
+__shared_future__ associated with this task, and the result of the task is not ['ready], `f(*this)` shall be invoked.]]
+
+[[Throws:] [__task_moved__ if ownership of the task associated with `*this` has been moved to another instance of
+__packaged_task__.]]
+
+]
+
+[endsect]
+
+
+[endsect]
+
+[section:wait_for_any Non-member function `wait_for_any()`]
+
+    template<typename Iterator>
+    Iterator wait_for_any(Iterator begin,Iterator end);
+
+    template<typename F1,typename F2>
+    unsigned wait_for_any(F1& f1,F2& f2);
+
+    template<typename F1,typename F2,typename F3>
+    unsigned wait_for_any(F1& f1,F2& f2,F3& f3);
+
+    template<typename F1,typename F2,typename F3,typename F4>
+    unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4);
+
+    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);
+
+[variablelist
+
+[[Preconditions:] [The types `Fn` shall be specializations of
+__unique_future__ or __shared_future__, and `Iterator` shall be a
+forward iterator with a `value_type` which is a specialization of
+__unique_future__ or __shared_future__.]]
+
+[[Effects:] [Waits until at least one of the specified futures is ['ready].]]
+
+[[Returns:] [The range-based overload returns an `Iterator` identifying the first future in the range that was detected as
+['ready]. The remaining overloads return the zero-based index of the first future that was detected as ['ready] (first parameter =>
+0, second parameter => 1, etc.).]]
+
+[[Throws:] [__thread_interrupted__ if the current thread is interrupted. Any exception thrown by the ['wait callback] associated
+with any of the futures being waited for.  `std::bad_alloc` if memory could not be allocated for the internal wait structures.]]
+
+[[Notes:] [`wait_for_any()` is an ['interruption point].]]
+
+]
+
+
+[endsect]
+
+[section:wait_for_all Non-member function `wait_for_all()`]
+
+    template<typename Iterator>
+    void wait_for_all(Iterator begin,Iterator end);
+
+    template<typename F1,typename F2>
+    void wait_for_all(F1& f1,F2& f2);
+
+    template<typename F1,typename F2,typename F3>
+    void wait_for_all(F1& f1,F2& f2,F3& f3);
+
+    template<typename F1,typename F2,typename F3,typename F4>
+    void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4);
+
+    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);
+
+[variablelist
+
+[[Preconditions:] [The types `Fn` shall be specializations of
+__unique_future__ or __shared_future__, and `Iterator` shall be a
+forward iterator with a `value_type` which is a specialization of
+__unique_future__ or __shared_future__.]]
+
+[[Effects:] [Waits until all of the specified futures are ['ready].]]
+
+[[Throws:] [Any exceptions thrown by a call to `wait()` on the specified futures.]]
+
+[[Notes:] [`wait_for_all()` is an ['interruption point].]]
+
+]
+
+
+[endsect]
+
+
+[endsect]
Added: trunk/libs/thread/doc/futures.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/thread/doc/futures.qbk	2009-10-22 05:33:21 EDT (Thu, 22 Oct 2009)
@@ -0,0 +1,187 @@
+[/
+  (C) Copyright 2008-9 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).
+]
+
+[section:futures Futures]
+
+[template future_state_link[link_text] [link thread.synchronization.futures.reference.future_state [link_text]]]
+[def __uninitialized__ [future_state_link `boost::future_state::uninitialized`]]
+[def __ready__ [future_state_link `boost::future_state::ready`]]
+[def __waiting__ [future_state_link `boost::future_state::waiting`]]
+
+[def __future_uninitialized__ `boost::future_uninitialized`]
+[def __broken_promise__ `boost::broken_promise`]
+[def __future_already_retrieved__ `boost::future_already_retrieved`]
+[def __task_moved__ `boost::task_moved`]
+[def __task_already_started__ `boost::task_already_started`]
+[def __promise_already_satisfied__ `boost::promise_already_satisfied`]
+
+[def __thread_interrupted__ `boost::thread_interrupted`]
+
+
+[template unique_future_link[link_text] [link thread.synchronization.futures.reference.unique_future [link_text]]]
+[def __unique_future__ [unique_future_link `boost::unique_future`]]
+
+[template unique_future_get_link[link_text] [link thread.synchronization.futures.reference.unique_future.get [link_text]]]
+[def __unique_future_get__ [unique_future_get_link `boost::unique_future<R>::get()`]]
+
+[template unique_future_wait_link[link_text] [link thread.synchronization.futures.reference.unique_future.wait [link_text]]]
+[def __unique_future_wait__ [unique_future_wait_link `boost::unique_future<R>::wait()`]]
+
+[template unique_future_is_ready_link[link_text] [link thread.synchronization.futures.reference.unique_future.is_ready [link_text]]]
+[def __unique_future_is_ready__ [unique_future_is_ready_link `boost::unique_future<R>::is_ready()`]]
+
+[template unique_future_has_value_link[link_text] [link thread.synchronization.futures.reference.unique_future.has_value [link_text]]]
+[def __unique_future_has_value__ [unique_future_has_value_link `boost::unique_future<R>::has_value()`]]
+
+[template unique_future_has_exception_link[link_text] [link thread.synchronization.futures.reference.unique_future.has_exception [link_text]]]
+[def __unique_future_has_exception__ [unique_future_has_exception_link `boost::unique_future<R>::has_exception()`]]
+
+[template unique_future_get_state_link[link_text] [link thread.synchronization.futures.reference.unique_future.get_state [link_text]]]
+[def __unique_future_get_state__ [unique_future_get_state_link `boost::unique_future<R>::get_state()`]]
+
+[template shared_future_link[link_text] [link thread.synchronization.futures.reference.shared_future [link_text]]]
+[def __shared_future__ [shared_future_link `boost::shared_future`]]
+
+[template shared_future_get_link[link_text] [link thread.synchronization.futures.reference.shared_future.get [link_text]]]
+[def __shared_future_get__ [shared_future_get_link `boost::shared_future<R>::get()`]]
+
+[template shared_future_wait_link[link_text] [link thread.synchronization.futures.reference.shared_future.wait [link_text]]]
+[def __shared_future_wait__ [shared_future_wait_link `boost::shared_future<R>::wait()`]]
+
+[template shared_future_is_ready_link[link_text] [link thread.synchronization.futures.reference.shared_future.is_ready [link_text]]]
+[def __shared_future_is_ready__ [shared_future_is_ready_link `boost::shared_future<R>::is_ready()`]]
+
+[template shared_future_has_value_link[link_text] [link thread.synchronization.futures.reference.shared_future.has_value [link_text]]]
+[def __shared_future_has_value__ [shared_future_has_value_link `boost::shared_future<R>::has_value()`]]
+
+[template shared_future_has_exception_link[link_text] [link thread.synchronization.futures.reference.shared_future.has_exception [link_text]]]
+[def __shared_future_has_exception__ [shared_future_has_exception_link `boost::shared_future<R>::has_exception()`]]
+
+[template shared_future_get_state_link[link_text] [link thread.synchronization.futures.reference.shared_future.get_state [link_text]]]
+[def __shared_future_get_state__ [shared_future_get_state_link `boost::shared_future<R>::get_state()`]]
+
+[template promise_link[link_text] [link thread.synchronization.futures.reference.promise [link_text]]]
+[def __promise__ [promise_link `boost::promise`]]
+
+[template packaged_task_link[link_text] [link thread.synchronization.futures.reference.packaged_task [link_text]]]
+[def __packaged_task__ [packaged_task_link `boost::packaged_task`]]
+
+[template wait_for_any_link[link_text] [link thread.synchronization.futures.reference.wait_for_any [link_text]]]
+[def __wait_for_any__ [wait_for_any_link `boost::wait_for_any()`]]
+
+[template wait_for_all_link[link_text] [link thread.synchronization.futures.reference.wait_for_all [link_text]]]
+[def __wait_for_all__ [wait_for_all_link `boost::wait_for_all()`]]
+
+
+[section:overview Overview]
+
+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.
+
+This is done through the provision of four class templates: __unique_future__ and __shared_future__ which are used to retrieve the
+asynchronous results, and __promise__ and __packaged_task__ which are used to generate the asynchronous results.
+
+An instance of __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 __unique_future_get__ by rvalue-reference to allow the result to be moved or copied as
+appropriate for the type.
+
+On the other hand, many instances of __shared_future__ may reference the same result. Instances can be freely copied and assigned,
+and __shared_future_get__ returns a `const` reference so that multiple calls to __shared_future_get__ are safe. You can move an
+instance of __unique_future__ into an instance of __shared_future__, thus transferring ownership of the associated asynchronous
+result, but not vice-versa.
+
+You can wait for futures either individually or with one of the __wait_for_any__ and __wait_for_all__ functions.
+
+[endsect]
+
+[section:creating Creating asynchronous values]
+
+You can set the value in a future with either a __promise__ or a __packaged_task__. A __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 __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.
+
+    int calculate_the_answer_to_life_the_universe_and_everything()
+    {
+        return 42;
+    }
+
+    boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything);
+    boost::unique_future<int> fi=pt.get_future();
+
+    boost::thread task(boost::move(pt)); // launch task on a thread
+
+    fi.wait(); // wait for it to finish
+        
+    assert(fi.is_ready());
+    assert(fi.has_value());
+    assert(!fi.has_exception());
+    assert(fi.get_state()==boost::future_state::ready);
+    assert(fi.get()==42);
+
+
+A __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.
+
+    boost::promise<int> pi;
+    boost::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()==boost::future_state::ready);
+    assert(fi.get()==42);
+
+[endsect]
+
+[section:lazy_futures Wait Callbacks and Lazy Futures]
+
+Both __promise__ and __packaged_task__ support ['wait callbacks] that are invoked when a thread blocks in a call to `wait()` or
+`timed_wait()` on a future that is waiting for the result from the __promise__ or __packaged_task__, in the thread that is doing the
+waiting. These can be set using the `set_wait_callback()` member function on the __promise__ or __packaged_task__ in question.
+
+This allows ['lazy futures] where the result is not actually computed until it is needed by some thread. In the example below, the
+call to `f.get()` invokes the callback `invoke_lazy_task`, which runs the task to set the value. If you remove the call to
+`f.get()`, the task is not ever run.
+
+    int calculate_the_answer_to_life_the_universe_and_everything()
+    {
+        return 42;
+    }
+
+    void invoke_lazy_task(boost::packaged_task<int>& task)
+    {
+        try
+        {
+            task();
+        }
+        catch(boost::task_already_started&)
+        {}
+    }
+
+    int main()
+    {
+        boost::packaged_task<int> task(calculate_the_answer_to_life_the_universe_and_everything);
+        task.set_wait_callback(invoke_lazy_task);
+        boost::unique_future<int> f(task.get_future());
+
+        assert(f.get()==42);
+    }
+
+
+[endsect]
+
+[include future_ref.qbk]
+
+[endsect]
\ No newline at end of file
Modified: trunk/libs/thread/doc/thread.qbk
==============================================================================
--- trunk/libs/thread/doc/thread.qbk	(original)
+++ trunk/libs/thread/doc/thread.qbk	2009-10-22 05:33:21 EDT (Thu, 22 Oct 2009)
@@ -158,6 +158,7 @@
 [include condition_variables.qbk]
 [include once.qbk]
 [include barrier.qbk]
+[include futures.qbk]
 [endsect]
 
 [include tss.qbk]
Modified: trunk/libs/thread/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2	(original)
+++ trunk/libs/thread/test/Jamfile.v2	2009-10-22 05:33:21 EDT (Thu, 22 Oct 2009)
@@ -57,6 +57,7 @@
           [ thread-run test_shared_mutex_timed_locks.cpp ]
           [ thread-run test_lock_concept.cpp ]
           [ thread-run test_generic_locks.cpp ]
+          [ thread-run test_futures.cpp ]
           [ compile-fail no_implicit_move_from_lvalue_thread.cpp ]
           [ compile-fail no_implicit_assign_from_lvalue_thread.cpp ]
     ;
Added: trunk/libs/thread/test/test_futures.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/test_futures.cpp	2009-10-22 05:33:21 EDT (Thu, 22 Oct 2009)
@@ -0,0 +1,1218 @@
+//  (C) Copyright 2008-9 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 "boost/thread/future.hpp"
+#include <utility>
+#include <memory>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+
+#ifdef BOOST_HAS_RVALUE_REFS
+    template<typename T>
+    typename boost::remove_reference<T>::type&& cast_to_rval(T&& t)
+    {
+        return t;
+    }
+#else
+    template<typename T>
+    boost::detail::thread_move_t<T> cast_to_rval(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(boost::promise<int>* p)
+{
+    p->set_value(42);
+}
+
+struct my_exception
+{};
+
+void set_promise_exception_thread(boost::promise<int>* p)
+{
+    p->set_exception(boost::copy_exception(my_exception()));
+}
+
+
+void test_store_value_from_thread()
+{
+    boost::promise<int> pi2;
+    boost::unique_future<int> fi2=pi2.get_future();
+    boost::thread(set_promise_thread,&pi2);
+    int j=fi2.get();
+    BOOST_CHECK(j==42);
+    BOOST_CHECK(fi2.is_ready());
+    BOOST_CHECK(fi2.has_value());
+    BOOST_CHECK(!fi2.has_exception());
+    BOOST_CHECK(fi2.get_state()==boost::future_state::ready);
+}
+
+
+void test_store_exception()
+{
+    boost::promise<int> pi3;
+    boost::unique_future<int> fi3=pi3.get_future();
+    boost::thread(set_promise_exception_thread,&pi3);
+    try
+    {
+        fi3.get();
+        BOOST_CHECK(false);
+    }
+    catch(my_exception)
+    {
+        BOOST_CHECK(true);
+    }
+    
+    BOOST_CHECK(fi3.is_ready());
+    BOOST_CHECK(!fi3.has_value());
+    BOOST_CHECK(fi3.has_exception());
+    BOOST_CHECK(fi3.get_state()==boost::future_state::ready);
+}
+
+void test_initial_state()
+{
+    boost::unique_future<int> fi;
+    BOOST_CHECK(!fi.is_ready());
+    BOOST_CHECK(!fi.has_value());
+    BOOST_CHECK(!fi.has_exception());
+    BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized);
+    int i;
+    try
+    {
+        i=fi.get();
+        BOOST_CHECK(false);
+    }
+    catch(boost::future_uninitialized)
+    {
+        BOOST_CHECK(true);
+    }
+}
+
+void test_waiting_future()
+{
+    boost::promise<int> pi;
+    boost::unique_future<int> fi;
+    fi=pi.get_future();
+
+    int i=0;
+    BOOST_CHECK(!fi.is_ready());
+    BOOST_CHECK(!fi.has_value());
+    BOOST_CHECK(!fi.has_exception());
+    BOOST_CHECK(fi.get_state()==boost::future_state::waiting);
+    BOOST_CHECK(i==0);
+}
+
+void test_cannot_get_future_twice()
+{
+    boost::promise<int> pi;
+    pi.get_future();
+
+    try
+    {
+        pi.get_future();
+        BOOST_CHECK(false);
+    }
+    catch(boost::future_already_retrieved&)
+    {
+        BOOST_CHECK(true);
+    }
+}
+
+void test_set_value_updates_future_state()
+{
+    boost::promise<int> pi;
+    boost::unique_future<int> fi;
+    fi=pi.get_future();
+
+    pi.set_value(42);
+    
+    BOOST_CHECK(fi.is_ready());
+    BOOST_CHECK(fi.has_value());
+    BOOST_CHECK(!fi.has_exception());
+    BOOST_CHECK(fi.get_state()==boost::future_state::ready);
+}
+
+void test_set_value_can_be_retrieved()
+{
+    boost::promise<int> pi;
+    boost::unique_future<int> fi;
+    fi=pi.get_future();
+
+    pi.set_value(42);
+    
+    int i=0;
+    BOOST_CHECK(i=fi.get());
+    BOOST_CHECK(i==42);
+    BOOST_CHECK(fi.is_ready());
+    BOOST_CHECK(fi.has_value());
+    BOOST_CHECK(!fi.has_exception());
+    BOOST_CHECK(fi.get_state()==boost::future_state::ready);
+}
+
+void test_set_value_can_be_moved()
+{
+//     boost::promise<int> pi;
+//     boost::unique_future<int> fi;
+//     fi=pi.get_future();
+
+//     pi.set_value(42);
+    
+//     int i=0;
+//     BOOST_CHECK(i=fi.get());
+//     BOOST_CHECK(i==42);
+//     BOOST_CHECK(fi.is_ready());
+//     BOOST_CHECK(fi.has_value());
+//     BOOST_CHECK(!fi.has_exception());
+//     BOOST_CHECK(fi.get_state()==boost::future_state::ready);
+}
+
+void test_future_from_packaged_task_is_waiting()
+{
+    boost::packaged_task<int> pt(make_int);
+    boost::unique_future<int> fi=pt.get_future();
+    int i=0;
+    BOOST_CHECK(!fi.is_ready());
+    BOOST_CHECK(!fi.has_value());
+    BOOST_CHECK(!fi.has_exception());
+    BOOST_CHECK(fi.get_state()==boost::future_state::waiting);
+    BOOST_CHECK(i==0);
+}
+
+void test_invoking_a_packaged_task_populates_future()
+{
+    boost::packaged_task<int> pt(make_int);
+    boost::unique_future<int> fi=pt.get_future();
+
+    pt();
+
+    int i=0;
+    BOOST_CHECK(fi.is_ready());
+    BOOST_CHECK(fi.has_value());
+    BOOST_CHECK(!fi.has_exception());
+    BOOST_CHECK(fi.get_state()==boost::future_state::ready);
+    BOOST_CHECK(i=fi.get());
+    BOOST_CHECK(i==42);
+}
+
+void test_invoking_a_packaged_task_twice_throws()
+{
+    boost::packaged_task<int> pt(make_int);
+
+    pt();
+    try
+    {
+        pt();
+        BOOST_CHECK(false);
+    }
+    catch(boost::task_already_started)
+    {
+        BOOST_CHECK(true);
+    }
+}
+
+
+void test_cannot_get_future_twice_from_task()
+{
+    boost::packaged_task<int> pt(make_int);
+    pt.get_future();
+    try
+    {
+        pt.get_future();
+        BOOST_CHECK(false);
+    }
+    catch(boost::future_already_retrieved)
+    {
+        BOOST_CHECK(true);
+    }
+}
+
+void test_task_stores_exception_if_function_throws()
+{
+    boost::packaged_task<int> pt(throw_runtime_error);
+    boost::unique_future<int> fi=pt.get_future();
+
+    pt();
+
+    BOOST_CHECK(fi.is_ready());
+    BOOST_CHECK(!fi.has_value());
+    BOOST_CHECK(fi.has_exception());
+    BOOST_CHECK(fi.get_state()==boost::future_state::ready);
+    try
+    {
+        fi.get();
+        BOOST_CHECK(false);
+    }
+    catch(std::exception&)
+    {
+        BOOST_CHECK(true);
+    }
+    catch(...)
+    {
+        BOOST_CHECK(!"Unknown exception thrown");
+    }
+    
+}
+
+void test_void_promise()
+{
+    boost::promise<void> p;
+    boost::unique_future<void> f=p.get_future();
+    p.set_value();
+    BOOST_CHECK(f.is_ready());
+    BOOST_CHECK(f.has_value());
+    BOOST_CHECK(!f.has_exception());
+    BOOST_CHECK(f.get_state()==boost::future_state::ready);
+    f.get();
+}
+
+void test_reference_promise()
+{
+    boost::promise<int&> p;
+    boost::unique_future<int&> f=p.get_future();
+    int i=42;
+    p.set_value(i);
+    BOOST_CHECK(f.is_ready());
+    BOOST_CHECK(f.has_value());
+    BOOST_CHECK(!f.has_exception());
+    BOOST_CHECK(f.get_state()==boost::future_state::ready);
+    BOOST_CHECK(&f.get()==&i);
+}
+
+void do_nothing()
+{}
+
+void test_task_returning_void()
+{
+    boost::packaged_task<void> pt(do_nothing);
+    boost::unique_future<void> fi=pt.get_future();
+
+    pt();
+
+    BOOST_CHECK(fi.is_ready());
+    BOOST_CHECK(fi.has_value());
+    BOOST_CHECK(!fi.has_exception());
+    BOOST_CHECK(fi.get_state()==boost::future_state::ready);
+}
+
+int global_ref_target=0;
+
+int& return_ref()
+{
+    return global_ref_target;
+}
+
+void test_task_returning_reference()
+{
+    boost::packaged_task<int&> pt(return_ref);
+    boost::unique_future<int&> fi=pt.get_future();
+
+    pt();
+
+    BOOST_CHECK(fi.is_ready());
+    BOOST_CHECK(fi.has_value());
+    BOOST_CHECK(!fi.has_exception());
+    BOOST_CHECK(fi.get_state()==boost::future_state::ready);
+    int& i=fi.get();
+    BOOST_CHECK(&i==&global_ref_target);
+}
+
+void test_shared_future()
+{
+    boost::packaged_task<int> pt(make_int);
+    boost::unique_future<int> fi=pt.get_future();
+
+    boost::shared_future<int> sf(::cast_to_rval(fi));
+    BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized);
+
+    pt();
+
+    int i=0;
+    BOOST_CHECK(sf.is_ready());
+    BOOST_CHECK(sf.has_value());
+    BOOST_CHECK(!sf.has_exception());
+    BOOST_CHECK(sf.get_state()==boost::future_state::ready);
+    BOOST_CHECK(i=sf.get());
+    BOOST_CHECK(i==42);
+}
+
+void test_copies_of_shared_future_become_ready_together()
+{
+    boost::packaged_task<int> pt(make_int);
+    boost::unique_future<int> fi=pt.get_future();
+
+    boost::shared_future<int> sf(::cast_to_rval(fi));
+    boost::shared_future<int> sf2(sf);
+    boost::shared_future<int> sf3;
+    sf3=sf;
+    BOOST_CHECK(sf.get_state()==boost::future_state::waiting);
+    BOOST_CHECK(sf2.get_state()==boost::future_state::waiting);
+    BOOST_CHECK(sf3.get_state()==boost::future_state::waiting);
+
+    pt();
+
+    int i=0;
+    BOOST_CHECK(sf.is_ready());
+    BOOST_CHECK(sf.has_value());
+    BOOST_CHECK(!sf.has_exception());
+    BOOST_CHECK(sf.get_state()==boost::future_state::ready);
+    BOOST_CHECK(i=sf.get());
+    BOOST_CHECK(i==42);
+    i=0;
+    BOOST_CHECK(sf2.is_ready());
+    BOOST_CHECK(sf2.has_value());
+    BOOST_CHECK(!sf2.has_exception());
+    BOOST_CHECK(sf2.get_state()==boost::future_state::ready);
+    BOOST_CHECK(i=sf2.get());
+    BOOST_CHECK(i==42);
+    i=0;
+    BOOST_CHECK(sf3.is_ready());
+    BOOST_CHECK(sf3.has_value());
+    BOOST_CHECK(!sf3.has_exception());
+    BOOST_CHECK(sf3.get_state()==boost::future_state::ready);
+    BOOST_CHECK(i=sf3.get());
+    BOOST_CHECK(i==42);
+}
+
+void test_shared_future_can_be_move_assigned_from_unique_future()
+{
+    boost::packaged_task<int> pt(make_int);
+    boost::unique_future<int> fi=pt.get_future();
+
+    boost::shared_future<int> sf;
+    sf=::cast_to_rval(fi);
+    BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized);
+
+    BOOST_CHECK(!sf.is_ready());
+    BOOST_CHECK(!sf.has_value());
+    BOOST_CHECK(!sf.has_exception());
+    BOOST_CHECK(sf.get_state()==boost::future_state::waiting);
+}
+
+void test_shared_future_void()
+{
+    boost::packaged_task<void> pt(do_nothing);
+    boost::unique_future<void> fi=pt.get_future();
+
+    boost::shared_future<void> sf(::cast_to_rval(fi));
+    BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized);
+
+    pt();
+
+    BOOST_CHECK(sf.is_ready());
+    BOOST_CHECK(sf.has_value());
+    BOOST_CHECK(!sf.has_exception());
+    BOOST_CHECK(sf.get_state()==boost::future_state::ready);
+    sf.get();
+}
+
+void test_shared_future_ref()
+{
+    boost::promise<int&> p;
+    boost::shared_future<int&> f(p.get_future());
+    int i=42;
+    p.set_value(i);
+    BOOST_CHECK(f.is_ready());
+    BOOST_CHECK(f.has_value());
+    BOOST_CHECK(!f.has_exception());
+    BOOST_CHECK(f.get_state()==boost::future_state::ready);
+    BOOST_CHECK(&f.get()==&i);
+}
+
+void test_can_get_a_second_future_from_a_moved_promise()
+{
+    boost::promise<int> pi;
+    boost::unique_future<int> fi=pi.get_future();
+    
+    boost::promise<int> pi2(::cast_to_rval(pi));
+    boost::unique_future<int> fi2=pi.get_future();
+
+    pi2.set_value(3);
+    BOOST_CHECK(fi.is_ready());
+    BOOST_CHECK(!fi2.is_ready());
+    BOOST_CHECK(fi.get()==3);
+    pi.set_value(42);
+    BOOST_CHECK(fi2.is_ready());
+    BOOST_CHECK(fi2.get()==42);
+}
+
+void test_can_get_a_second_future_from_a_moved_void_promise()
+{
+    boost::promise<void> pi;
+    boost::unique_future<void> fi=pi.get_future();
+    
+    boost::promise<void> pi2(::cast_to_rval(pi));
+    boost::unique_future<void> fi2=pi.get_future();
+
+    pi2.set_value();
+    BOOST_CHECK(fi.is_ready());
+    BOOST_CHECK(!fi2.is_ready());
+    pi.set_value();
+    BOOST_CHECK(fi2.is_ready());
+}
+
+void test_unique_future_for_move_only_udt()
+{
+    boost::promise<X> pt;
+    boost::unique_future<X> fi=pt.get_future();
+
+    pt.set_value(X());
+    X res(fi.get());
+    BOOST_CHECK(res.i==42);
+}
+
+void test_unique_future_for_string()
+{
+    boost::promise<std::string> pt;
+    boost::unique_future<std::string> fi=pt.get_future();
+
+    pt.set_value(std::string("hello"));
+    std::string res(fi.get());
+    BOOST_CHECK(res=="hello");
+
+    boost::promise<std::string> pt2;
+    fi=pt2.get_future();
+
+    std::string const s="goodbye";
+    
+    pt2.set_value(s);
+    res=fi.get();
+    BOOST_CHECK(res=="goodbye");
+
+    boost::promise<std::string> pt3;
+    fi=pt3.get_future();
+
+    std::string s2="foo";
+    
+    pt3.set_value(s2);
+    res=fi.get();
+    BOOST_CHECK(res=="foo");
+}
+
+boost::mutex callback_mutex;
+unsigned callback_called=0;
+
+void wait_callback(boost::promise<int>& pi)
+{
+    boost::lock_guard<boost::mutex> lk(callback_mutex);
+    ++callback_called;
+    try
+    {
+        pi.set_value(42);
+    }
+    catch(...)
+    {
+    }
+}
+
+void do_nothing_callback(boost::promise<int>& pi)
+{
+    boost::lock_guard<boost::mutex> lk(callback_mutex);
+    ++callback_called;
+}
+
+void test_wait_callback()
+{
+    callback_called=0;
+    boost::promise<int> pi;
+    boost::unique_future<int> fi=pi.get_future();
+    pi.set_wait_callback(wait_callback);
+    fi.wait();
+    BOOST_CHECK(callback_called);
+    BOOST_CHECK(fi.get()==42);
+    fi.wait();
+    fi.wait();
+    BOOST_CHECK(callback_called==1);
+}
+
+void test_wait_callback_with_timed_wait()
+{
+    callback_called=0;
+    boost::promise<int> pi;
+    boost::unique_future<int> fi=pi.get_future();
+    pi.set_wait_callback(do_nothing_callback);
+    bool success=fi.timed_wait(boost::posix_time::milliseconds(10));
+    BOOST_CHECK(callback_called);
+    BOOST_CHECK(!success);
+    success=fi.timed_wait(boost::posix_time::milliseconds(10));
+    BOOST_CHECK(!success);
+    success=fi.timed_wait(boost::posix_time::milliseconds(10));
+    BOOST_CHECK(!success);
+    BOOST_CHECK(callback_called==3);
+    pi.set_value(42);
+    success=fi.timed_wait(boost::posix_time::milliseconds(10));
+    BOOST_CHECK(success);
+    BOOST_CHECK(callback_called==3);
+    BOOST_CHECK(fi.get()==42);
+    BOOST_CHECK(callback_called==3);
+}
+
+
+void wait_callback_for_task(boost::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;
+    boost::packaged_task<int> pt(make_int);
+    boost::unique_future<int> fi=pt.get_future();
+    pt.set_wait_callback(wait_callback_for_task);
+    fi.wait();
+    BOOST_CHECK(callback_called);
+    BOOST_CHECK(fi.get()==42);
+    fi.wait();
+    fi.wait();
+    BOOST_CHECK(callback_called==1);
+}
+
+void test_packaged_task_can_be_moved()
+{
+    boost::packaged_task<int> pt(make_int);
+
+    boost::unique_future<int> fi=pt.get_future();
+
+    BOOST_CHECK(!fi.is_ready());
+    
+    boost::packaged_task<int> pt2(::cast_to_rval(pt));
+
+    BOOST_CHECK(!fi.is_ready());
+    try
+    {
+        pt();
+        BOOST_CHECK(!"Can invoke moved task!");
+    }
+    catch(boost::task_moved&)
+    {
+    }
+
+    BOOST_CHECK(!fi.is_ready());
+
+    pt2();
+    
+    BOOST_CHECK(fi.is_ready());
+}
+
+void test_destroying_a_promise_stores_broken_promise()
+{
+    boost::unique_future<int> f;
+    
+    {
+        boost::promise<int> p;
+        f=p.get_future();
+    }
+    BOOST_CHECK(f.is_ready());
+    BOOST_CHECK(f.has_exception());
+    try
+    {
+        f.get();
+    }
+    catch(boost::broken_promise&)
+    {
+    }
+}
+
+void test_destroying_a_packaged_task_stores_broken_promise()
+{
+    boost::unique_future<int> f;
+    
+    {
+        boost::packaged_task<int> p(make_int);
+        f=p.get_future();
+    }
+    BOOST_CHECK(f.is_ready());
+    BOOST_CHECK(f.has_exception());
+    try
+    {
+        f.get();
+    }
+    catch(boost::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()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    
+    boost::thread(::cast_to_rval(pt));
+    
+    unsigned const future=boost::wait_for_any(f1,f2);
+    
+    BOOST_CHECK(future==0);
+    BOOST_CHECK(f1.is_ready());
+    BOOST_CHECK(!f2.is_ready());
+    BOOST_CHECK(f1.get()==42);
+}
+
+void test_wait_for_either_of_two_futures_2()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    
+    boost::thread(::cast_to_rval(pt2));
+    
+    unsigned const future=boost::wait_for_any(f1,f2);
+    
+    BOOST_CHECK(future==1);
+    BOOST_CHECK(!f1.is_ready());
+    BOOST_CHECK(f2.is_ready());
+    BOOST_CHECK(f2.get()==42);
+}
+
+void test_wait_for_either_of_three_futures_1()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    
+    boost::thread(::cast_to_rval(pt));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3);
+    
+    BOOST_CHECK(future==0);
+    BOOST_CHECK(f1.is_ready());
+    BOOST_CHECK(!f2.is_ready());
+    BOOST_CHECK(!f3.is_ready());
+    BOOST_CHECK(f1.get()==42);
+}
+
+void test_wait_for_either_of_three_futures_2()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    
+    boost::thread(::cast_to_rval(pt2));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3);
+    
+    BOOST_CHECK(future==1);
+    BOOST_CHECK(!f1.is_ready());
+    BOOST_CHECK(f2.is_ready());
+    BOOST_CHECK(!f3.is_ready());
+    BOOST_CHECK(f2.get()==42);
+}
+
+void test_wait_for_either_of_three_futures_3()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    
+    boost::thread(::cast_to_rval(pt3));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3);
+    
+    BOOST_CHECK(future==2);
+    BOOST_CHECK(!f1.is_ready());
+    BOOST_CHECK(!f2.is_ready());
+    BOOST_CHECK(f3.is_ready());
+    BOOST_CHECK(f3.get()==42);
+}
+
+void test_wait_for_either_of_four_futures_1()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    boost::packaged_task<int> pt4(make_int_slowly);
+    boost::unique_future<int> f4(pt4.get_future());
+    
+    boost::thread(::cast_to_rval(pt));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3,f4);
+    
+    BOOST_CHECK(future==0);
+    BOOST_CHECK(f1.is_ready());
+    BOOST_CHECK(!f2.is_ready());
+    BOOST_CHECK(!f3.is_ready());
+    BOOST_CHECK(!f4.is_ready());
+    BOOST_CHECK(f1.get()==42);
+}
+
+void test_wait_for_either_of_four_futures_2()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    boost::packaged_task<int> pt4(make_int_slowly);
+    boost::unique_future<int> f4(pt4.get_future());
+    
+    boost::thread(::cast_to_rval(pt2));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3,f4);
+    
+    BOOST_CHECK(future==1);
+    BOOST_CHECK(!f1.is_ready());
+    BOOST_CHECK(f2.is_ready());
+    BOOST_CHECK(!f3.is_ready());
+    BOOST_CHECK(!f4.is_ready());
+    BOOST_CHECK(f2.get()==42);
+}
+
+void test_wait_for_either_of_four_futures_3()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    boost::packaged_task<int> pt4(make_int_slowly);
+    boost::unique_future<int> f4(pt4.get_future());
+    
+    boost::thread(::cast_to_rval(pt3));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3,f4);
+    
+    BOOST_CHECK(future==2);
+    BOOST_CHECK(!f1.is_ready());
+    BOOST_CHECK(!f2.is_ready());
+    BOOST_CHECK(f3.is_ready());
+    BOOST_CHECK(!f4.is_ready());
+    BOOST_CHECK(f3.get()==42);
+}
+
+void test_wait_for_either_of_four_futures_4()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    boost::packaged_task<int> pt4(make_int_slowly);
+    boost::unique_future<int> f4(pt4.get_future());
+    
+    boost::thread(::cast_to_rval(pt4));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3,f4);
+    
+    BOOST_CHECK(future==3);
+    BOOST_CHECK(!f1.is_ready());
+    BOOST_CHECK(!f2.is_ready());
+    BOOST_CHECK(!f3.is_ready());
+    BOOST_CHECK(f4.is_ready());
+    BOOST_CHECK(f4.get()==42);
+}
+
+void test_wait_for_either_of_five_futures_1()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    boost::packaged_task<int> pt4(make_int_slowly);
+    boost::unique_future<int> f4(pt4.get_future());
+    boost::packaged_task<int> pt5(make_int_slowly);
+    boost::unique_future<int> f5(pt5.get_future());
+    
+    boost::thread(::cast_to_rval(pt));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5);
+    
+    BOOST_CHECK(future==0);
+    BOOST_CHECK(f1.is_ready());
+    BOOST_CHECK(!f2.is_ready());
+    BOOST_CHECK(!f3.is_ready());
+    BOOST_CHECK(!f4.is_ready());
+    BOOST_CHECK(!f5.is_ready());
+    BOOST_CHECK(f1.get()==42);
+}
+
+void test_wait_for_either_of_five_futures_2()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    boost::packaged_task<int> pt4(make_int_slowly);
+    boost::unique_future<int> f4(pt4.get_future());
+    boost::packaged_task<int> pt5(make_int_slowly);
+    boost::unique_future<int> f5(pt5.get_future());
+    
+    boost::thread(::cast_to_rval(pt2));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5);
+    
+    BOOST_CHECK(future==1);
+    BOOST_CHECK(!f1.is_ready());
+    BOOST_CHECK(f2.is_ready());
+    BOOST_CHECK(!f3.is_ready());
+    BOOST_CHECK(!f4.is_ready());
+    BOOST_CHECK(!f5.is_ready());
+    BOOST_CHECK(f2.get()==42);
+}
+void test_wait_for_either_of_five_futures_3()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    boost::packaged_task<int> pt4(make_int_slowly);
+    boost::unique_future<int> f4(pt4.get_future());
+    boost::packaged_task<int> pt5(make_int_slowly);
+    boost::unique_future<int> f5(pt5.get_future());
+    
+    boost::thread(::cast_to_rval(pt3));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5);
+    
+    BOOST_CHECK(future==2);
+    BOOST_CHECK(!f1.is_ready());
+    BOOST_CHECK(!f2.is_ready());
+    BOOST_CHECK(f3.is_ready());
+    BOOST_CHECK(!f4.is_ready());
+    BOOST_CHECK(!f5.is_ready());
+    BOOST_CHECK(f3.get()==42);
+}
+void test_wait_for_either_of_five_futures_4()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    boost::packaged_task<int> pt4(make_int_slowly);
+    boost::unique_future<int> f4(pt4.get_future());
+    boost::packaged_task<int> pt5(make_int_slowly);
+    boost::unique_future<int> f5(pt5.get_future());
+    
+    boost::thread(::cast_to_rval(pt4));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5);
+    
+    BOOST_CHECK(future==3);
+    BOOST_CHECK(!f1.is_ready());
+    BOOST_CHECK(!f2.is_ready());
+    BOOST_CHECK(!f3.is_ready());
+    BOOST_CHECK(f4.is_ready());
+    BOOST_CHECK(!f5.is_ready());
+    BOOST_CHECK(f4.get()==42);
+}
+void test_wait_for_either_of_five_futures_5()
+{
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> f1(pt.get_future());
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> f2(pt2.get_future());
+    boost::packaged_task<int> pt3(make_int_slowly);
+    boost::unique_future<int> f3(pt3.get_future());
+    boost::packaged_task<int> pt4(make_int_slowly);
+    boost::unique_future<int> f4(pt4.get_future());
+    boost::packaged_task<int> pt5(make_int_slowly);
+    boost::unique_future<int> f5(pt5.get_future());
+    
+    boost::thread(::cast_to_rval(pt5));
+    
+    unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5);
+    
+    BOOST_CHECK(future==4);
+    BOOST_CHECK(!f1.is_ready());
+    BOOST_CHECK(!f2.is_ready());
+    BOOST_CHECK(!f3.is_ready());
+    BOOST_CHECK(!f4.is_ready());
+    BOOST_CHECK(f5.is_ready());
+    BOOST_CHECK(f5.get()==42);
+}
+
+void test_wait_for_either_invokes_callbacks()
+{
+    callback_called=0;
+    boost::packaged_task<int> pt(make_int_slowly);
+    boost::unique_future<int> fi=pt.get_future();
+    boost::packaged_task<int> pt2(make_int_slowly);
+    boost::unique_future<int> fi2=pt2.get_future();
+    pt.set_wait_callback(wait_callback_for_task);
+
+    boost::thread(::cast_to_rval(pt));
+    
+    boost::wait_for_any(fi,fi2);
+    BOOST_CHECK(callback_called==1);
+    BOOST_CHECK(fi.get()==42);
+}
+
+void test_wait_for_any_from_range()
+{
+    unsigned const count=10;
+    for(unsigned i=0;i<count;++i)
+    {
+        boost::packaged_task<int> tasks[count];
+        boost::unique_future<int> futures[count];
+        for(unsigned j=0;j<count;++j)
+        {
+            tasks[j]=boost::packaged_task<int>(make_int_slowly);
+            futures[j]=tasks[j].get_future();
+        }
+        boost::thread(::cast_to_rval(tasks[i]));
+    
+        boost::unique_future<int>* const future=boost::wait_for_any(futures,futures+count);
+    
+        BOOST_CHECK(future==(futures+i));
+        for(unsigned j=0;j<count;++j)
+        {
+            if(j!=i)
+            {
+                BOOST_CHECK(!futures[j].is_ready());
+            }
+            else
+            {
+                BOOST_CHECK(futures[j].is_ready());
+            }
+        }
+        BOOST_CHECK(futures[i].get()==42);
+    }
+}
+
+void test_wait_for_all_from_range()
+{
+    unsigned const count=10;
+    boost::unique_future<int> futures[count];
+    for(unsigned j=0;j<count;++j)
+    {
+        boost::packaged_task<int> task(make_int_slowly);
+        futures[j]=task.get_future();
+        boost::thread(::cast_to_rval(task));
+    }
+    
+    boost::wait_for_all(futures,futures+count);
+    
+    for(unsigned j=0;j<count;++j)
+    {
+        BOOST_CHECK(futures[j].is_ready());
+    }
+}
+
+void test_wait_for_all_two_futures()
+{
+    unsigned const count=2;
+    boost::unique_future<int> futures[count];
+    for(unsigned j=0;j<count;++j)
+    {
+        boost::packaged_task<int> task(make_int_slowly);
+        futures[j]=task.get_future();
+        boost::thread(::cast_to_rval(task));
+    }
+    
+    boost::wait_for_all(futures[0],futures[1]);
+    
+    for(unsigned j=0;j<count;++j)
+    {
+        BOOST_CHECK(futures[j].is_ready());
+    }
+}
+
+void test_wait_for_all_three_futures()
+{
+    unsigned const count=3;
+    boost::unique_future<int> futures[count];
+    for(unsigned j=0;j<count;++j)
+    {
+        boost::packaged_task<int> task(make_int_slowly);
+        futures[j]=task.get_future();
+        boost::thread(::cast_to_rval(task));
+    }
+    
+    boost::wait_for_all(futures[0],futures[1],futures[2]);
+    
+    for(unsigned j=0;j<count;++j)
+    {
+        BOOST_CHECK(futures[j].is_ready());
+    }
+}
+
+void test_wait_for_all_four_futures()
+{
+    unsigned const count=4;
+    boost::unique_future<int> futures[count];
+    for(unsigned j=0;j<count;++j)
+    {
+        boost::packaged_task<int> task(make_int_slowly);
+        futures[j]=task.get_future();
+        boost::thread(::cast_to_rval(task));
+    }
+    
+    boost::wait_for_all(futures[0],futures[1],futures[2],futures[3]);
+    
+    for(unsigned j=0;j<count;++j)
+    {
+        BOOST_CHECK(futures[j].is_ready());
+    }
+}
+
+void test_wait_for_all_five_futures()
+{
+    unsigned const count=5;
+    boost::unique_future<int> futures[count];
+    for(unsigned j=0;j<count;++j)
+    {
+        boost::packaged_task<int> task(make_int_slowly);
+        futures[j]=task.get_future();
+        boost::thread(::cast_to_rval(task));
+    }
+    
+    boost::wait_for_all(futures[0],futures[1],futures[2],futures[3],futures[4]);
+    
+    for(unsigned j=0;j<count;++j)
+    {
+        BOOST_CHECK(futures[j].is_ready());
+    }
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
+{
+    boost::unit_test_framework::test_suite* test =
+        BOOST_TEST_SUITE("Boost.Threads: futures test suite");
+
+    test->add(BOOST_TEST_CASE(test_initial_state));
+    test->add(BOOST_TEST_CASE(test_waiting_future));
+    test->add(BOOST_TEST_CASE(test_cannot_get_future_twice));
+    test->add(BOOST_TEST_CASE(test_set_value_updates_future_state));
+    test->add(BOOST_TEST_CASE(test_set_value_can_be_retrieved));
+    test->add(BOOST_TEST_CASE(test_set_value_can_be_moved));
+    test->add(BOOST_TEST_CASE(test_store_value_from_thread));
+    test->add(BOOST_TEST_CASE(test_store_exception));
+    test->add(BOOST_TEST_CASE(test_future_from_packaged_task_is_waiting));
+    test->add(BOOST_TEST_CASE(test_invoking_a_packaged_task_populates_future));
+    test->add(BOOST_TEST_CASE(test_invoking_a_packaged_task_twice_throws));
+    test->add(BOOST_TEST_CASE(test_cannot_get_future_twice_from_task));
+    test->add(BOOST_TEST_CASE(test_task_stores_exception_if_function_throws));
+    test->add(BOOST_TEST_CASE(test_void_promise));
+    test->add(BOOST_TEST_CASE(test_reference_promise));
+    test->add(BOOST_TEST_CASE(test_task_returning_void));
+    test->add(BOOST_TEST_CASE(test_task_returning_reference));
+    test->add(BOOST_TEST_CASE(test_shared_future));
+    test->add(BOOST_TEST_CASE(test_copies_of_shared_future_become_ready_together));
+    test->add(BOOST_TEST_CASE(test_shared_future_can_be_move_assigned_from_unique_future));
+    test->add(BOOST_TEST_CASE(test_shared_future_void));
+    test->add(BOOST_TEST_CASE(test_shared_future_ref));
+    test->add(BOOST_TEST_CASE(test_can_get_a_second_future_from_a_moved_promise));
+    test->add(BOOST_TEST_CASE(test_can_get_a_second_future_from_a_moved_void_promise));
+    test->add(BOOST_TEST_CASE(test_unique_future_for_move_only_udt));
+    test->add(BOOST_TEST_CASE(test_unique_future_for_string));
+    test->add(BOOST_TEST_CASE(test_wait_callback));
+    test->add(BOOST_TEST_CASE(test_wait_callback_with_timed_wait));
+    test->add(BOOST_TEST_CASE(test_wait_callback_for_packaged_task));
+    test->add(BOOST_TEST_CASE(test_packaged_task_can_be_moved));
+    test->add(BOOST_TEST_CASE(test_destroying_a_promise_stores_broken_promise));
+    test->add(BOOST_TEST_CASE(test_destroying_a_packaged_task_stores_broken_promise));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_two_futures_1));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_two_futures_2));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_1));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_2));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_3));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_1));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_2));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_3));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_4));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_1));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_2));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_3));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_4));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_5));
+    test->add(BOOST_TEST_CASE(test_wait_for_either_invokes_callbacks));
+    test->add(BOOST_TEST_CASE(test_wait_for_any_from_range));
+    test->add(BOOST_TEST_CASE(test_wait_for_all_from_range));
+    test->add(BOOST_TEST_CASE(test_wait_for_all_two_futures));
+    test->add(BOOST_TEST_CASE(test_wait_for_all_three_futures));
+    test->add(BOOST_TEST_CASE(test_wait_for_all_four_futures));
+    test->add(BOOST_TEST_CASE(test_wait_for_all_five_futures));
+
+    return test;
+}