|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r84719 - in trunk: boost/thread boost/thread/detail libs/thread/doc libs/thread/example libs/thread/test libs/thread/test/sync/futures/future
From: vicente.botet_at_[hidden]
Date: 2013-06-09 17:41:00
Author: viboes
Date: 2013-06-09 17:41:00 EDT (Sun, 09 Jun 2013)
New Revision: 84719
URL: http://svn.boost.org/trac/boost/changeset/84719
Log:
Thread: Added future::unwrap()/get_or()/fallback_to().
Added:
trunk/libs/thread/example/future_fallback_to.cpp (contents, props changed)
trunk/libs/thread/example/future_unwrap.cpp (contents, props changed)
trunk/libs/thread/test/sync/futures/future/get_or_pass.cpp (contents, props changed)
Text files modified:
trunk/boost/thread/detail/config.hpp | 5
trunk/boost/thread/future.hpp | 422 +++++++++++++++++++++++++++++++++------
trunk/libs/thread/doc/future_ref.qbk | 234 ++++++++++++++++-----
trunk/libs/thread/doc/futures.qbk | 10
trunk/libs/thread/example/future_fallback_to.cpp | 78 +++++++
trunk/libs/thread/example/future_unwrap.cpp | 59 +++++
trunk/libs/thread/test/Jamfile.v2 | 5
trunk/libs/thread/test/sync/futures/future/get_or_pass.cpp | 182 +++++++++++++++++
8 files changed, 856 insertions(+), 139 deletions(-)
Modified: trunk/boost/thread/detail/config.hpp
==============================================================================
--- trunk/boost/thread/detail/config.hpp Sun Jun 9 17:29:17 2013 (r84718)
+++ trunk/boost/thread/detail/config.hpp 2013-06-09 17:41:00 EDT (Sun, 09 Jun 2013) (r84719)
@@ -264,6 +264,11 @@
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#endif
+#if ! defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_UNWRAP
+#define BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+#endif
+
// FUTURE_INVALID_AFTER_GET
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET \
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET
Modified: trunk/boost/thread/future.hpp
==============================================================================
--- trunk/boost/thread/future.hpp Sun Jun 9 17:29:17 2013 (r84718)
+++ trunk/boost/thread/future.hpp 2013-06-09 17:41:00 EDT (Sun, 09 Jun 2013) (r84719)
@@ -32,6 +32,7 @@
#include <boost/thread/detail/is_convertible.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/is_void.hpp>
#include <boost/mpl/if.hpp>
#include <boost/config.hpp>
#include <boost/throw_exception.hpp>
@@ -646,13 +647,13 @@
#endif
}
- move_dest_type get()
+ virtual move_dest_type get()
{
wait();
return boost::move(*result);
}
- shared_future_get_result_type get_sh()
+ virtual shared_future_get_result_type get_sh()
{
wait();
return *result;
@@ -722,13 +723,13 @@
mark_finished_with_result_internal(result_, lock);
}
- T& get()
+ virtual T& get()
{
wait();
return *result;
}
- T& get_sh()
+ virtual T& get_sh()
{
wait();
return *result;
@@ -770,12 +771,12 @@
mark_finished_with_result_internal(lock);
}
- void get()
+ virtual void get()
{
this->wait();
}
- void get_sh()
+ virtual void get_sh()
{
wait();
}
@@ -1122,18 +1123,21 @@
struct is_future_type
{
BOOST_STATIC_CONSTANT(bool, value=false);
+ typedef void type;
};
template<typename T>
struct is_future_type<BOOST_THREAD_FUTURE<T> >
{
BOOST_STATIC_CONSTANT(bool, value=true);
+ typedef T type;
};
template<typename T>
struct is_future_type<shared_future<T> >
{
BOOST_STATIC_CONSTANT(bool, value=true);
+ typedef T type;
};
template<typename Iterator>
@@ -1254,6 +1258,7 @@
class basic_future : public base_future
{
protected:
+ public:
typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
@@ -1401,9 +1406,11 @@
make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ template<typename F, typename Rp>
+ struct future_unwrap_shared_state;
template <class F, class Rp>
- typename BOOST_THREAD_FUTURE<Rp>::value_type
- make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_FUTURE<Rp>& f);
+ inline BOOST_THREAD_FUTURE<Rp>
+ make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, F& f);
#endif
}
@@ -1430,6 +1437,13 @@
friend BOOST_THREAD_FUTURE<Rp>
detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
#endif
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ template<typename F, typename Rp>
+ friend struct detail::future_unwrap_shared_state;
+ template <class F, class Rp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, F& f);
+#endif
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
template <class> friend class packaged_task; // todo check if this works in windows
#else
@@ -1501,14 +1515,53 @@
{
boost::throw_exception(future_uninitialized());
}
-#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
future_ptr fut_=this->future_;
+#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
this->future_.reset();
+#endif
return fut_->get();
+ }
-#else
- return this->future_->get();
+ template <typename R2>
+ typename disable_if< is_void<R2>, move_dest_type>::type
+ get_or(BOOST_THREAD_RV_REF(R2) v)
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ this->future_->wait(false);
+ future_ptr fut_=this->future_;
+#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ this->future_.reset();
#endif
+ if (fut_->has_value()) {
+ return fut_->get();
+ }
+ else {
+ return boost::move(v);
+ }
+ }
+
+ template <typename R2>
+ typename disable_if< is_void<R2>, move_dest_type>::type
+ get_or(R2 const& v)
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ this->future_->wait(false);
+ future_ptr fut_=this->future_;
+#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ this->future_.reset();
+#endif
+ if (fut_->has_value()) {
+ return fut_->get();
+ }
+ else {
+ return v;
+ }
}
@@ -1529,20 +1582,197 @@
template<typename F>
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE&)>::type>
then(launch policy, BOOST_THREAD_FWD_REF(F) func);
+
+ template <typename R2>
+ inline typename disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
+ fallback_to(BOOST_THREAD_RV_REF(R2) v);
+ template <typename R2>
+ inline typename disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
+ fallback_to(R2 const& v);
+
#endif
-#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
- inline
- typename enable_if_c<
- is_future<value_type>::value,
- BOOST_THREAD_FUTURE<typename value_type::value_type>
- >::type
- unwrap();
-#endif
+
+//#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+// inline
+// typename enable_if<
+// is_future_type<value_type>,
+// value_type
+// //BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type>
+// >::type
+// unwrap();
+//#endif
};
BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
+ template <typename R2>
+ class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> >
+ {
+ typedef BOOST_THREAD_FUTURE<R2> R;
+
+ private:
+ typedef detail::basic_future<R> base_type;
+ typedef typename base_type::future_ptr future_ptr;
+
+ friend class shared_future<R>;
+ friend class promise<R>;
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ template <typename, typename, typename>
+ friend struct detail::future_async_continuation_shared_state;
+ template <typename, typename, typename>
+ friend struct detail::future_deferred_continuation_shared_state;
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
+ #endif
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ template<typename F, typename Rp>
+ friend struct detail::future_unwrap_shared_state;
+ template <class F, class Rp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, F& f);
+#endif
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ template <class> friend class packaged_task; // todo check if this works in windows
+ #else
+ friend class packaged_task<R>;
+ #endif
+ friend class detail::future_waiter;
+
+ template <class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
+
+ template <class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
+
+
+ typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
+
+ BOOST_THREAD_FUTURE(future_ptr a_future):
+ base_type(a_future)
+ {
+ }
+
+ public:
+ BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
+ typedef future_state::state state;
+ typedef R value_type;
+
+ BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
+
+ ~BOOST_THREAD_FUTURE() {}
+
+ BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
+ base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
+ {
+ }
+
+ BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
+ {
+ this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
+ return *this;
+ }
+
+ shared_future<R> share()
+ {
+ return shared_future<R>(::boost::move(*this));
+ }
+
+ void swap(BOOST_THREAD_FUTURE& other)
+ {
+ static_cast<base_type*>(this)->swap(other);
+ }
+
+ // todo this function must be private and friendship provided to the internal users.
+ void set_async()
+ {
+ this->future_->set_async();
+ }
+ // todo this function must be private and friendship provided to the internal users.
+ void set_deferred()
+ {
+ this->future_->set_deferred();
+ }
+
+ // retrieving the value
+ move_dest_type get()
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ future_ptr fut_=this->future_;
+ #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ this->future_.reset();
+ #endif
+ return fut_->get();
+ }
+ move_dest_type get_or(BOOST_THREAD_RV_REF(R) v)
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ this->future_->wait(false);
+ future_ptr fut_=this->future_;
+ #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ this->future_.reset();
+ #endif
+ if (fut_->has_value()) return fut_->get();
+ else return boost::move(v);
+ }
+
+ move_dest_type get_or(R const& v)
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ this->future_->wait(false);
+ future_ptr fut_=this->future_;
+ #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ this->future_.reset();
+ #endif
+ if (fut_->has_value()) return fut_->get();
+ else return v;
+ }
+
+
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+
+ // template<typename F>
+ // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
+
+ //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
+ // template<typename RF>
+ // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&));
+ // template<typename RF>
+ // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&));
+ //#endif
+ template<typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE&)>::type>
+ then(BOOST_THREAD_FWD_REF(F) func);
+ template<typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE&)>::type>
+ then(launch policy, BOOST_THREAD_FWD_REF(F) func);
+ #endif
+
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ inline
+ BOOST_THREAD_FUTURE<R2>
+ unwrap();
+ #endif
+
+ };
+
template <typename R>
class shared_future : public detail::basic_future<R>
{
@@ -1633,6 +1863,21 @@
return this->future_->get_sh();
}
+
+ template <typename R2>
+ typename disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type
+ get_or(BOOST_THREAD_RV_REF(R2) v)
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ future_ptr fut_=this->future_;
+ fut_->wait();
+ if (fut_->has_value()) return fut_->get_sh();
+ else return boost::move(v);
+ }
+
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
// template<typename F>
@@ -1653,14 +1898,14 @@
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future&)>::type>
then(launch policy, BOOST_THREAD_FWD_REF(F) func);
#endif
-#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
- inline
- typename enable_if_c<
- is_future<value_type>::value,
- BOOST_THREAD_FUTURE<typename value_type::value_type>
- >::type
- unwrap();
-#endif
+//#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+// inline
+// typename enable_if_c<
+// is_future_type<value_type>::value,
+// BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type>
+// >::type
+// unwrap();
+//#endif
};
@@ -3820,7 +4065,61 @@
BOOST_THREAD_ASSERT_PRECONDITION(false && "invalid launch parameter", std::logic_error("invalid launch parameter"));
}
}
+ namespace detail
+ {
+ template <typename T>
+ struct mfallbacker_to
+ {
+ T value_;
+ typedef T result_type;
+ mfallbacker_to(BOOST_THREAD_RV_REF(T) v)
+ : value_(boost::move(v))
+ {}
+
+ T operator()(BOOST_THREAD_FUTURE<T>& fut)
+ {
+ return fut.get_or(boost::move(value_));
+
+ }
+ };
+ template <typename T>
+ struct cfallbacker_to
+ {
+ T value_;
+ typedef T result_type;
+ cfallbacker_to(T const& v)
+ : value_(v)
+ {}
+
+ T operator()(BOOST_THREAD_FUTURE<T>& fut)
+ {
+ return fut.get_or(value_);
+
+ }
+ };
+ }
+ ////////////////////////////////
+ // future<R> future<R>::fallback_to(R&& v);
+ ////////////////////////////////
+
+ template <typename R>
+ template <typename R2>
+ inline typename disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
+ BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v)
+ {
+ return then(detail::mfallbacker_to<R>(boost::move(v)));
+ }
+
+ template <typename R>
+ template <typename R2>
+ inline typename disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
+ BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v)
+ {
+ return then(detail::cfallbacker_to<R>(v));
+ }
+
#endif
+
#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
namespace detail
{
@@ -3829,68 +4128,49 @@
/// future_unwrap_shared_state
/////////////////////////
- template<typename Rp>
- struct future_unwrap_shared_state: future_async_shared_state_base<Rp>
+ template<typename F, typename Rp>
+ struct future_unwrap_shared_state: shared_state<Rp>
{
- typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
-
- future_ptr parent_;
+ F parent;
public:
- explicit future_async_continuation_shared_state(
- F& f, BOOST_THREAD_FWD_REF(Fp) c
+ explicit future_unwrap_shared_state(
+ F& f
) :
- parent(f.future_),
- continuation(c)
+ parent(f.future_)
{
}
-
- void launch_continuation(boost::unique_lock<boost::mutex>& lock)
+ virtual void wait(bool rethrow)
{
- lock.unlock();
- this->thr_ = thread(&future_async_continuation_shared_state::run, this);
+ boost::unique_lock<boost::mutex> lock(mutex);
+ parent.get().wait();
}
-
- static void run(future_async_continuation_shared_state* that)
+ virtual Rp get()
{
- try
- {
- that->mark_finished_with_result(that->continuation(that->parent));
- }
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- that->mark_interrupted_finish();
- }
-#endif
- catch(...)
- {
- that->mark_exceptional_finish();
- }
+ boost::unique_lock<boost::mutex> lock(mutex);
+ return parent.get().get();
}
+
};
- template <class Rp>
- typename BOOST_THREAD_FUTURE<Rp>::value_type
- make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_FUTURE<Rp>& f)
+ template <class F, class Rp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, F& f)
{
-
- typedef typename BOOST_THREAD_FUTURE<Rp>::value_type future_value_type;
- shared_ptr<future_unwrap_shared_state<future_value_type> >
- h(new future_unwrap_shared_state<future_value_type>(f.future_));
+ shared_ptr<future_unwrap_shared_state<F, Rp> >
+ //shared_ptr<basic_future<Rp> >
+ //typename boost::detail::basic_future<Rp>::future_ptr
+ h(new future_unwrap_shared_state<F, Rp>(f));
f.future_->set_continuation_ptr(h, lock);
return BOOST_THREAD_FUTURE<Rp>(h);
}
}
- template <typename R>
- typename enable_if_c<
- is_future<value_type>::value,
- value_type>
- >::type
- future<R>::unwrap()
+ template <typename R2>
+ BOOST_THREAD_FUTURE<R2>
+ BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
{
- BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized())
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
- return boost::detail::make_future_unwrap_shared_state(lock, *this);
+ return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, *this);
}
#endif
}
Modified: trunk/libs/thread/doc/future_ref.qbk
==============================================================================
--- trunk/libs/thread/doc/future_ref.qbk Sun Jun 9 17:29:17 2013 (r84718)
+++ trunk/libs/thread/doc/future_ref.qbk 2013-06-09 17:41:00 EDT (Sun, 09 Jun 2013) (r84719)
@@ -260,18 +260,20 @@
public:
typedef R value_type; // EXTENSION
- __unique_future__(__unique_future__ & rhs);// = delete;
- __unique_future__& operator=(__unique_future__& rhs);// = delete;
+ __unique_future__(__unique_future__ const& rhs) = delete;
+ __unique_future__& operator=(__unique_future__ const& rhs) = delete;
__unique_future__() noexcept;
~__unique_future__();
// move support
__unique_future__(__unique_future__ && other) noexcept;
+ __unique_future__(__unique_future__<__unique_future__<R>>&& rhs); // EXTENSION
__unique_future__& operator=(__unique_future__ && other) noexcept;
// factories
shared_future<R> share();
+
template<typename F>
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
then(F&& func); // EXTENSION
@@ -281,11 +283,15 @@
template<typename F>
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
then(launch policy, F&& func); // EXTENSION
-
+
+ see below unwrap(); // EXTENSION
+ __unique_future__ fallback_to(); // EXTENSION
+
void swap(__unique_future__& other) noexcept;
// retrieving the value
see below get();
+ see below get_or(see below); // EXTENSION
// functions to check state
bool valid() const noexcept;
@@ -300,7 +306,7 @@
template <class Clock, class Duration>
future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
- #if defined BOOST_THREAD_USES_DATE_TIME || defined BOOST_THREAD_DONT_USE_CHRONO
+ #if defined BOOST_THREAD_USES_DATE_TIME
template<typename Duration>
bool timed_wait(Duration const& rel_time) const; // DEPRECATED SINCE V3.0.0
bool timed_wait_until(boost::system_time const& abs_time) const; // DEPRECATED SINCE V3.0.0
@@ -309,6 +315,7 @@
state get_state() const; // EXTENSION
};
+[///////////////////////////////////////////////]
[section:default_constructor Default Constructor]
__unique_future__();
@@ -339,7 +346,7 @@
]
[endsect]
-
+[/////////////////////////////////////////]
[section:move_constructor Move Constructor]
__unique_future__(__unique_future__ && other);
@@ -359,7 +366,31 @@
]
[endsect]
+[///////////////////////////////////////////////////////////////////]
+[section:unwrap_move_constructor Unwrap Move Constructor - EXTENSION]
+
+ __unique_future__(__unique_future__<__unique_future__<R>>&& other); // EXTENSION
+
+[warning This constructor is experimental and subject to change in future versions.
+There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
+
+[variablelist
+
+[[Requires:] [`other.valid()`.]
+[[Effects:] [Constructs a new __unique_future__, and transfers ownership of the shared state associated with `other` and unwrapping the inner future (see `unwrap()`).]]
+
+[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
+call. `other->get_state()` returns __uninitialized__. The associated shared state is now
+unwrapped and the inner future shared state is associated with `*this`. `other` is not associated with any shared state, `! other.valid()`.]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+]
+
+[endsect]
+[////////////////////////////////////////////////]
[section:move_assignment Move Assignment Operator]
__unique_future__& operator=(__unique_future__ && other);
@@ -380,7 +411,7 @@
]
[endsect]
-
+[/////////////////////////////////////]
[section:swap Member function `swap()`]
void swap(__unique_future__ & other) no_except;
@@ -399,8 +430,7 @@
]
[endsect]
-
-
+[///////////////////////////////////]
[section:get Member function `get()`]
R get();
@@ -439,7 +469,47 @@
]
[endsect]
+[/////////////////////////////////////////////////////]
+[section:get_or Member function `get_or()` - EXTENSION]
+
+ R get_or(R&& v); // EXTENSION
+ R get_or(R const& v); // EXTENSION
+ R& __unique_future__<R&>::get_or(R& v); // EXTENSION
+ void __unique_future__<void>::get_or(); // EXTENSION
+
+[warning These functions are experimental and subject to change in future versions.
+There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with a shared state, waits until the result is ready as-if by a call to
+__unique_future_wait__, and depending on whether the shared state `has_value()` the retrieves the result.]]
+
+[[Returns:] [
+- `__unique_future__<R&>::get_or(v)` return the stored reference if has_value() and the passes parameter otherwise.
+
+- `__unique_future__<void>::get_or()`, there is no return value, but the function doesn't throws even if the shared state contained an exception.
+
+- `__unique_future__<R>::get_or(v)` returns an rvalue-reference to the value stored in the shared state if `has_value()` and an rvalue-reference build with the parameter `v`.
+
+]]
+
+[[Postconditions:] [[unique_future_is_ready_link `this->is_ready()`] returns `true`. [unique_future_get_state_link
+`this->get_state()`] returns __ready__.]]
+
+[[Throws:] [
+
+- __future_uninitialized__ if `*this` is not associated with a shared state.
+
+]]
+
+[[Notes:] [`get_or()` is an ['interruption point].]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
[section:wait Member function `wait()`]
void wait() const;
@@ -466,7 +536,7 @@
]
[endsect]
-
+[//////////////////////////////////////////////////////////////////////////////////]
[section:timed_wait_duration Member function `timed_wait()` DEPRECATED SINCE V3.0.0]
template<typename Duration>
@@ -505,7 +575,7 @@
]
[endsect]
-
+[//////////////////////////////////////////////////////////////////////////////////]
[section:timed_wait_absolute Member function `timed_wait()` DEPRECATED SINCE V3.0.0]
bool timed_wait(boost::system_time const& wait_timeout);
@@ -543,7 +613,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////]
[section:wait_for Member function `wait_for()`]
template <class Rep, class Period>
@@ -581,7 +651,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////]
[section:wait_until Member function `wait_until()`]
template <class Clock, class Duration>
@@ -619,8 +689,7 @@
]
[endsect]
-
-
+[///////////////////////////////////////]
[section:valid Member function `valid()`]
bool valid() const noexcept;
@@ -635,6 +704,7 @@
]
[endsect]
+[///////////////////////////////////////////////////////]
[section:is_ready Member function `is_ready()` EXTENSION]
bool is_ready() const;
@@ -649,7 +719,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////////////]
[section:has_value Member function `has_value()` EXTENSION]
bool has_value() const;
@@ -664,7 +734,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////////////////////]
[section:has_exception Member function `has_exception()` EXTENSION]
bool has_exception() const;
@@ -679,7 +749,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////////////]
[section:get_state Member function `get_state()` EXTENSION]
future_state::state get_state();
@@ -695,9 +765,25 @@
]
+
[endsect]
+[///////////////////////////////////////]
+[section:share Member function `share()`]
-[section:then Member function `then()` EXTENSION]
+ shared_future<R> share();
+
+[variablelist
+
+[[Returns:] [`shared_future<R>(boost::move(*this))`.]]
+
+[[Postconditions:] [`this->valid() == false`.]]
+
+]
+
+
+[endsect]
+[/////////////////////////////////////////////////]
+[section:then Member function `then()` - EXTENSION]
template<typename F>
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
@@ -709,13 +795,10 @@
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
then(launch policy, F&& func); // EXTENSION
-
[warning These functions are experimental and subject to change in future versions.
There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
-[note These functions are based on the [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3558.pdf [*N3558 - A Standardized Representation of Asynchronous Operations]] C++1y proposal by N. Gustafsson, A. Laksberg, H. Sutter, S. Mithani.]
-
-
+[note These functions are based on the [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3634.pdf [*N3634 - Improvements to std::future<T> and related APIs]] C++1y proposal by N. Gustafsson, A. Laksberg, H. Sutter, S. Mithani.]
[variablelist
@@ -747,7 +830,7 @@
[[Postconditions:] [
-- The `shared_future` object passed to the parameter of the continuation function is a copy of the original `shared_future`.
+- The `__unique_future__` object passed to the parameter of the continuation function is a copy of the original `__unique_future__`.
- `valid() == false` on original future object immediately after it returns.
@@ -756,12 +839,44 @@
]
[endsect]
+[///////////////////////////////////////////////////]
+[section:unwrap Member function `unwrap()` EXTENSION]
+ template <typename R2>
+ __unique_future__<R2> __unique_future__<__unique_future__<R2>>::unwrap(); // EXTENSION
+ template <typename R2>
+ __shared_future__<R2> __unique_future__<__shared_future__<R2>>::unwrap(); // EXTENSION
+
+[warning These functions are experimental and subject to change in future versions.
+There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
+
+[note These functions are based on the [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3634.pdf [*N3634 - Improvements to std::future<T> and related APIs]] C++1y proposal by N. Gustafsson, A. Laksberg, H. Sutter, S. Mithani.]
+
+[variablelist
+
+[[Notes:] [Removes the outermost future and returns a future with the associated state been a proxy of inner future.]]
+
+[[Effects:] [
+
+- Returns a future that becomes ready when the shared state of the inner future is ready.
+
+]]
+
+[[Returns:] [An object of type future with the associated state been a proxy of inner future.]]
+
+[[Postconditions:] [
+
+- The returned future has `valid() == true` regardless of the validity of the inner future.
+
+]]
+
+]
-
[endsect]
+[endsect]
+[////////////////////////////////////////////////////]
[section:shared_future `shared_future` class template]
template <typename R>
@@ -838,7 +953,7 @@
]
[endsect]
-
+[///////////////////////////////////]
[section:get Member function `get()`]
const R& get();
@@ -872,7 +987,7 @@
]
[endsect]
-
+[/////////////////////////////////////]
[section:wait Member function `wait()`]
void wait() const;
@@ -898,7 +1013,7 @@
]
[endsect]
-
+[//////////////////////////////////////////////////////////]
[section:timed_wait_duration Member function `timed_wait()`]
template<typename Duration>
@@ -929,7 +1044,7 @@
]
[endsect]
-
+[//////////////////////////////////////////////////////////]
[section:timed_wait_absolute Member function `timed_wait()`]
bool timed_wait(boost::system_time const& wait_timeout);
@@ -958,7 +1073,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////]
[section:wait_for Member function `wait_for()`]
template <class Rep, class Period>
@@ -996,7 +1111,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////]
[section:wait_until Member function `wait_until()`]
template <class Clock, class Duration>
@@ -1034,7 +1149,7 @@
]
[endsect]
-
+[///////////////////////////////////////]
[section:valid Member function `valid()`]
bool valid() const noexcept;
@@ -1049,7 +1164,7 @@
]
[endsect]
-
+[///////////////////////////////////////////////////////]
[section:is_ready Member function `is_ready()` EXTENSION]
bool is_ready() const;
@@ -1064,7 +1179,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////////////]
[section:has_value Member function `has_value()` EXTENSION]
bool has_value() const;
@@ -1079,7 +1194,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////////////////////]
[section:has_exception Member function `has_exception()` EXTENSION]
bool has_exception() const;
@@ -1094,7 +1209,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////////////]
[section:get_state Member function `get_state()` EXTENSION]
future_state::state get_state();
@@ -1111,7 +1226,7 @@
]
[endsect]
-
+[///////////////////////////////////////////////]
[section:then Member function `then()` EXTENSION]
template<typename F>
@@ -1128,9 +1243,7 @@
[warning These functions are experimental and subject to change in future versions.
There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
-[note These functions are based on the [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3558.pdf [*N3558 - A Standardized Representation of Asynchronous Operations]] C++1y proposal by N. Gustafsson, A. Laksberg, H. Sutter, S. Mithani.]
-
-
+[note These functions are based on the [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3634.pdf [*N3634 - Improvements to std::future<T> and related APIs]] C++1y proposal by N. Gustafsson, A. Laksberg, H. Sutter, S. Mithani.]
[variablelist
@@ -1174,6 +1287,7 @@
[endsect]
+[////////////////////////////////////////]
[section:promise `promise` class template]
template <typename R>
@@ -1185,8 +1299,8 @@
promise();
template <class Allocator>
promise(allocator_arg_t, Allocator a);
- promise & operator=(const promise & rhs);// = delete;
- promise(const promise & rhs);// = delete;
+ promise & operator=(promise const& rhs) = delete;
+ promise(promise const& rhs) = delete;
~promise();
// Move support
@@ -1226,7 +1340,7 @@
]
[endsect]
-
+[///////////////////////////////////////////////]
[section:alloc_constructor Allocator Constructor]
template <class Allocator>
@@ -1243,9 +1357,7 @@
]
[endsect]
-
-
-
+[/////////////////////////////////////////]
[section:move_constructor Move Constructor]
promise(promise && other);
@@ -1262,7 +1374,7 @@
]
[endsect]
-
+[////////////////////////////////////////////////]
[section:move_assignment Move Assignment Operator]
promise& operator=(promise && other);
@@ -1280,7 +1392,7 @@
]
[endsect]
-
+[/////////////////////////////]
[section:destructor Destructor]
~promise();
@@ -1295,7 +1407,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////]
[section:get_future Member Function `get_future()`]
__unique_future__<R> get_future();
@@ -1311,7 +1423,7 @@
]
[endsect]
-
+[///////////////////////////////////////////////]
[section:set_value Member Function `set_value()`]
void set_value(R&& r);
@@ -1343,7 +1455,7 @@
]
[endsect]
-
+[///////////////////////////////////////////////////////]
[section:set_exception Member Function `set_exception()`]
void set_exception(boost::exception_ptr e);
@@ -1373,7 +1485,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////////////////////////////////]
[section:set_value_at_thread_exit Member Function `set_value_at_thread_exit()`]
void set_value_at_thread_exit(R&& r);
@@ -1402,7 +1514,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////////////////////////////////////////]
[section:set_exception_at_thread_exit Member Function `set_exception_at_thread_exit()`]
void set_exception_at_thread_exit(boost::exception_ptr e);
@@ -1430,6 +1542,7 @@
]
[endsect]
+[/////////////////////////////////////////////////////////////////////////]
[section:set_wait_callback Member Function `set_wait_callback()` EXTENSION]
template<typename F>
@@ -1451,7 +1564,7 @@
[endsect]
[endsect]
-
+[////////////////////////////////////////////////////]
[section:packaged_task `packaged_task` class template]
template<typename S>
@@ -1462,8 +1575,8 @@
class packaged_task<R(ArgTypes)>
{
public:
- packaged_task(packaged_task&);// = delete;
- packaged_task& operator=(packaged_task&);// = delete;
+ packaged_task(packaged_task const&) = delete;
+ packaged_task& operator=(packaged_task const&) = delete;
// construction and destruction
packaged_task() noexcept;
@@ -1529,7 +1642,7 @@
]
[endsect]
-
+[///////////////////////////////////////////////]
[section:alloc_constructor Allocator Constructor]
template <class Allocator>
@@ -1553,7 +1666,7 @@
]
[endsect]
-
+[/////////////////////////////////////////]
[section:move_constructor Move Constructor]
packaged_task(packaged_task && other);
@@ -1570,8 +1683,7 @@
]
[endsect]
-
-
+[////////////////////////////////////////////////]
[section:move_assignment Move Assignment Operator]
packaged_task& operator=(packaged_task && other);
@@ -1589,7 +1701,7 @@
]
[endsect]
-
+[/////////////////////////////]
[section:destructor Destructor]
~packaged_task();
@@ -1604,7 +1716,7 @@
]
[endsect]
-
+[/////////////////////////////////////////////////]
[section:get_future Member Function `get_future()`]
__unique_future__<R> get_future();
Modified: trunk/libs/thread/doc/futures.qbk
==============================================================================
--- trunk/libs/thread/doc/futures.qbk Sun Jun 9 17:29:17 2013 (r84718)
+++ trunk/libs/thread/doc/futures.qbk 2013-06-09 17:41:00 EDT (Sun, 09 Jun 2013) (r84719)
@@ -293,7 +293,7 @@
[heading Multiple get]
-The second `get()` call in the following example future
+The second `get()` call in the following example is undefined.
void bad_second_use( type arg ) {
@@ -372,14 +372,14 @@
[section:make_ready_future Making immediate futures easier]
Some functions may know the value at the point of construction. In these cases the value is immediately available,
-but needs to be returned as a future or shared_future. By using make_ready_future (make_shared_future) a future (shared_future)
+but needs to be returned as a future or shared_future. By using make_ready_future a future
can be created which holds a pre-computed result in its shared state.
Without these features it is non-trivial to create a future directly from a value.
First a promise must be created, then the promise is set, and lastly the future is retrieved from the promise.
This can now be done with one operation.
-[heading make_ready_future / make_shared_future]
+[heading make_ready_future]
This function creates a future for a given value. If no value is given then a future<void> is returned.
This function is primarily useful in cases where sometimes, the return value is immediately available, but sometimes
@@ -396,9 +396,7 @@
}
There are two variations of this function. The first takes a value of any type, and returns a future of that type.
-The input value is passed to the shared state of the returned future. The second version takes no input and returns a future<void>.
-make_shared_future has the same functionality as make_ready_future, except has a return type of shared_future.
-
+The input value is passed to the shared state of the returned future. The second version takes no input and returns a future<void>.
[endsect]
Added: trunk/libs/thread/example/future_fallback_to.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/thread/example/future_fallback_to.cpp 2013-06-09 17:41:00 EDT (Sun, 09 Jun 2013) (r84719)
@@ -0,0 +1,78 @@
+// Copyright (C) 2012-2013 Vicente Botet
+//
+// 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)
+
+#define BOOST_THREAD_VERSION 4
+#define BOOST_THREAD_USES_LOG
+#define BOOST_THREAD_USES_LOG_THREAD_ID
+
+#include <boost/thread/detail/log.hpp>
+#include <boost/thread/future.hpp>
+#include <boost/assert.hpp>
+#include <exception>
+#include <string>
+
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+
+int p1_ex()
+{
+ BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
+ throw std::logic_error("kk");
+}
+
+int p1()
+{
+ BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
+ return 1;;
+}
+
+int main()
+{
+ BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
+ {
+ try
+ {
+ boost::future<int> f1 = boost::async(boost::launch::async, &p1);
+ boost::future<int> f2 = f1.fallback_to(-1);
+ assert(f2.get()==1);
+ }
+ catch (std::exception& ex)
+ {
+ BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
+ return 1;
+ }
+ catch (...)
+ {
+ BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
+ return 2;
+ }
+ }
+ {
+ try
+ {
+ boost::future<int> f1 = boost::async(boost::launch::async, &p1_ex);
+ boost::future<int> f2 = f1.fallback_to(-1);
+ assert(f2.get()==-1);
+ }
+ catch (std::exception& ex)
+ {
+ BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
+ return 1;
+ }
+ catch (...)
+ {
+ BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
+ return 2;
+ }
+ }
+ BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
+ return 0;
+}
+#else
+
+int main()
+{
+ return 0;
+}
+#endif
Added: trunk/libs/thread/example/future_unwrap.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/thread/example/future_unwrap.cpp 2013-06-09 17:41:00 EDT (Sun, 09 Jun 2013) (r84719)
@@ -0,0 +1,59 @@
+// Copyright (C) 2012-2013 Vicente Botet
+//
+// 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)
+
+#define BOOST_THREAD_VERSION 4
+#define BOOST_THREAD_USES_LOG
+#define BOOST_THREAD_USES_LOG_THREAD_ID
+
+#include <boost/thread/detail/log.hpp>
+#include <boost/thread/future.hpp>
+#include <boost/assert.hpp>
+#include <string>
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+
+int p1()
+{
+ BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
+ return 123;
+}
+
+boost::future<int> p2()
+{
+ BOOST_THREAD_LOG << "<P2" << BOOST_THREAD_END_LOG;
+ boost::future<int> f1 = boost::async(boost::launch::async, &p1);
+ BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG;
+ return boost::move(f1);
+}
+
+int main()
+{
+ BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
+ try
+ {
+ boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
+ boost::future<int> inner_future = outer_future.unwrap();
+ int i = inner_future.get();
+ BOOST_THREAD_LOG << "i= "<< i << "" << BOOST_THREAD_END_LOG;
+ }
+ catch (std::exception& ex)
+ {
+ BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
+ return 1;
+ }
+ catch (...)
+ {
+ BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
+ return 2;
+ }
+ BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
+ return 0;
+}
+#else
+
+int main()
+{
+ return 0;
+}
+#endif
Modified: trunk/libs/thread/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2 Sun Jun 9 17:29:17 2013 (r84718)
+++ trunk/libs/thread/test/Jamfile.v2 2013-06-09 17:41:00 EDT (Sun, 09 Jun 2013) (r84719)
@@ -352,6 +352,7 @@
[ thread-run2-noit ./sync/futures/future/default_pass.cpp : future__default_p ]
[ thread-run2-noit ./sync/futures/future/dtor_pass.cpp : future__dtor_p ]
[ thread-run2-noit ./sync/futures/future/get_pass.cpp : future__get_p ]
+ [ thread-run2-noit ./sync/futures/future/get_or_pass.cpp : future__get_or_p ]
[ thread-run2-noit ./sync/futures/future/move_ctor_pass.cpp : future__move_ctor_p ]
[ thread-run2-noit ./sync/futures/future/move_assign_pass.cpp : future__move_asign_p ]
[ thread-run2-noit ./sync/futures/future/share_pass.cpp : future__share_p ]
@@ -690,6 +691,8 @@
#[ thread-run ../example/vhh_shared_mutex.cpp ]
[ thread-run2 ../example/make_future.cpp : ex_make_future ]
[ thread-run2 ../example/future_then.cpp : ex_future_then ]
+ [ thread-run2 ../example/future_fallback_to.cpp : ex_future_fallback_to ]
+ [ thread-run2 ../example/future_unwrap.cpp : ex_future_unwrap ]
[ thread-run2-noit ../example/synchronized_value.cpp : ex_synchronized_value ]
[ thread-run2-noit ../example/synchronized_person.cpp : ex_synchronized_person ]
[ thread-run2-noit ../example/thread_guard.cpp : ex_thread_guard ]
@@ -772,7 +775,7 @@
#[ thread-run ../example/std_async_test.cpp ]
#[ thread-run test_8508.cpp ]
#[ thread-run test_8586.cpp ]
- [ thread-run test_8596.cpp ]
+ #[ thread-run test_8596.cpp ]
#[ thread-run test_8600.cpp ]
;
Added: trunk/libs/thread/test/sync/futures/future/get_or_pass.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/thread/test/sync/futures/future/get_or_pass.cpp 2013-06-09 17:41:00 EDT (Sun, 09 Jun 2013) (r84719)
@@ -0,0 +1,182 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+
+// <boost/thread/future.hpp>
+
+// class future<R>
+
+// R future::get_or(R&&);
+// R& future<R&>::get_or(R&);
+
+#define BOOST_THREAD_VERSION 4
+#define BOOST_THREAD_USES_LOG
+#define BOOST_THREAD_USES_LOG_THREAD_ID
+#include <boost/thread/detail/log.hpp>
+
+#include <boost/thread/future.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#if defined BOOST_THREAD_USES_CHRONO
+
+namespace boost
+{
+template <typename T>
+struct wrap
+{
+ wrap(T const& v) : value(v){}
+ T value;
+
+};
+
+template <typename T>
+exception_ptr make_exception_ptr(T v) {
+ return copy_exception(wrap<T>(v));
+}
+}
+
+void func1(boost::promise<int> p)
+{
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
+ p.set_value(3);
+}
+
+void func2(boost::promise<int> p)
+{
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
+ p.set_exception(boost::make_exception_ptr(3));
+}
+
+int j = 0;
+
+void func3(boost::promise<int&> p)
+{
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
+ j = 5;
+ p.set_value(j);
+}
+
+void func4(boost::promise<int&> p)
+{
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
+ p.set_exception(boost::make_exception_ptr(3.5));
+}
+
+void func5(boost::promise<void> p)
+{
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
+ p.set_value();
+}
+
+void func6(boost::promise<void> p)
+{
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
+ p.set_exception(boost::make_exception_ptr(4));
+}
+
+
+int main()
+{
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ {
+ typedef int T;
+ {
+ boost::promise<T> p;
+ boost::future<T> f = p.get_future();
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ boost::thread(func1, boost::move(p)).detach();
+#else
+ p.set_value(3);
+#endif
+ BOOST_TEST(f.valid());
+ BOOST_TEST(f.get_or(4) == 3);
+#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ BOOST_TEST(!f.valid());
+#endif
+ }
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ {
+ boost::promise<T> p;
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ boost::future<T> f = p.get_future();
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ boost::thread(func2, boost::move(p)).detach();
+#else
+ p.set_exception(boost::make_exception_ptr(3));
+#endif
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ try
+ {
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ BOOST_TEST(f.valid());
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ BOOST_TEST(f.get_or(4) == 4);
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ }
+ catch (...)
+ {
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ BOOST_TEST(false);
+ }
+#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ BOOST_TEST(!f.valid());
+#endif
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ }
+ }
+// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+// {
+// typedef int& T;
+// {
+// boost::promise<T> p;
+// boost::future<T> f = p.get_future();
+//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+// boost::thread(func3, boost::move(p)).detach();
+//#else
+// int j=5;
+// p.set_value(j);
+//#endif
+// BOOST_TEST(f.valid());
+// int k=4;
+// BOOST_TEST(f.get_or(k) == 5);
+//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+// BOOST_TEST(!f.valid());
+//#endif
+// }
+// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+// {
+// boost::promise<T> p;
+// boost::future<T> f = p.get_future();
+//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+// boost::thread(func4, boost::move(p)).detach();
+//#else
+// p.set_exception(boost::make_exception_ptr(3.5));
+//#endif
+// try
+// {
+// BOOST_TEST(f.valid());
+// int j=4;
+// BOOST_TEST(f.get_or(j) == 4);
+// }
+// catch (...)
+// {
+// BOOST_TEST(false);
+// }
+//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+// BOOST_TEST(!f.valid());
+//#endif
+// }
+// }
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+
+
+ return boost::report_errors();
+}
+
+#else
+#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
+#endif
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk