2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-04 22:02:10 +00:00

Compare commits

...

2 Commits

Author SHA1 Message Date
Vicente J. Botet Escriba
69c1d40750 Merge branch 'develop' into feature/promise_set_value_emplace 2014-11-05 23:43:02 +01:00
Vicente J. Botet Escriba
952aa44a98 Added promise::emplace and variadic make_ready_future. 2014-10-25 23:31:09 +02:00
5 changed files with 501 additions and 187 deletions

View File

@@ -432,24 +432,24 @@ namespace boost
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
void mark_interrupted_finish()
{
boost::unique_lock<boost::mutex> lock(this->mutex);
exception = boost::copy_exception(boost::thread_interrupted());
mark_finished_internal(lock);
}
// void mark_interrupted_finish()
// {
// boost::unique_lock<boost::mutex> lock(this->mutex);
// exception = boost::copy_exception(boost::thread_interrupted());
// mark_finished_internal(lock);
// }
void set_interrupted_at_thread_exit()
{
unique_lock<boost::mutex> lk(this->mutex);
if (has_value(lk))
{
throw_exception(promise_already_satisfied());
}
exception = boost::copy_exception(boost::thread_interrupted());
this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
// void set_interrupted_at_thread_exit()
// {
// unique_lock<boost::mutex> lk(this->mutex);
// if (has_value(lk))
// {
// throw_exception(promise_already_satisfied());
// }
// exception = boost::copy_exception(boost::thread_interrupted());
// this->is_constructed = true;
// detail::make_ready_at_thread_exit(shared_from_this());
// }
#endif
void set_exception_at_thread_exit(exception_ptr e)
@@ -481,14 +481,14 @@ namespace boost
return done && exception;
}
bool has_exception(unique_lock<boost::mutex>&) const
{
return done && exception;
}
// bool has_exception(unique_lock<boost::mutex>&) const
// {
// return done && exception;
// }
bool is_deferred(boost::lock_guard<boost::mutex>&) const {
return is_deferred_;
}
// bool is_deferred(boost::lock_guard<boost::mutex>&) const {
// return is_deferred_;
// }
launch launch_policy(boost::unique_lock<boost::mutex>&) const
{
@@ -511,13 +511,14 @@ namespace boost
exception_ptr get_exception_ptr()
{
boost::unique_lock<boost::mutex> lock(this->mutex);
return get_exception_ptr(lock);
}
exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock)
{
wait_internal(lock, false);
return exception;
}
// exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock)
// {
// wait_internal(lock, false);
// return exception;
// }
template<typename F,typename U>
void set_wait_callback(F f,U* u)
@@ -580,21 +581,29 @@ namespace boost
void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
result = boost::move(result_);
#else
#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
result.reset(new T(boost::move(result_)));
#endif
#else
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
result = boost::move(result_);
#else
result.reset(new T(static_cast<rvalue_source_type>(result_)));
#endif
this->mark_finished_internal(lock);
}
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class ...Args>
void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock, BOOST_THREAD_FWD_REF(Args)... args)
{
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
result.emplace(boost::forward<Args>(args)...);
#else
result.reset(new T(boost::forward<Args>(args)...));
#endif
this->mark_finished_internal(lock);
}
#endif
void mark_finished_with_result(source_reference_type result_)
{
@@ -830,12 +839,6 @@ namespace boost
{
that->mark_finished_with_result(f());
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
that->mark_interrupted_finish();
}
#endif
catch(...)
{
that->mark_exceptional_finish();
@@ -858,12 +861,6 @@ namespace boost
f();
that->mark_finished_with_result();
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
that->mark_interrupted_finish();
}
#endif
catch(...)
{
that->mark_exceptional_finish();
@@ -885,12 +882,6 @@ namespace boost
{
that->mark_finished_with_result(f());
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
that->mark_interrupted_finish();
}
#endif
catch(...)
{
that->mark_exceptional_finish();
@@ -1277,7 +1268,6 @@ namespace boost
future_ = p.get_future().future_;
}
future_ptr future_;
basic_future(future_ptr a_future):
@@ -2077,6 +2067,22 @@ namespace boost
future_->mark_finished_with_result_internal(static_cast<rvalue_source_type>(r), lock);
#endif
}
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class ...Args>
void emplace(BOOST_THREAD_FWD_REF(Args) ...args)
{
lazy_init();
boost::unique_lock<boost::mutex> lock(future_->mutex);
if(future_->done)
{
boost::throw_exception(promise_already_satisfied());
}
future_->mark_finished_with_result_internal(lock, boost::forward<Args>(args)...);
}
#endif
void set_exception(boost::exception_ptr p)
{
lazy_init();
@@ -2606,12 +2612,12 @@ namespace boost
this->set_value_at_thread_exit(f());
}
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->set_interrupted_at_thread_exit();
}
#endif
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// catch(thread_interrupted& )
// {
// this->set_interrupted_at_thread_exit();
// }
//#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -2637,12 +2643,6 @@ namespace boost
this->mark_finished_with_result(f());
#endif
}
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->mark_interrupted_finish();
}
#endif
catch(...)
{
@@ -2693,12 +2693,12 @@ namespace boost
this->set_value_at_thread_exit(f());
}
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->set_interrupted_at_thread_exit();
}
#endif
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// catch(thread_interrupted& )
// {
// this->set_interrupted_at_thread_exit();
// }
//#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -2720,12 +2720,6 @@ namespace boost
R& res((f()));
this->mark_finished_with_result(res);
}
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->mark_interrupted_finish();
}
#endif
catch(...)
{
@@ -2783,12 +2777,12 @@ namespace boost
this->set_value_at_thread_exit(boost::move(r));
}
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->set_interrupted_at_thread_exit();
}
#endif
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// catch(thread_interrupted& )
// {
// this->set_interrupted_at_thread_exit();
// }
//#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -2811,12 +2805,6 @@ namespace boost
R res((f()));
this->mark_finished_with_result(boost::move(res));
}
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->mark_interrupted_finish();
}
#endif
catch(...)
{
@@ -2870,12 +2858,12 @@ namespace boost
this->set_value_at_thread_exit(f());
}
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->set_interrupted_at_thread_exit();
}
#endif
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// catch(thread_interrupted& )
// {
// this->set_interrupted_at_thread_exit();
// }
//#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -2897,12 +2885,6 @@ namespace boost
{
this->mark_finished_with_result(f());
}
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->mark_interrupted_finish();
}
#endif
catch(...)
{
@@ -2953,12 +2935,12 @@ namespace boost
#endif
this->set_value_at_thread_exit();
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->set_interrupted_at_thread_exit();
}
#endif
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// catch(thread_interrupted& )
// {
// this->set_interrupted_at_thread_exit();
// }
//#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -2980,12 +2962,6 @@ namespace boost
#endif
this->mark_finished_with_result();
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->mark_interrupted_finish();
}
#endif
catch(...)
{
this->mark_exceptional_finish();
@@ -3032,12 +3008,12 @@ namespace boost
#endif
this->set_value_at_thread_exit();
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->set_interrupted_at_thread_exit();
}
#endif
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// catch(thread_interrupted& )
// {
// this->set_interrupted_at_thread_exit();
// }
//#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -3059,12 +3035,6 @@ namespace boost
#endif
this->mark_finished_with_result();
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->mark_interrupted_finish();
}
#endif
catch(...)
{
this->mark_exceptional_finish();
@@ -3602,10 +3572,6 @@ namespace detail {
void operator()() {
try {
that->mark_finished_with_result(f_());
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(...) {
that->mark_exceptional_finish();
}
@@ -3653,10 +3619,6 @@ namespace detail {
try {
f_();
that->mark_finished_with_result();
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(...) {
that->mark_exceptional_finish();
}
@@ -3702,10 +3664,6 @@ namespace detail {
void operator()() {
try {
that->mark_finished_with_result(f_());
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(...) {
that->mark_exceptional_finish();
}
@@ -3929,7 +3887,11 @@ namespace detail {
////////////////////////////////
// make_ready_future
////////////////////////////////
template <typename T>
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <int = 0, int..., class T>
#else
template <class T>
#endif
BOOST_THREAD_FUTURE<typename decay<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) {
typedef typename decay<T>::type future_value_type;
promise<future_value_type> p;
@@ -3937,6 +3899,35 @@ namespace detail {
return BOOST_THREAD_MAKE_RV_REF(p.get_future());
}
// explicit overloads
template <class T>
BOOST_THREAD_FUTURE<T> make_ready_future(typename remove_reference<T>::type & x)
{
promise<T> p;
p.set_value(x);
return p.get_future();
}
template <class T>
BOOST_THREAD_FUTURE<T> make_ready_future(BOOST_THREAD_FWD_REF(typename remove_reference<T>::type) x)
{
promise<T> p;
p.set_value(forward<typename remove_reference<T>::type>(x));
return p.get_future();
}
// variadic overload
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class T, class ...Args>
BOOST_THREAD_FUTURE<T> make_ready_future(Args&&... args)
{
promise<T> p;
p.emplace(forward<Args>(args)...);
return p.get_future();
}
#endif
template <typename T, typename T1>
BOOST_THREAD_FUTURE<T> make_ready_no_decay_future(T1 value) {
typedef T future_value_type;
@@ -4052,10 +4043,6 @@ namespace detail
static void run(future_async_continuation_shared_state* that) {
try {
that->mark_finished_with_result(that->continuation(boost::move(that->parent)));
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -4086,10 +4073,6 @@ namespace detail
try {
that->continuation(boost::move(that->parent));
that->mark_finished_with_result();
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -4135,10 +4118,6 @@ namespace detail
static void run(future_executor_continuation_shared_state* that) {
try {
that->mark_finished_with_result(that->continuation(boost::move(that->parent)));
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -4172,10 +4151,6 @@ namespace detail
try {
that->continuation(boost::move(that->parent));
that->mark_finished_with_result();
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -4210,10 +4185,6 @@ namespace detail
static void run(shared_future_async_continuation_shared_state* that) {
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();
}
@@ -4244,10 +4215,6 @@ namespace detail
try {
that->continuation(that->parent);
that->mark_finished_with_result();
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -4285,10 +4252,6 @@ namespace detail
static void run(shared_future_executor_continuation_shared_state* that) {
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();
}
@@ -4321,10 +4284,6 @@ namespace detail
try {
that->continuation(that->parent);
that->mark_finished_with_result();
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -4811,10 +4770,6 @@ namespace detail
try {
boost::wait_for_all(that->vec_.begin(), that->vec_.end());
that->mark_finished_with_result(boost::move(that->vec_));
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -4885,10 +4840,6 @@ namespace detail
try {
boost::wait_for_any(that->vec_.begin(), that->vec_.end());
that->mark_finished_with_result(boost::move(that->vec_));
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -4993,10 +4944,6 @@ namespace detail
that->wait_for_all(Index());
that->mark_finished_with_result(boost::move(that->tup_));
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -5067,10 +5014,6 @@ namespace detail
that->wait_for_any(Index());
that->mark_finished_with_result(boost::move(that->tup_));
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(thread_interrupted& ) {
that->mark_interrupted_finish();
#endif
} catch(...) {
that->mark_exceptional_finish();
}

View File

@@ -27,7 +27,7 @@ namespace boost
/// Effect: Decrement the count. Unlocks the lock and notify anyone waiting if we reached zero.
/// Returns: true if count_ reached the value 0.
/// @ThreadSafe ensured by the @c lk parameter
bool count_down(unique_lock<mutex> &lk)
bool count_down(unique_lock<mutex> &)
/// pre_condition (count_ > 0)
{
BOOST_ASSERT(count_ > 0);

View File

@@ -349,6 +349,7 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2-noit ./sync/futures/promise/set_rvalue_pass.cpp : promise__set_rvalue_p ]
[ thread-run2-noit ./sync/futures/promise/set_value_const_pass.cpp : promise__set_value_const_p ]
[ thread-run2-noit ./sync/futures/promise/set_value_void_pass.cpp : promise__set_value_void_p ]
[ thread-run2-noit ./sync/futures/promise/emplace_pass.cpp : promise__emplace_p ]
[ thread-run2-noit ./sync/futures/promise/use_allocator_pass.cpp : promise__use_allocator_p ]
[ thread-run2-noit ./sync/futures/promise/set_exception_at_thread_exit_pass.cpp : promise__set_exception_at_thread_exit_p ]
[ thread-run2-noit ./sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp : promise__set_lvalue_at_thread_exit_p ]
@@ -357,6 +358,12 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2-noit ./sync/futures/promise/set_value_at_thread_exit_void_pass.cpp : promise__set_value_at_thread_exit_void_p ]
;
#explicit ts_make_ready_future ;
test-suite ts_make_ready_future
:
[ thread-run2-noit ./sync/futures/make_ready_future_pass.cpp : make_ready_future_p ]
;
#explicit ts_future ;
test-suite ts_future
:

View File

@@ -0,0 +1,157 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 2011,2014 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 promise<R>
// future<void> make_ready_future();
// template <class T>
// future<decay_t<T>> make_ready_future(T&&);
// template <class T>
// future<T> make_ready_future(remove_reference_t<T>&);
// template <class T>
// future<T> make_ready_future(remove_reference_t<T>&&);
// template <class T, class ...Args>
// future<T> make_ready_future(Args&& ... args);
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/static_assert.hpp>
struct A
{
A() :
value(0)
{
}
A(int i) :
value(i)
{
}
A(int i, int j) :
value(i+j)
{
}
int value;
};
A make(int i) {
return A(i);
}
A make(int i, int j) {
return A(i, j);
}
struct movable2
{
int value_;
BOOST_THREAD_MOVABLE_ONLY(movable2)
movable2() : value_(1){}
movable2(int i) : value_(i){}
movable2(int i, int j) : value_(i+j){}
//Move constructor and assignment
movable2(BOOST_RV_REF(movable2) m)
{ value_ = m.value_; m.value_ = 0; }
movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m)
{ value_ = m.value_; m.value_ = 0; return *this; }
bool moved() const //Observer
{ return !value_; }
int value() const //Observer
{ return value_; }
};
movable2 move_return_function2(int i) {
return movable2(i);
}
int main()
{
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false));
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true));
BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == true));
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == false));
#endif
{
boost::future<void> f = boost::make_ready_future();
f.wait();
}
{
typedef A T;
T i;
boost::future<T> f = boost::make_ready_future(i);
BOOST_TEST(f.get().value==0);
}
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
{
typedef A T;
boost::future<T> f = boost::make_ready_future<T>();
BOOST_TEST(f.get().value==0);
}
{
typedef A T;
boost::future<T> f = boost::make_ready_future<T>(1);
BOOST_TEST(f.get().value==1);
}
{
typedef A T;
boost::future<T> f = boost::make_ready_future<T>(1,2);
BOOST_TEST(f.get().value==3);
}
{
typedef A T;
T i;
boost::future<T&> f = boost::make_ready_future<T&>(i);
BOOST_TEST(f.get().value==0);
}
#endif
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
// sync/futures/make_ready_future_pass.cpp:125:65: erreur: conversion from Ôboost::future<boost::rv<movable2> >Õ to non-scalar type Ôboost::future<movable2>Õ requested
{
typedef movable2 T;
T i;
boost::future<T> f = boost::make_ready_future(boost::move(i));
BOOST_TEST_EQ(f.get().value(),1);
}
#endif
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
{
typedef movable2 T;
boost::future<T> f = boost::make_ready_future<T>();
BOOST_TEST(f.get().value()==1);
}
{
typedef movable2 T;
boost::future<T> f = boost::make_ready_future<T>(1);
BOOST_TEST(f.get().value()==1);
}
{
typedef movable2 T;
boost::future<T> f = boost::make_ready_future<T>(1,2);
BOOST_TEST(f.get().value()==3);
}
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,207 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 2011,2014 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 promise<R>
// template <class ...Args>
// void promise::emplace(Args&& ... args);
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/static_assert.hpp>
struct A
{
A() :
value(0)
{
}
A(int i) :
value(i)
{
}
A(int i, int j) :
value(i+j)
{
}
BOOST_THREAD_MOVABLE_ONLY(A)
A(BOOST_THREAD_RV_REF(A) rhs)
{
if(rhs.value==0)
throw 9;
else
{
value=rhs.value;
rhs.value=0;
}
}
A& operator=(BOOST_THREAD_RV_REF(A) rhs)
{
if(rhs.value==0)
throw 9;
else
{
value=rhs.value;
rhs.value=0;
}
return *this;
}
int value;
};
A make(int i) {
return A(i);
}
A make(int i, int j) {
return A(i, j);
}
struct movable2
{
int value_;
BOOST_THREAD_MOVABLE_ONLY(movable2)
movable2() : value_(1){}
movable2(int i) : value_(i){}
movable2(int i, int j) : value_(i+j){}
//Move constructor and assignment
movable2(BOOST_RV_REF(movable2) m)
{ value_ = m.value_; m.value_ = 0; }
movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m)
{ value_ = m.value_; m.value_ = 0; return *this; }
bool moved() const //Observer
{ return !value_; }
int value() const //Observer
{ return value_; }
};
movable2 move_return_function2(int i) {
return movable2(i);
}
int main()
{
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false));
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true));
BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == false));
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == true));
#endif
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
{
typedef A T;
T i;
boost::promise<T> p;
boost::future<T> f = p.get_future();
p.emplace();
try
{
T a = f.get(); (void)a;
BOOST_TEST(false);
}
catch (int j)
{
BOOST_TEST(j == 9);
}
catch (...)
{
BOOST_TEST(false);
}
}
{
typedef A T;
boost::promise<T> p;
boost::future<T> f = p.get_future();
p.emplace(3);
BOOST_TEST(f.get().value == 3);
try
{
T j(3);
p.set_value(boost::move(j));
BOOST_TEST(false);
}
catch (const boost::future_error& e)
{
BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
}
catch (...)
{
BOOST_TEST(false);
}
}
{
boost::promise<movable2> p;
boost::future<movable2> f = p.get_future();
p.emplace(3);
BOOST_TEST(f.get().value_ == 3);
try
{
p.emplace(3);
BOOST_TEST(false);
}
catch (const boost::future_error& e)
{
BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
}
catch (...)
{
BOOST_TEST(false);
}
}
{
boost::promise<A> p;
boost::future<A> f = p.get_future();
p.emplace(1,2);
BOOST_TEST(f.get().value == 3);
try
{
p.emplace(1,2);
BOOST_TEST(false);
}
catch (const boost::future_error& e)
{
BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
}
catch (...)
{
BOOST_TEST(false);
}
}
{
typedef A T;
boost::promise<T> p;
boost::future<T> f = p.get_future();
p.emplace(3);
boost::promise<T> p2(boost::move(p));
BOOST_TEST(f.get().value == 3);
}
#endif
return boost::report_errors();
}