diff options
author | Remko Tronçon <git@el-tramo.be> | 2010-04-11 18:19:17 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2010-04-11 19:20:07 (GMT) |
commit | 857e44c156a1dbefcb49bb5792c4384cebd8762a (patch) | |
tree | 11947fb81ad9c502627f1b2bb8f090fb8d53c107 /3rdParty/Boost/src/boost/thread/future.hpp | |
parent | 77d4eb7588e113beaa03f3347523b26adefdeb06 (diff) | |
download | swift-contrib-857e44c156a1dbefcb49bb5792c4384cebd8762a.zip swift-contrib-857e44c156a1dbefcb49bb5792c4384cebd8762a.tar.bz2 |
Updated Boost to 1.42.
Diffstat (limited to '3rdParty/Boost/src/boost/thread/future.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/thread/future.hpp | 1364 |
1 files changed, 1364 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/thread/future.hpp b/3rdParty/Boost/src/boost/thread/future.hpp new file mode 100644 index 0000000..3d694eb --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/future.hpp @@ -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 |