|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r56772 - sandbox/async/boost
From: vicente.botet_at_[hidden]
Date: 2009-10-13 03:14:12
Author: viboes
Date: 2009-10-13 03:14:12 EDT (Tue, 13 Oct 2009)
New Revision: 56772
URL: http://svn.boost.org/trac/boost/changeset/56772
Log:
TBoost.Async:
* Added futures library
Added:
sandbox/async/boost/future.hpp (contents, props changed)
Added: sandbox/async/boost/future.hpp
==============================================================================
--- (empty file)
+++ sandbox/async/boost/future.hpp 2009-10-13 03:14:12 EDT (Tue, 13 Oct 2009)
@@ -0,0 +1,1418 @@
+// (C) Copyright 2008 Anthony Williams
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/futures/future.hpp>
+
+#if 0
+#ifndef N2561_FUTURE_HPP
+#define N2561_FUTURE_HPP
+#include <stdexcept>
+#include <boost/exception.hpp>
+#include <boost/thread.hpp>
+#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>
+
+#define CATCH_ENABLE_CURRENT_EXCEPTION( Exception) \
+catch ( Exception const& e) \
+{ throw boost::enable_current_exception( e); }
+
+namespace jss
+{
+ 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(jss::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
+ {
+ try
+ { this->mark_finished_with_result(f()); }
+ CATCH_ENABLE_CURRENT_EXCEPTION( boost::thread_interrupted)
+ CATCH_ENABLE_CURRENT_EXCEPTION( boost::exception)
+
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::domain_error)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::invalid_argument)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::length_error)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::out_of_range)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::logic_error)
+
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::overflow_error)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::range_error)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::underflow_error)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::runtime_error)
+
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::bad_alloc)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::bad_cast)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::bad_typeid)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::bad_exception)
+
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::ios_base::failure)
+ }
+ 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
+ {
+ try
+ {
+ f();
+ this->mark_finished_with_result();
+ }
+ CATCH_ENABLE_CURRENT_EXCEPTION( boost::thread_interrupted)
+ CATCH_ENABLE_CURRENT_EXCEPTION( boost::exception)
+
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::domain_error)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::invalid_argument)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::length_error)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::out_of_range)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::logic_error)
+
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::overflow_error)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::range_error)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::underflow_error)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::runtime_error)
+
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::bad_alloc)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::bad_cast)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::bad_typeid)
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::bad_exception)
+
+ CATCH_ENABLE_CURRENT_EXCEPTION( std::ios_base::failure)
+ }
+ 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);
+ }
+
+ };
+
+}
+
+#undef CATCH_ENABLE_CURRENT_EXCEPTION
+
+#endif
+#endif
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk