diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2017-07-11 12:38:35 +0000 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2017-07-11 12:38:35 +0000 |
commit | 3c97cd1449b8c7f4ef752207274b210bf0337de6 (patch) | |
tree | 1cbdc4778faaa9c2f171c69961bd0eea921e0a86 | |
parent | a7b7f6b92e3f3231c6c57851bc38d58f60574232 (diff) |
PR libstdc++/80316 make promise::set_value throw no_state error
Backport from mainline
2017-04-21 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/80316
* include/std/future (_State_baseV2::_Setter::operator()): Remove
_S_check calls that are done after the pointer to the shared state is
already dereferenced.
(_State_baseV2::_Setter<_Res, void>): Define specialization for void
as partial specialization so it can be defined within the definition
of _State_baseV2.
(_State_baseV2::__setter): Call _S_check.
(_State_baseV2::__setter(promise<void>*)): Add overload for use by
promise<void>::set_value and promise<void>::set_value_at_thread_exit.
(promise<T>, promise<T&>, promise<void>): Make _State a friend.
(_State_baseV2::_Setter<void, void>): Remove explicit specialization.
(promise<void>::set_value, promise<void>::set_value_at_thread_exit):
Use new __setter overload.
* testsuite/30_threads/promise/members/at_thread_exit2.cc: New test.
* testsuite/30_threads/promise/members/set_exception.cc: Test
promise<T&> and promise<void> specializations.
* testsuite/30_threads/promise/members/set_exception2.cc: Likewise.
Test for no_state error condition.
* testsuite/30_threads/promise/members/set_value2.cc: Likewise.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-6-branch@250131 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libstdc++-v3/ChangeLog | 26 | ||||
-rw-r--r-- | libstdc++-v3/include/std/future | 59 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc | 167 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc | 49 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc | 181 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc | 292 |
6 files changed, 745 insertions, 29 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 81c1d7f9f43..fbabb99bb90 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,29 @@ +2017-07-11 Jonathan Wakely <jwakely@redhat.com> + + Backport from mainline + 2017-04-21 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/80316 + * include/std/future (_State_baseV2::_Setter::operator()): Remove + _S_check calls that are done after the pointer to the shared state is + already dereferenced. + (_State_baseV2::_Setter<_Res, void>): Define specialization for void + as partial specialization so it can be defined within the definition + of _State_baseV2. + (_State_baseV2::__setter): Call _S_check. + (_State_baseV2::__setter(promise<void>*)): Add overload for use by + promise<void>::set_value and promise<void>::set_value_at_thread_exit. + (promise<T>, promise<T&>, promise<void>): Make _State a friend. + (_State_baseV2::_Setter<void, void>): Remove explicit specialization. + (promise<void>::set_value, promise<void>::set_value_at_thread_exit): + Use new __setter overload. + * testsuite/30_threads/promise/members/at_thread_exit2.cc: New test. + * testsuite/30_threads/promise/members/set_exception.cc: Test + promise<T&> and promise<void> specializations. + * testsuite/30_threads/promise/members/set_exception2.cc: Likewise. + Test for no_state error condition. + * testsuite/30_threads/promise/members/set_value2.cc: Likewise. + 2017-07-04 Release Manager * GCC 6.4.0 released. diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future index 80b7b06a45f..830494f1904 100644 --- a/libstdc++-v3/include/std/future +++ b/libstdc++-v3/include/std/future @@ -462,7 +462,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Used by std::promise to copy construct the result. typename promise<_Res>::_Ptr_type operator()() const { - _State_baseV2::_S_check(_M_promise->_M_future); _M_promise->_M_storage->_M_set(*_M_arg); return std::move(_M_promise->_M_storage); } @@ -477,7 +476,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Used by std::promise to move construct the result. typename promise<_Res>::_Ptr_type operator()() const { - _State_baseV2::_S_check(_M_promise->_M_future); _M_promise->_M_storage->_M_set(std::move(*_M_arg)); return std::move(_M_promise->_M_storage); } @@ -485,6 +483,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Res* _M_arg; }; + // set void + template<typename _Res> + struct _Setter<_Res, void> + { + static_assert(is_void<_Res>::value, "Only used for promise<void>"); + + typename promise<_Res>::_Ptr_type operator()() const + { return std::move(_M_promise->_M_storage); } + + promise<_Res>* _M_promise; + }; + struct __exception_ptr_tag { }; // set exceptions @@ -494,7 +504,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Used by std::promise to store an exception as the result. typename promise<_Res>::_Ptr_type operator()() const { - _State_baseV2::_S_check(_M_promise->_M_future); _M_promise->_M_storage->_M_error = *_M_ex; return std::move(_M_promise->_M_storage); } @@ -507,6 +516,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _Setter<_Res, _Arg&&> __setter(promise<_Res>* __prom, _Arg&& __arg) { + _S_check(__prom->_M_future); return _Setter<_Res, _Arg&&>{ __prom, std::__addressof(__arg) }; } @@ -514,9 +524,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _Setter<_Res, __exception_ptr_tag> __setter(exception_ptr& __ex, promise<_Res>* __prom) { + _S_check(__prom->_M_future); return _Setter<_Res, __exception_ptr_tag>{ __prom, &__ex }; } + template<typename _Res> + static _Setter<_Res, void> + __setter(promise<_Res>* __prom) + { + _S_check(__prom->_M_future); + return _Setter<_Res, void>{ __prom }; + } + template<typename _Tp> static void _S_check(const shared_ptr<_Tp>& __p) @@ -1014,6 +1033,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef __future_base::_Result<_Res> _Res_type; typedef __future_base::_Ptr<_Res_type> _Ptr_type; template<typename, typename> friend class _State::_Setter; + friend _State; shared_ptr<_State> _M_future; _Ptr_type _M_storage; @@ -1124,6 +1144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef __future_base::_Result<_Res&> _Res_type; typedef __future_base::_Ptr<_Res_type> _Ptr_type; template<typename, typename> friend class _State::_Setter; + friend _State; shared_ptr<_State> _M_future; _Ptr_type _M_storage; @@ -1213,6 +1234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef __future_base::_Result<void> _Res_type; typedef __future_base::_Ptr<_Res_type> _Ptr_type; template<typename, typename> friend class _State::_Setter; + friend _State; shared_ptr<_State> _M_future; _Ptr_type _M_storage; @@ -1273,14 +1295,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return future<void>(_M_future); } // Setting the result - void set_value(); + void + set_value() + { _M_future->_M_set_result(_State::__setter(this)); } void set_exception(exception_ptr __p) { _M_future->_M_set_result(_State::__setter(__p, this)); } void - set_value_at_thread_exit(); + set_value_at_thread_exit() + { _M_future->_M_set_delayed_result(_State::__setter(this), _M_future); } void set_exception_at_thread_exit(exception_ptr __p) @@ -1290,30 +1315,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; - // set void - template<> - struct __future_base::_State_base::_Setter<void, void> - { - promise<void>::_Ptr_type operator()() const - { - _State_base::_S_check(_M_promise->_M_future); - return std::move(_M_promise->_M_storage); - } - - promise<void>* _M_promise; - }; - - inline void - promise<void>::set_value() - { _M_future->_M_set_result(_State::_Setter<void, void>{ this }); } - - inline void - promise<void>::set_value_at_thread_exit() - { - _M_future->_M_set_delayed_result(_State::_Setter<void, void>{this}, - _M_future); - } - template<typename _Ptr_type, typename _Fn, typename _Res> struct __future_base::_Task_setter { diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc b/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc new file mode 100644 index 00000000000..9429a9958d2 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc @@ -0,0 +1,167 @@ +// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-rtems* *-*-darwin* powerpc-ibm-aix* } } +// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* powerpc-ibm-aix* } } +// { dg-require-effective-target c++11 } +// { dg-require-cstdint "" } +// { dg-require-gthreads "" } + +// Copyright (C) 2014-2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// Test set_value_at_thread_exit error conditions + +#include <future> +#include <testsuite_hooks.h> + +void test01() +{ + std::promise<int> p1; + p1.set_value(1); + try + { + p1.set_value_at_thread_exit(2); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::promise_already_satisfied ); + } + try + { + p1.set_exception_at_thread_exit(std::make_exception_ptr(3)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::promise_already_satisfied ); + } + + std::promise<int> p2(std::move(p1)); + try + { + p1.set_value_at_thread_exit(2); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::no_state ); + } + try + { + p1.set_exception_at_thread_exit(std::make_exception_ptr(3)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::no_state ); + } +} + +void test02() +{ + std::promise<int&> p1; + int i = 1; + p1.set_value(i); + try + { + p1.set_value_at_thread_exit(i); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::promise_already_satisfied ); + } + try + { + p1.set_exception_at_thread_exit(std::make_exception_ptr(3)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::promise_already_satisfied ); + } + + std::promise<int&> p2(std::move(p1)); + try + { + int i = 0; + p1.set_value_at_thread_exit(i); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::no_state ); + } + try + { + p1.set_exception_at_thread_exit(std::make_exception_ptr(3)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::no_state ); + } +} + +void test03() +{ + std::promise<void> p1; + int i = 0; + p1.set_value(); + try { + p1.set_value_at_thread_exit(); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::promise_already_satisfied ); + } + try + { + p1.set_exception_at_thread_exit(std::make_exception_ptr(3)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::promise_already_satisfied ); + } + + std::promise<void> p2(std::move(p1)); + try { + p1.set_value_at_thread_exit(); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::no_state ); + } + try + { + p1.set_exception_at_thread_exit(std::make_exception_ptr(3)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY( e.code() == std::future_errc::no_state ); + } +} + +int main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc b/libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc index b753c24ef5e..76343f7f696 100644 --- a/libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc +++ b/libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc @@ -23,6 +23,7 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +// Test that promise::set_exception stores an exception. #include <future> #include <testsuite_hooks.h> @@ -50,8 +51,56 @@ void test01() VERIFY( !f1.valid() ); } +void test02() +{ + bool test = false; + + std::promise<int&> p1; + std::future<int&> f1 = p1.get_future(); + + VERIFY( f1.valid() ); + + p1.set_exception(std::make_exception_ptr(0)); + + try + { + f1.get(); + } + catch (int) + { + test = true; + } + VERIFY( test ); + VERIFY( !f1.valid() ); +} + +void test03() +{ + bool test = false; + + std::promise<void> p1; + std::future<void> f1 = p1.get_future(); + + VERIFY( f1.valid() ); + + p1.set_exception(std::make_exception_ptr(0)); + + try + { + f1.get(); + } + catch (int) + { + test = true; + } + VERIFY( test ); + VERIFY( !f1.valid() ); +} + int main() { test01(); + test02(); + test03(); return 0; } diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc b/libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc index d9850ca9405..951c8e16a68 100644 --- a/libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc +++ b/libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc @@ -23,10 +23,13 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +// Test that promise::set_exception throws when required. #include <future> #include <testsuite_hooks.h> +// Check for promise_already_satisfied error conditions. + void test01() { bool test = false; @@ -85,9 +88,187 @@ void test02() VERIFY( test ); } +void test03() +{ + bool test = false; + + std::promise<int&> p1; + std::future<int&> f1 = p1.get_future(); + + p1.set_exception(std::make_exception_ptr(0)); + + try + { + p1.set_exception(std::make_exception_ptr(1)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == + std::make_error_code(std::future_errc::promise_already_satisfied)); + test = true; + } + + try + { + f1.get(); + test = false; + } + catch(int i) + { + VERIFY( i == 0 ); + } + + VERIFY( test ); +} + +void test04() +{ + bool test = false; + + std::promise<int&> p1; + std::future<int&> f1 = p1.get_future(); + + int i = 2; + p1.set_value(i); + + try + { + p1.set_exception(std::make_exception_ptr(0)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == + std::make_error_code(std::future_errc::promise_already_satisfied)); + test = true; + } + + VERIFY( test ); +} + +void test05() +{ + bool test = false; + + std::promise<void> p1; + std::future<void> f1 = p1.get_future(); + + p1.set_exception(std::make_exception_ptr(0)); + + try + { + p1.set_exception(std::make_exception_ptr(1)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == + std::make_error_code(std::future_errc::promise_already_satisfied)); + test = true; + } + + try + { + f1.get(); + test = false; + } + catch(int i) + { + VERIFY( i == 0 ); + } + + VERIFY( test ); +} + +void test06() +{ + bool test = false; + + std::promise<void> p1; + std::future<void> f1 = p1.get_future(); + + p1.set_value(); + + try + { + p1.set_exception(std::make_exception_ptr(0)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == + std::make_error_code(std::future_errc::promise_already_satisfied)); + test = true; + } + + VERIFY( test ); +} + +// Check for no_state error condition (PR libstdc++/80316) + +void test07() +{ + using namespace std; + + promise<int> p1; + promise<int> p2(std::move(p1)); + try + { + p1.set_exception(std::make_exception_ptr(1)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == make_error_code(future_errc::no_state)); + } +} + +void test08() +{ + using namespace std; + + promise<int&> p1; + promise<int&> p2(std::move(p1)); + try + { + int i = 0; + p1.set_exception(std::make_exception_ptr(1)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == make_error_code(future_errc::no_state)); + } +} + +void test09() +{ + using namespace std; + + promise<void> p1; + promise<void> p2(std::move(p1)); + try + { + p1.set_exception(std::make_exception_ptr(1)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == make_error_code(future_errc::no_state)); + } +} + int main() { test01(); test02(); + test03(); + test04(); + test05(); + test06(); + test07(); + test08(); + test09(); return 0; } diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc b/libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc index 9c308c5e69e..2a3f9b89ce3 100644 --- a/libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc +++ b/libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc @@ -23,10 +23,13 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +// Test that promise::set_value throws when required. #include <future> #include <testsuite_hooks.h> +// Check for promise_already_satisfied error conditions. + void test01() { bool test = false; @@ -81,9 +84,298 @@ void test02() VERIFY( test ); } +void test03() +{ + bool test = false; + + std::promise<int> p1; + std::future<int> f1 = p1.get_future(); + + p1.set_exception(std::make_exception_ptr(4)); + + try + { + p1.set_value(3); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == + std::make_error_code(std::future_errc::promise_already_satisfied)); + test = true; + } + + std::chrono::milliseconds delay(1); + VERIFY( f1.wait_for(delay) == std::future_status::ready ); + test = false; + try + { + f1.get(); + VERIFY( false ); + } + catch (int e) + { + VERIFY(e == 4 ); + test = true; + } + + VERIFY( test ); +} + +void test04() +{ + bool test = false; + + std::promise<int&> p1; + std::future<int&> f1 = p1.get_future(); + + int i = 1; + p1.set_value(i); + + try + { + p1.set_value(i); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == + std::make_error_code(std::future_errc::promise_already_satisfied)); + test = true; + } + + std::chrono::milliseconds delay(1); + VERIFY( f1.wait_for(delay) == std::future_status::ready ); + VERIFY( f1.get() == 1 ); + VERIFY( test ); +} + +void test05() +{ + bool test = false; + + std::promise<int&> p1; + std::future<int&> f1 = p1.get_future(); + + int i = 3; + p1.set_value(i); + + try + { + p1.set_exception(std::make_exception_ptr(4)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == + std::make_error_code(std::future_errc::promise_already_satisfied)); + test = true; + } + + std::chrono::milliseconds delay(1); + VERIFY( f1.wait_for(delay) == std::future_status::ready ); + VERIFY( f1.get() == 3 ); + VERIFY( test ); +} + +void test06() +{ + bool test = false; + + std::promise<int&> p1; + std::future<int&> f1 = p1.get_future(); + + p1.set_exception(std::make_exception_ptr(4)); + + try + { + int i = 3; + p1.set_value(i); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == + std::make_error_code(std::future_errc::promise_already_satisfied)); + test = true; + } + + std::chrono::milliseconds delay(1); + VERIFY( f1.wait_for(delay) == std::future_status::ready ); + test = false; + try + { + f1.get(); + VERIFY( false ); + } + catch (int e) + { + VERIFY(e == 4 ); + test = true; + } + + VERIFY( test ); +} + +void test07() +{ + bool test = false; + + std::promise<void> p1; + std::future<void> f1 = p1.get_future(); + + p1.set_value(); + + try + { + p1.set_value(); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == + std::make_error_code(std::future_errc::promise_already_satisfied)); + test = true; + } + + std::chrono::milliseconds delay(1); + VERIFY( f1.wait_for(delay) == std::future_status::ready ); + f1.get(); + VERIFY( test ); +} + +void test08() +{ + bool test = false; + + std::promise<void> p1; + std::future<void> f1 = p1.get_future(); + + p1.set_value(); + + try + { + p1.set_exception(std::make_exception_ptr(4)); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == + std::make_error_code(std::future_errc::promise_already_satisfied)); + test = true; + } + + std::chrono::milliseconds delay(1); + VERIFY( f1.wait_for(delay) == std::future_status::ready ); + f1.get(); + VERIFY( test ); +} + +void test09() +{ + bool test = false; + + std::promise<void> p1; + std::future<void> f1 = p1.get_future(); + + p1.set_exception(std::make_exception_ptr(4)); + + try + { + p1.set_value(); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == + std::make_error_code(std::future_errc::promise_already_satisfied)); + test = true; + } + + std::chrono::milliseconds delay(1); + VERIFY( f1.wait_for(delay) == std::future_status::ready ); + test = false; + try + { + f1.get(); + VERIFY( false ); + } + catch (int e) + { + VERIFY(e == 4 ); + test = true; + } + + VERIFY( test ); +} + +// Check for no_state error condition (PR libstdc++/80316) + +void test10() +{ + using namespace std; + + promise<int> p1; + promise<int> p2(std::move(p1)); + try + { + p1.set_value(1); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == make_error_code(future_errc::no_state)); + } +} + +void test11() +{ + using namespace std; + + promise<int&> p1; + promise<int&> p2(std::move(p1)); + try + { + int i = 0; + p1.set_value(i); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == make_error_code(future_errc::no_state)); + } +} + +void test12() +{ + using namespace std; + + promise<void> p1; + promise<void> p2(std::move(p1)); + try + { + p1.set_value(); + VERIFY( false ); + } + catch (std::future_error& e) + { + VERIFY(e.code() == make_error_code(future_errc::no_state)); + } +} + int main() { test01(); test02(); + test03(); + test04(); + test05(); + test06(); + test07(); + test08(); + test09(); + test10(); + test11(); + test12(); return 0; } |