summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Boost/src/boost/thread/future.hpp')
-rw-r--r--3rdParty/Boost/src/boost/thread/future.hpp1243
1 files changed, 864 insertions, 379 deletions
diff --git a/3rdParty/Boost/src/boost/thread/future.hpp b/3rdParty/Boost/src/boost/thread/future.hpp
index a4b4343..6bf5cf6 100644
--- a/3rdParty/Boost/src/boost/thread/future.hpp
+++ b/3rdParty/Boost/src/boost/thread/future.hpp
@@ -1,4 +1,5 @@
-// (C) Copyright 2008-10 Anthony Williams
+// (C) Copyright 2008-10 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -6,6 +7,15 @@
#ifndef BOOST_THREAD_FUTURE_HPP
#define BOOST_THREAD_FUTURE_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+// boost::thread::future requires exception handling
+// due to boost::exception::exception_ptr dependency
+
+#ifndef BOOST_NO_EXCEPTIONS
+
+#include <boost/detail/scoped_enum_emulation.hpp>
#include <stdexcept>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/thread_time.hpp>
@@ -16,6 +26,8 @@
#include <boost/scoped_ptr.hpp>
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/remove_cv.hpp>
#include <boost/mpl/if.hpp>
#include <boost/config.hpp>
#include <boost/throw_exception.hpp>
@@ -28,59 +40,168 @@
#include <list>
#include <boost/next_prior.hpp>
#include <vector>
+#include <boost/system/error_code.hpp>
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#endif
+
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+#include <boost/thread/detail/memory.hpp>
+#endif
+
+#include <boost/utility/result_of.hpp>
+#include <boost/thread/thread.hpp>
+
+#if defined BOOST_THREAD_PROVIDES_FUTURE
+#define BOOST_THREAD_FUTURE future
+#else
+#define BOOST_THREAD_FUTURE unique_future
+#endif
+
namespace boost
{
- class future_uninitialized:
- public std::logic_error
+
+ //enum class future_errc
+ BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc)
+ {
+ broken_promise,
+ future_already_retrieved,
+ promise_already_satisfied,
+ no_state
+ }
+ BOOST_SCOPED_ENUM_DECLARE_END(future_errc)
+
+ namespace system
+ {
+ template <>
+ struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type {};
+
+ #ifdef BOOST_NO_CXX11_SCOPED_ENUMS
+ template <>
+ struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { };
+ #endif
+ }
+
+ //enum class launch
+ BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch)
+ {
+ async = 1,
+ deferred = 2,
+ any = async | deferred
+ }
+ BOOST_SCOPED_ENUM_DECLARE_END(launch)
+
+ //enum class future_status
+ BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status)
+ {
+ ready,
+ timeout,
+ deferred
+ }
+ BOOST_SCOPED_ENUM_DECLARE_END(future_status)
+
+ BOOST_THREAD_DECL
+ const system::error_category& future_category() BOOST_NOEXCEPT;
+
+ namespace system
+ {
+ inline
+ error_code
+ make_error_code(future_errc e) //BOOST_NOEXCEPT
+ {
+ return error_code(underlying_cast<int>(e), boost::future_category());
+ }
+
+ inline
+ error_condition
+ make_error_condition(future_errc e) //BOOST_NOEXCEPT
+ {
+ return error_condition(underlying_cast<int>(e), future_category());
+ }
+ }
+
+ class BOOST_SYMBOL_VISIBLE future_error
+ : public std::logic_error
+ {
+ system::error_code ec_;
+ public:
+ future_error(system::error_code ec)
+ : logic_error(ec.message()),
+ ec_(ec)
+ {
+ }
+
+ const system::error_code& code() const BOOST_NOEXCEPT
+ {
+ return ec_;
+ }
+ const char* what() const BOOST_THREAD_NOEXCEPT_OR_THROW
+ {
+ return code().message().c_str();
+ }
+
+ };
+
+ class BOOST_SYMBOL_VISIBLE future_uninitialized:
+ public future_error
{
public:
- future_uninitialized():
- std::logic_error("Future Uninitialized")
+ future_uninitialized() :
+ future_error(system::make_error_code(future_errc::no_state))
{}
};
- class broken_promise:
- public std::logic_error
+ class BOOST_SYMBOL_VISIBLE broken_promise:
+ public future_error
{
public:
broken_promise():
- std::logic_error("Broken promise")
+ future_error(system::make_error_code(future_errc::broken_promise))
{}
};
- class future_already_retrieved:
- public std::logic_error
+ class BOOST_SYMBOL_VISIBLE future_already_retrieved:
+ public future_error
{
public:
future_already_retrieved():
- std::logic_error("Future already retrieved")
+ future_error(system::make_error_code(future_errc::future_already_retrieved))
{}
};
- class promise_already_satisfied:
- public std::logic_error
+ class BOOST_SYMBOL_VISIBLE promise_already_satisfied:
+ public future_error
{
public:
promise_already_satisfied():
- std::logic_error("Promise already satisfied")
+ future_error(system::make_error_code(future_errc::promise_already_satisfied))
{}
};
- class task_already_started:
- public std::logic_error
+ class BOOST_SYMBOL_VISIBLE task_already_started:
+ public future_error
{
public:
task_already_started():
- std::logic_error("Task already started")
+ future_error(system::make_error_code(future_errc::promise_already_satisfied))
{}
};
- class task_moved:
- public std::logic_error
- {
- public:
- task_moved():
- std::logic_error("Task moved")
- {}
- };
+ class BOOST_SYMBOL_VISIBLE task_moved:
+ public future_error
+ {
+ public:
+ task_moved():
+ future_error(system::make_error_code(future_errc::no_state))
+ {}
+ };
+
+ class promise_moved:
+ public future_error
+ {
+ public:
+ promise_moved():
+ future_error(system::make_error_code(future_errc::no_state))
+ {}
+ };
namespace future_state
{
@@ -93,6 +214,7 @@ namespace boost
{
boost::exception_ptr exception;
bool done;
+ bool thread_was_interrupted;
boost::mutex mutex;
boost::condition_variable waiters;
typedef std::list<boost::condition_variable_any*> waiter_list;
@@ -100,7 +222,8 @@ namespace boost
boost::function<void()> callback;
future_object_base():
- done(false)
+ done(false),
+ thread_was_interrupted(false)
{}
virtual ~future_object_base()
{}
@@ -111,7 +234,7 @@ namespace boost
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);
@@ -132,7 +255,7 @@ namespace boost
struct relocker
{
boost::unique_lock<boost::mutex>& lock;
-
+
relocker(boost::unique_lock<boost::mutex>& lock_):
lock(lock_)
{
@@ -155,7 +278,7 @@ namespace boost
local_callback();
}
}
-
+
void wait(bool rethrow=true)
{
@@ -165,6 +288,10 @@ namespace boost
{
waiters.wait(lock);
}
+ if(rethrow && thread_was_interrupted)
+ {
+ throw boost::thread_interrupted();
+ }
if(rethrow && exception)
{
boost::rethrow_exception(exception);
@@ -185,7 +312,26 @@ namespace boost
}
return true;
}
-
+
+#ifdef BOOST_THREAD_USES_CHRONO
+
+ template <class Clock, class Duration>
+ future_status
+ wait_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ do_callback(lock);
+ while(!done)
+ {
+ cv_status const st=waiters.wait_until(lock,abs_time);
+ if(st==cv_status::timeout && !done)
+ {
+ return future_status::timeout;
+ }
+ }
+ return future_status::ready;
+ }
+#endif
void mark_exceptional_finish_internal(boost::exception_ptr const& e)
{
exception=e;
@@ -196,16 +342,21 @@ namespace boost
boost::lock_guard<boost::mutex> lock(mutex);
mark_exceptional_finish_internal(boost::current_exception());
}
-
+ void mark_interrupted_finish()
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ thread_was_interrupted=true;
+ mark_finished_internal();
+ }
bool has_value()
{
boost::lock_guard<boost::mutex> lock(mutex);
- return done && !exception;
+ return done && !(exception || thread_was_interrupted);
}
bool has_exception()
{
boost::lock_guard<boost::mutex> lock(mutex);
- return done && exception;
+ return done && (exception || thread_was_interrupted);
}
template<typename F,typename U>
@@ -213,7 +364,7 @@ namespace boost
{
callback=boost::bind(f,boost::ref(*u));
}
-
+
private:
future_object_base(future_object_base const&);
future_object_base& operator=(future_object_base const&);
@@ -223,25 +374,31 @@ namespace boost
struct future_traits
{
typedef boost::scoped_ptr<T> storage_type;
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_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;
+ typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
+ typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type;
+#elif defined BOOST_THREAD_USES_MOVE
+ typedef T& source_reference_type;
+ typedef typename boost::mpl::if_<boost::has_move_emulation_enabled<T>,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
+ typedef typename boost::mpl::if_<boost::has_move_emulation_enabled<T>,BOOST_THREAD_RV_REF(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;
+ typedef typename boost::mpl::if_<boost::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
+ typedef typename boost::mpl::if_<boost::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
#endif
+ typedef const T& shared_future_get_result_type;
+
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)));
+ storage.reset(new T(static_cast<rvalue_source_type>(t)));
}
static void cleanup(storage_type& storage)
@@ -249,7 +406,7 @@ namespace boost
storage.reset();
}
};
-
+
template<typename T>
struct future_traits<T&>
{
@@ -258,6 +415,7 @@ namespace boost
struct rvalue_source_type
{};
typedef T& move_dest_type;
+ typedef T& shared_future_get_result_type;
static void init(storage_type& storage,T& t)
{
@@ -275,6 +433,7 @@ namespace boost
{
typedef bool storage_type;
typedef void move_dest_type;
+ typedef void shared_future_get_result_type;
static void init(storage_type& storage)
{
@@ -296,7 +455,8 @@ namespace boost
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;
-
+ typedef typename future_traits<T>::shared_future_get_result_type shared_future_get_result_type;
+
storage_type result;
future_object():
@@ -308,6 +468,7 @@ namespace boost
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_));
@@ -319,10 +480,11 @@ namespace boost
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_);
+ mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_));
}
move_dest_type get()
@@ -331,6 +493,12 @@ namespace boost
return static_cast<move_dest_type>(*result);
}
+ shared_future_get_result_type get_sh()
+ {
+ wait();
+ return static_cast<shared_future_get_result_type>(*result);
+ }
+
future_state::state get_state()
{
boost::lock_guard<boost::mutex> guard(mutex);
@@ -353,6 +521,8 @@ namespace boost
struct future_object<void>:
detail::future_object_base
{
+ typedef void shared_future_get_result_type;
+
future_object()
{}
@@ -371,7 +541,10 @@ namespace boost
{
wait();
}
-
+ void get_sh()
+ {
+ wait();
+ }
future_state::state get_state()
{
boost::lock_guard<boost::mutex> guard(mutex);
@@ -384,74 +557,93 @@ namespace boost
return future_state::ready;
}
}
-
private:
future_object(future_object const&);
future_object& operator=(future_object const&);
};
+// template<typename T, typename Allocator>
+// struct future_object_alloc: public future_object<T>
+// {
+// typedef future_object<T> base;
+// Allocator alloc_;
+//
+// public:
+// explicit future_object_alloc(const Allocator& a)
+// : alloc_(a) {}
+//
+// };
class future_waiter
{
struct registered_waiter;
- typedef std::vector<registered_waiter>::size_type count_type;
-
+ typedef std::vector<int>::size_type count_type;
+
struct registered_waiter
{
- boost::shared_ptr<detail::future_object_base> future;
+ 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_,
+ registered_waiter(boost::shared_ptr<detail::future_object_base> const& a_future,
detail::future_object_base::waiter_list::iterator wait_iterator_,
count_type index_):
- future(future_),wait_iterator(wait_iterator_),index(index_)
+ future_(a_future),wait_iterator(wait_iterator_),index(index_)
{}
};
-
+
struct all_futures_lock
{
- count_type count;
+#ifdef _MANAGED
+ typedef std::ptrdiff_t count_type_portable;
+#else
+ typedef count_type count_type_portable;
+#endif
+ count_type_portable 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)
+ for(count_type_portable i=0;i<count;++i)
{
- locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex);
+#if defined __DECCXX || defined __SUNPRO_CC || defined __hpux
+ locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex).move();
+#else
+ locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex);
+#endif
}
}
-
+
void lock()
{
boost::lock(locks.get(),locks.get()+count);
}
-
+
void unlock()
{
- for(count_type i=0;i<count;++i)
+ for(count_type_portable 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)
+ if(f.future_)
{
- futures.push_back(registered_waiter(f.future,f.future->register_external_waiter(cv),future_count));
+ futures.push_back(registered_waiter(f.future_,f.future_->register_external_waiter(cv),future_count));
}
++future_count;
}
@@ -463,7 +655,7 @@ namespace boost
{
for(count_type i=0;i<futures.size();++i)
{
- if(futures[i].future->done)
+ if(futures[i].future_->done)
{
return futures[i].index;
}
@@ -471,21 +663,21 @@ namespace boost
cv.wait(lk);
}
}
-
+
~future_waiter()
{
for(count_type i=0;i<futures.size();++i)
{
- futures[i].future->remove_external_waiter(futures[i].wait_iterator);
+ futures[i].future_->remove_external_waiter(futures[i].wait_iterator);
}
}
-
+
};
-
+
}
template <typename R>
- class unique_future;
+ class BOOST_THREAD_FUTURE;
template <typename R>
class shared_future;
@@ -495,13 +687,13 @@ namespace boost
{
BOOST_STATIC_CONSTANT(bool, value=false);
};
-
+
template<typename T>
- struct is_future_type<unique_future<T> >
+ struct is_future_type<BOOST_THREAD_FUTURE<T> >
{
BOOST_STATIC_CONSTANT(bool, value=true);
};
-
+
template<typename T>
struct is_future_type<shared_future<T> >
{
@@ -531,7 +723,7 @@ namespace boost
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)
{
@@ -556,7 +748,7 @@ namespace boost
{
if(begin==end)
return end;
-
+
detail::future_waiter waiter;
for(Iterator current=begin;current!=end;++current)
{
@@ -583,7 +775,7 @@ namespace boost
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)
{
@@ -606,7 +798,7 @@ namespace boost
waiter.add(f5);
return waiter.wait();
}
-
+
template <typename R>
class promise;
@@ -614,14 +806,13 @@ namespace boost
class packaged_task;
template <typename R>
- class unique_future
+ class BOOST_THREAD_FUTURE
{
- unique_future(unique_future & rhs);// = delete;
- unique_future& operator=(unique_future& rhs);// = delete;
+ private:
typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
-
- future_ptr future;
+
+ future_ptr future_;
friend class shared_future<R>;
friend class promise<R>;
@@ -630,139 +821,151 @@ namespace boost
typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
- unique_future(future_ptr future_):
- future(future_)
+ BOOST_THREAD_FUTURE(future_ptr a_future):
+ future_(a_future)
{}
public:
+ BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
typedef future_state::state state;
- unique_future()
+ BOOST_THREAD_FUTURE()
{}
-
- ~unique_future()
+
+ ~BOOST_THREAD_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)
+ BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
+ future_(BOOST_THREAD_RV(other).future_)
{
- other->future.reset();
+ BOOST_THREAD_RV(other).future_.reset();
}
- unique_future& operator=(boost::detail::thread_move_t<unique_future> other)
+ BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
{
- future=other->future;
- other->future.reset();
+ future_=BOOST_THREAD_RV(other).future_;
+ BOOST_THREAD_RV(other).future_.reset();
return *this;
}
- operator boost::detail::thread_move_t<unique_future>()
+ shared_future<R> share()
{
- return boost::detail::thread_move_t<unique_future>(*this);
+ return shared_future<R>(::boost::move(*this));
}
-#endif
- void swap(unique_future& other)
+ void swap(BOOST_THREAD_FUTURE& other)
{
- future.swap(other.future);
+ future_.swap(other.future_);
}
// retrieving the value
move_dest_type get()
{
- if(!future)
+ if(!future_)
{
boost::throw_exception(future_uninitialized());
}
- return future->get();
+ return future_->get();
}
-
+
// functions to check state, and wait for ready
- state get_state() const
+ state get_state() const BOOST_NOEXCEPT
{
- if(!future)
+ if(!future_)
{
return future_state::uninitialized;
}
- return future->get_state();
+ return future_->get_state();
}
-
- bool is_ready() const
+ bool is_ready() const BOOST_NOEXCEPT
{
return get_state()==future_state::ready;
}
-
- bool has_exception() const
+
+ bool has_exception() const BOOST_NOEXCEPT
{
- return future && future->has_exception();
+ return future_ && future_->has_exception();
}
-
- bool has_value() const
+
+ bool has_value() const BOOST_NOEXCEPT
{
- return future && future->has_value();
+ return future_ && future_->has_value();
}
-
+
+ bool valid() const BOOST_NOEXCEPT
+ {
+ return future_ != 0;
+ }
+
+
void wait() const
{
- if(!future)
+ if(!future_)
{
boost::throw_exception(future_uninitialized());
}
- future->wait(false);
+ 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)
+ if(!future_)
{
boost::throw_exception(future_uninitialized());
}
- return future->timed_wait_until(abs_time);
+ return future_->timed_wait_until(abs_time);
}
-
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ future_status
+ wait_for(const chrono::duration<Rep, Period>& rel_time) const
+ {
+ return wait_until(chrono::steady_clock::now() + rel_time);
+
+ }
+ template <class Clock, class Duration>
+ future_status
+ wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
+ {
+ if(!future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ return future_->wait_until(abs_time);
+ }
+#endif
};
+ BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
+
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);
+ future_ptr future_;
friend class detail::future_waiter;
friend class promise<R>;
friend class packaged_task<R>;
-
- shared_future(future_ptr future_):
- future(future_)
+
+ shared_future(future_ptr a_future):
+ future_(a_future)
{}
public:
+ BOOST_THREAD_MOVABLE(shared_future)
+
shared_future(shared_future const& other):
- future(other.future)
+ future_(other.future_)
{}
typedef future_state::state state;
@@ -775,396 +978,405 @@ namespace boost
shared_future& operator=(shared_future const& other)
{
- future=other.future;
+ future_=other.future_;
return *this;
}
-#ifndef BOOST_NO_RVALUE_REFERENCES
- shared_future(shared_future && other)
+ shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT :
+ future_(BOOST_THREAD_RV(other).future_)
{
- future.swap(other.future);
+ BOOST_THREAD_RV(other).future_.reset();
}
- shared_future(unique_future<R> && other)
+ shared_future(BOOST_THREAD_RV_REF_BEG BOOST_THREAD_FUTURE<R> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT :
+ future_(BOOST_THREAD_RV(other).future_)
{
- future.swap(other.future);
+ BOOST_THREAD_RV(other).future_.reset();
}
- shared_future& operator=(shared_future && other)
+ shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT
{
- future.swap(other.future);
- other.future.reset();
+ future_.swap(BOOST_THREAD_RV(other).future_);
+ BOOST_THREAD_RV(other).future_.reset();
return *this;
}
- shared_future& operator=(unique_future<R> && other)
+ shared_future& operator=(BOOST_THREAD_RV_REF_BEG BOOST_THREAD_FUTURE<R> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT
{
- future.swap(other.future);
- other.future.reset();
+ future_.swap(BOOST_THREAD_RV(other).future_);
+ BOOST_THREAD_RV(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)
+ void swap(shared_future& other) BOOST_NOEXCEPT
{
- future.swap(other.future);
+ future_.swap(other.future_);
}
// retrieving the value
- R get()
+ typename detail::future_object<R>::shared_future_get_result_type get()
{
- if(!future)
+ if(!future_)
{
boost::throw_exception(future_uninitialized());
}
- return future->get();
+ return future_->get_sh();
}
-
+
// functions to check state, and wait for ready
- state get_state() const
+ state get_state() const BOOST_NOEXCEPT
{
- if(!future)
+ if(!future_)
{
return future_state::uninitialized;
}
- return future->get_state();
+ return future_->get_state();
}
-
- bool is_ready() const
+ bool valid() const BOOST_NOEXCEPT
+ {
+ return future_ != 0;
+ }
+
+ bool is_ready() const BOOST_NOEXCEPT
{
return get_state()==future_state::ready;
}
-
- bool has_exception() const
+
+ bool has_exception() const BOOST_NOEXCEPT
{
- return future && future->has_exception();
+ return future_ && future_->has_exception();
}
-
- bool has_value() const
+
+ bool has_value() const BOOST_NOEXCEPT
{
- return future && future->has_value();
+ return future_ && future_->has_value();
}
void wait() const
{
- if(!future)
+ if(!future_)
{
boost::throw_exception(future_uninitialized());
}
- future->wait(false);
+ 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)
+ if(!future_)
{
boost::throw_exception(future_uninitialized());
}
- return future->timed_wait_until(abs_time);
+ return future_->timed_wait_until(abs_time);
}
-
+#ifdef BOOST_THREAD_USES_CHRONO
+
+ template <class Rep, class Period>
+ future_status
+ wait_for(const chrono::duration<Rep, Period>& rel_time) const
+ {
+ return wait_until(chrono::steady_clock::now() + rel_time);
+
+ }
+ template <class Clock, class Duration>
+ future_status
+ wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
+ {
+ if(!future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ return future_->wait_until(abs_time);
+ }
+#endif
};
+ BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
+
template <typename R>
class promise
{
typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
-
- future_ptr future;
+
+ future_ptr future_;
bool future_obtained;
-
- promise(promise & rhs);// = delete;
- promise & operator=(promise & rhs);// = delete;
void lazy_init()
{
- if(!atomic_load(&future))
+#if defined BOOST_THREAD_PROMISE_LAZY
+ if(!atomic_load(&future_))
{
future_ptr blank;
- atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<R>));
+ atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R>));
}
+#endif
}
-
+
public:
-// template <class Allocator> explicit promise(Allocator a);
+ BOOST_THREAD_MOVABLE_ONLY(promise)
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+ template <class Allocator>
+ promise(boost::allocator_arg_t, Allocator a)
+ {
+ typedef typename Allocator::template rebind<detail::future_object<R> >::other A2;
+ A2 a2(a);
+ typedef thread_detail::allocator_destructor<A2> D;
+ future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<R>(), D(a2, 1) );
+ future_obtained = false;
+ }
+#endif
promise():
- future(),future_obtained(false)
+#if defined BOOST_THREAD_PROMISE_LAZY
+ future_(),
+#else
+ future_(new detail::future_object<R>()),
+#endif
+ future_obtained(false)
{}
-
+
~promise()
{
- if(future)
+ if(future_)
{
- boost::lock_guard<boost::mutex> lock(future->mutex);
+ boost::lock_guard<boost::mutex> lock(future_->mutex);
- if(!future->done)
+ if(!future_->done)
{
- future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
}
}
}
// Assignment
-#ifndef BOOST_NO_RVALUE_REFERENCES
- promise(promise && rhs):
- future_obtained(rhs.future_obtained)
+ promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
+ future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
{
- future.swap(rhs.future);
- rhs.future_obtained=false;
+ BOOST_THREAD_RV(rhs).future_.reset();
+ BOOST_THREAD_RV(rhs).future_obtained=false;
}
- promise & operator=(promise&& rhs)
+ promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
{
- 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;
+ future_=BOOST_THREAD_RV(rhs).future_;
+ future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
+ BOOST_THREAD_RV(rhs).future_.reset();
+ BOOST_THREAD_RV(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);
+ future_.swap(other.future_);
std::swap(future_obtained,other.future_obtained);
}
// Result retrieval
- unique_future<R> get_future()
+ BOOST_THREAD_FUTURE<R> get_future()
{
lazy_init();
- if(future_obtained)
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ if (future_obtained)
{
boost::throw_exception(future_already_retrieved());
}
future_obtained=true;
- return unique_future<R>(future);
+ return BOOST_THREAD_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::lock_guard<boost::mutex> lock(future_->mutex);
+ if(future_->done)
{
boost::throw_exception(promise_already_satisfied());
}
- future->mark_finished_with_result_internal(r);
+ 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::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));
+ 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::lock_guard<boost::mutex> lock(future_->mutex);
+ if(future_->done)
{
boost::throw_exception(promise_already_satisfied());
}
- future->mark_exceptional_finish_internal(p);
+ future_->mark_exceptional_finish_internal(p);
}
+ // setting the result with deferred notification
+ //void set_value_at_thread_exit(const R& r); // NOT YET IMPLEMENTED
+ //void set_value_at_thread_exit(see below); // NOT YET IMPLEMENTED
+ //void set_exception_at_thread_exit(exception_ptr p); // NOT YET IMPLEMENTED
+
template<typename F>
void set_wait_callback(F f)
{
lazy_init();
- future->set_wait_callback(f,this);
+ future_->set_wait_callback(f,this);
}
-
+
};
template <>
class promise<void>
{
typedef boost::shared_ptr<detail::future_object<void> > future_ptr;
-
- future_ptr future;
+
+ future_ptr future_;
bool future_obtained;
-
- promise(promise & rhs);// = delete;
- promise & operator=(promise & rhs);// = delete;
void lazy_init()
{
- if(!atomic_load(&future))
+#if defined BOOST_THREAD_PROMISE_LAZY
+ if(!atomic_load(&future_))
{
future_ptr blank;
- atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<void>));
+ atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<void>));
}
+#endif
}
public:
-// template <class Allocator> explicit promise(Allocator a);
+ BOOST_THREAD_MOVABLE_ONLY(promise)
+
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+ template <class Allocator>
+ promise(boost::allocator_arg_t, Allocator a)
+ {
+ typedef typename Allocator::template rebind<detail::future_object<void> >::other A2;
+ A2 a2(a);
+ typedef thread_detail::allocator_destructor<A2> D;
+ future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<void>(), D(a2, 1) );
+ future_obtained = false;
+ }
+#endif
promise():
- future(),future_obtained(false)
+#if defined BOOST_THREAD_PROMISE_LAZY
+ future_(),
+#else
+ future_(new detail::future_object<void>),
+#endif
+ future_obtained(false)
{}
-
+
~promise()
{
- if(future)
+ if(future_)
{
- boost::lock_guard<boost::mutex> lock(future->mutex);
+ boost::lock_guard<boost::mutex> lock(future_->mutex);
- if(!future->done)
+ if(!future_->done)
{
- future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ 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)
+ promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
+ future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
{
- 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;
+ // we need to release the future as shared_ptr doesn't implements move semantics
+ BOOST_THREAD_RV(rhs).future_.reset();
+ BOOST_THREAD_RV(rhs).future_obtained=false;
}
- promise & operator=(boost::detail::thread_move_t<promise> rhs)
+
+ promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
{
- future=rhs->future;
- future_obtained=rhs->future_obtained;
- rhs->future.reset();
- rhs->future_obtained=false;
+ future_=BOOST_THREAD_RV(rhs).future_;
+ future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
+ BOOST_THREAD_RV(rhs).future_.reset();
+ BOOST_THREAD_RV(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);
+ future_.swap(other.future_);
std::swap(future_obtained,other.future_obtained);
}
// Result retrieval
- unique_future<void> get_future()
+ BOOST_THREAD_FUTURE<void> get_future()
{
lazy_init();
-
+
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
if(future_obtained)
{
boost::throw_exception(future_already_retrieved());
}
future_obtained=true;
- return unique_future<void>(future);
+ return BOOST_THREAD_FUTURE<void>(future_);
}
void set_value()
{
lazy_init();
- boost::lock_guard<boost::mutex> lock(future->mutex);
- if(future->done)
+ boost::lock_guard<boost::mutex> lock(future_->mutex);
+ if(future_->done)
{
boost::throw_exception(promise_already_satisfied());
}
- future->mark_finished_with_result_internal();
+ 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::lock_guard<boost::mutex> lock(future_->mutex);
+ if(future_->done)
{
boost::throw_exception(promise_already_satisfied());
}
- future->mark_exceptional_finish_internal(p);
+ future_->mark_exceptional_finish_internal(p);
}
template<typename F>
void set_wait_callback(F f)
{
lazy_init();
- future->set_wait_callback(f,this);
+ future_->set_wait_callback(f,this);
}
-
+
};
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+ namespace container
+ {
+ template <class R, class Alloc>
+ struct uses_allocator<promise<R> , Alloc> : true_type
+ {
+ };
+ }
+#endif
+
+ BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
+
namespace detail
{
template<typename R>
@@ -1177,6 +1389,10 @@ namespace boost
started(false)
{}
+ void reset()
+ {
+ started=false;
+ }
void run()
{
{
@@ -1199,30 +1415,44 @@ namespace boost
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>
{
+ private:
+ task_object(task_object&);
+ public:
F f;
task_object(F const& f_):
f(f_)
{}
- task_object(boost::detail::thread_move_t<F> f_):
- f(f_)
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ task_object(BOOST_THREAD_RV_REF(F) f_):
+ f(boost::forward<F>(f_))
+ {}
+#else
+ task_object(BOOST_THREAD_RV_REF(F) f_):
+ f(boost::move(f_))
{}
-
+#endif
void do_run()
{
try
{
this->mark_finished_with_result(f());
}
+ catch(thread_interrupted& )
+ {
+ this->mark_interrupted_finish();
+ }
catch(...)
{
this->mark_exceptional_finish();
@@ -1230,18 +1460,55 @@ namespace boost
}
};
+ template<typename R>
+ struct task_object<R,R (*)()>:
+ task_base<R>
+ {
+ private:
+ task_object(task_object&);
+ public:
+ R (*f)();
+ task_object(R (*f_)()):
+ f(f_)
+ {}
+ void do_run()
+ {
+ try
+ {
+ this->mark_finished_with_result(f());
+ }
+ catch(thread_interrupted& )
+ {
+ this->mark_interrupted_finish();
+ }
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+ };
+
template<typename F>
struct task_object<void,F>:
task_base<void>
{
+ private:
+ task_object(task_object&);
+ public:
F f;
task_object(F const& f_):
f(f_)
{}
- task_object(boost::detail::thread_move_t<F> f_):
- f(f_)
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ task_object(BOOST_THREAD_RV_REF(F) f_):
+ f(boost::forward<F>(f_))
{}
-
+#else
+ task_object(BOOST_THREAD_RV_REF(F) f_):
+ f(boost::move(f_))
+ {}
+#endif
+
void do_run()
{
try
@@ -1249,6 +1516,39 @@ namespace boost
f();
this->mark_finished_with_result();
}
+ catch(thread_interrupted& )
+ {
+ this->mark_interrupted_finish();
+ }
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+ };
+
+ template<>
+ struct task_object<void,void (*)()>:
+ task_base<void>
+ {
+ private:
+ task_object(task_object&);
+ public:
+ void (*f)();
+ task_object(void (*f_)()):
+ f(f_)
+ {}
+ void do_run()
+ {
+ try
+ {
+ f();
+ this->mark_finished_with_result();
+ }
+ catch(thread_interrupted& )
+ {
+ this->mark_interrupted_finish();
+ }
catch(...)
{
this->mark_exceptional_finish();
@@ -1257,41 +1557,92 @@ namespace boost
};
}
-
template<typename R>
class packaged_task
{
+ typedef boost::shared_ptr<detail::task_base<R> > task_ptr;
boost::shared_ptr<detail::task_base<R> > task;
bool future_obtained;
- packaged_task(packaged_task&);// = delete;
- packaged_task& operator=(packaged_task&);// = delete;
-
public:
+ typedef R result_type;
+ BOOST_THREAD_MOVABLE_ONLY(packaged_task)
+
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)
{}
-
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class F>
+ explicit packaged_task(BOOST_THREAD_RV_REF(F) f):
+ task(new detail::task_object<R,
+ typename remove_cv<typename remove_reference<F>::type>::type
+ >(boost::forward<F>(f))),future_obtained(false)
+ {}
+#else
template <class F>
- explicit packaged_task(boost::detail::thread_move_t<F> f):
+ explicit packaged_task(F const& f):
task(new detail::task_object<R,F>(f)),future_obtained(false)
{}
+ template <class F>
+ explicit packaged_task(BOOST_THREAD_RV_REF(F) f):
+ task(new detail::task_object<R,F>(boost::move(f))),future_obtained(false)
+ {}
+#endif
-// 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);
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+ template <class Allocator>
+ packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
+ {
+ typedef R(*FR)();
+ typedef typename Allocator::template rebind<detail::task_object<R,FR> >::other A2;
+ A2 a2(a);
+ typedef thread_detail::allocator_destructor<A2> D;
+ task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(f), D(a2, 1) );
+ future_obtained = false;
+ }
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class F, class Allocator>
+ packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
+ {
+ typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
+ typedef typename Allocator::template rebind<detail::task_object<R,FR> >::other A2;
+ A2 a2(a);
+ typedef thread_detail::allocator_destructor<A2> D;
+
+ task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(boost::forward<F>(f)), D(a2, 1) );
+ future_obtained = false;
+ }
+#else
+ template <class F, class Allocator>
+ packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
+ {
+ typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2;
+ A2 a2(a);
+ typedef thread_detail::allocator_destructor<A2> D;
+
+ task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(f), D(a2, 1) );
+ future_obtained = false;
+ }
+ template <class F, class Allocator>
+ packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
+ {
+ typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2;
+ A2 a2(a);
+ typedef thread_detail::allocator_destructor<A2> D;
+
+ task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(boost::move(f)), D(a2, 1) );
+ future_obtained = false;
+ }
+#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
+#endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
~packaged_task()
{
@@ -1302,46 +1653,39 @@ namespace boost
}
// assignment
-#ifndef BOOST_NO_RVALUE_REFERENCES
- packaged_task(packaged_task&& other):
- future_obtained(other.future_obtained)
+ packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT :
+ future_obtained(BOOST_THREAD_RV(other).future_obtained)
{
- task.swap(other.task);
- other.future_obtained=false;
+ task.swap(BOOST_THREAD_RV(other).task);
+ BOOST_THREAD_RV(other).future_obtained=false;
}
- packaged_task& operator=(packaged_task&& other)
+ packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
{
- packaged_task temp(static_cast<packaged_task&&>(other));
+ packaged_task temp(static_cast<BOOST_THREAD_RV_REF(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>()
+
+ void reset()
{
- return boost::detail::thread_move_t<packaged_task>(*this);
+ if (!valid())
+ throw future_error(system::make_error_code(future_errc::no_state));
+ task->reset();
+ future_obtained=false;
}
-#endif
- void swap(packaged_task& other)
+ void swap(packaged_task& other) BOOST_NOEXCEPT
{
task.swap(other.task);
std::swap(future_obtained,other.future_obtained);
}
+ bool valid() const BOOST_NOEXCEPT
+ {
+ return task.get()!=0;
+ }
// result retrieval
- unique_future<R> get_future()
+ BOOST_THREAD_FUTURE<R> get_future()
{
if(!task)
{
@@ -1350,14 +1694,16 @@ namespace boost
else if(!future_obtained)
{
future_obtained=true;
- return unique_future<R>(task);
+ return BOOST_THREAD_FUTURE<R>(task);
}
else
{
boost::throw_exception(future_already_retrieved());
}
+ return BOOST_THREAD_FUTURE<R>();
+
}
-
+
// execution
void operator()()
@@ -1374,10 +1720,149 @@ namespace boost
{
task->set_wait_callback(f,this);
}
-
+
};
-}
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+ namespace container
+ {
+ template <class R, class Alloc>
+ struct uses_allocator<packaged_task<R>, Alloc>
+ : public true_type {};
+ }
+#endif
+
+ BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
+
+
+ template <class R>
+ BOOST_THREAD_FUTURE<R>
+ async(launch policy, R(*f)())
+ {
+ if (int(policy) & int(launch::async))
+ {
+ packaged_task<R> pt( f );
+
+ BOOST_THREAD_FUTURE<R> ret = pt.get_future();
+ boost::thread( boost::move(pt) ).detach();
+ return ::boost::move(ret);
+ }
+ else if (int(policy) & int(launch::deferred))
+ {
+ packaged_task<R> pt( f );
+ BOOST_THREAD_FUTURE<R> ret = pt.get_future();
+ return ::boost::move(ret);
+ } else {
+ BOOST_THREAD_FUTURE<R> ret;
+ return ::boost::move(ret);
+ }
+ }
+
+ template <class R>
+ BOOST_THREAD_FUTURE<R>
+ async(R(*f)())
+ {
+ return async(launch::any, f);
+ }
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class F>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
+ async(launch policy, BOOST_THREAD_FWD_REF(F) f)
+ {
+ typedef typename boost::result_of<typename decay<F>::type()>::type R;
+ if (int(policy) & int(launch::async))
+ {
+ packaged_task<R> pt( boost::forward<F>(f) );
+
+ BOOST_THREAD_FUTURE<R> ret = pt.get_future();
+ boost::thread( boost::move(pt) ).detach();
+ return ::boost::move(ret);
+ }
+ else if (int(policy) & int(launch::deferred))
+ {
+ packaged_task<R> pt( boost::forward<F>(f) );
+
+ BOOST_THREAD_FUTURE<R> ret = pt.get_future();
+ return ::boost::move(ret);
+ } else {
+ BOOST_THREAD_FUTURE<R> ret;
+ return ::boost::move(ret);
+ }
+ }
+ template <class F>
+ BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
+ async(BOOST_THREAD_RV_REF(F) f)
+ {
+ return async(launch::any, boost::forward<F>(f));
+ }
+#else
+
+// template <class F>
+// BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
+// async(launch policy, F const& f)
+// {
+// typedef typename boost::result_of<typename decay<F>::type()>::type R;
+// if (int(policy) & int(launch::async))
+// {
+// packaged_task<R> pt( f );
+//
+// BOOST_THREAD_FUTURE<R> ret = pt.get_future();
+// boost::thread( boost::move(pt) ).detach();
+// return ::boost::move(ret);
+// }
+// else if (int(policy) & int(launch::deferred))
+// {
+// packaged_task<R> pt( f );
+//
+// BOOST_THREAD_FUTURE<R> ret = pt.get_future();
+// return ::boost::move(ret);
+// } else {
+// BOOST_THREAD_FUTURE<R> ret;
+// return ::boost::move(ret);
+// }
+// }
+// template <class F>
+// BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
+// async(F const& f)
+// {
+// return async(launch::any, f);
+// }
+
+ template <class F>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
+ async(launch policy, BOOST_THREAD_FWD_REF(F) f)
+ {
+ typedef typename boost::result_of<typename decay<F>::type()>::type R;
+ if (int(policy) & int(launch::async))
+ {
+ packaged_task<R> pt( boost::forward<F>(f) );
+
+ BOOST_THREAD_FUTURE<R> ret = pt.get_future();
+ boost::thread( boost::move(pt) ).detach();
+ return ::boost::move(ret);
+ }
+ else if (int(policy) & int(launch::deferred))
+ {
+ packaged_task<R> pt( boost::forward<F>(f) );
+
+ BOOST_THREAD_FUTURE<R> ret = pt.get_future();
+ return ::boost::move(ret);
+ } else {
+ BOOST_THREAD_FUTURE<R> ret;
+ return ::boost::move(ret);
+ }
+ }
+ template <class F>
+ BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
+ async(BOOST_THREAD_FWD_REF(F) f)
+ {
+ return async(launch::any, boost::forward<F>(f));
+ }
#endif
+
+}
+
+#endif // BOOST_NO_EXCEPTION
+#endif // header