/Src/Dependencies/Boost/boost/thread/future.hpp
http://hadesmem.googlecode.com/ · C++ Header · 1383 lines · 1166 code · 190 blank · 27 comment · 63 complexity · f96b20aff35d05ba065aca7abae43f40 MD5 · raw file
- // (C) Copyright 2008-10 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/thread/mutex.hpp>
- #include <boost/thread/condition_variable.hpp>
- #include <boost/exception_ptr.hpp>
- #include <boost/shared_ptr.hpp>
- #include <boost/scoped_ptr.hpp>
- #include <boost/type_traits/is_fundamental.hpp>
- #include <boost/type_traits/is_convertible.hpp>
- #include <boost/mpl/if.hpp>
- #include <boost/config.hpp>
- #include <boost/throw_exception.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();
- }
- private:
- relocker& operator=(relocker const&);
- };
- 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;
- #ifndef BOOST_NO_RVALUE_REFERENCES
- 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 static_cast<move_dest_type>(*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;
- typedef std::vector<registered_waiter>::size_type count_type;
-
- struct registered_waiter
- {
- boost::shared_ptr<detail::future_object_base> future;
- detail::future_object_base::waiter_list::iterator wait_iterator;
- count_type index;
- registered_waiter(boost::shared_ptr<detail::future_object_base> const& future_,
- detail::future_object_base::waiter_list::iterator wait_iterator_,
- count_type index_):
- future(future_),wait_iterator(wait_iterator_),index(index_)
- {}
- };
-
- struct all_futures_lock
- {
- count_type 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(count_type 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(count_type i=0;i<count;++i)
- {
- locks[i].unlock();
- }
- }
- };
-
- boost::condition_variable_any cv;
- std::vector<registered_waiter> futures;
- count_type 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;
- }
- count_type wait()
- {
- all_futures_lock lk(futures);
- for(;;)
- {
- for(count_type i=0;i<futures.size();++i)
- {
- if(futures[i].future->done)
- {
- return futures[i].index;
- }
- }
- cv.wait(lk);
- }
- }
-
- ~future_waiter()
- {
- for(count_type 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)
- {
- if(begin==end)
- return 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()
- {}
- #ifndef BOOST_NO_RVALUE_REFERENCES
- 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)
- {
- boost::throw_exception(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)
- {
- boost::throw_exception(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)
- {
- boost::throw_exception(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;
- }
- #ifndef BOOST_NO_RVALUE_REFERENCES
- 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)
- {
- boost::throw_exception(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)
- {
- boost::throw_exception(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)
- {
- boost::throw_exception(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(!atomic_load(&future))
- {
- future_ptr blank;
- atomic_compare_exchange(&future,&blank,future_ptr(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
- #ifndef BOOST_NO_RVALUE_REFERENCES
- promise(promise && rhs):
- future_obtained(rhs.future_obtained)
- {
- future.swap(rhs.future);
- rhs.future_obtained=false;
- }
- promise & operator=(promise&& rhs)
- {
- future.swap(rhs.future);
- future_obtained=rhs.future_obtained;
- rhs.future.reset();
- rhs.future_obtained=false;
- return *this;
- }
- #else
- promise(boost::detail::thread_move_t<promise> rhs):
- future(rhs->future),future_obtained(rhs->future_obtained)
- {
- rhs->future.reset();
- rhs->future_obtained=false;
- }
- promise & operator=(boost::detail::thread_move_t<promise> rhs)
- {
- future=rhs->future;
- future_obtained=rhs->future_obtained;
- rhs->future.reset();
- rhs->future_obtained=false;
- 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)
- {
- boost::throw_exception(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)
- {
- boost::throw_exception(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)
- {
- boost::throw_exception(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)
- {
- boost::throw_exception(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(!atomic_load(&future))
- {
- future_ptr blank;
- atomic_compare_exchange(&future,&blank,future_ptr(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
- #ifndef BOOST_NO_RVALUE_REFERENCES
- promise(promise && rhs):
- future_obtained(rhs.future_obtained)
- {
- future.swap(rhs.future);
- rhs.future_obtained=false;
- }
- promise & operator=(promise&& rhs)
- {
- future.swap(rhs.future);
- future_obtained=rhs.future_obtained;
- rhs.future.reset();
- rhs.future_obtained=false;
- return *this;
- }
- #else
- promise(boost::detail::thread_move_t<promise> rhs):
- future(rhs->future),future_obtained(rhs->future_obtained)
- {
- rhs->future.reset();
- rhs->future_obtained=false;
- }
- promise & operator=(boost::detail::thread_move_t<promise> rhs)
- {
- future=rhs->future;
- future_obtained=rhs->future_obtained;
- rhs->future.reset();
- rhs->future_obtained=false;
- 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)
- {
- boost::throw_exception(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)
- {
- boost::throw_exception(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)
- {
- boost::throw_exception(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)
- {
- boost::throw_exception(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
- #ifndef BOOST_NO_RVALUE_REFERENCES
- 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)
- {
- boost::throw_exception(task_moved());
- }
- else if(!future_obtained)
- {
- future_obtained=true;
- return unique_future<R>(task);
- }
- else
- {
- boost::throw_exception(future_already_retrieved());
- }
- }
-
- // execution
- void operator()()
- {
- if(!task)
- {
- boost::throw_exception(task_moved());
- }
- task->run();
- }
- template<typename F>
- void set_wait_callback(F f)
- {
- task->set_wait_callback(f,this);
- }
-
- };
- }
- #endif