From e598796eafc517031e478ae0178ef67615deea79 Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Sat, 2 May 2015 16:29:06 +0200 Subject: [PATCH] Add assertion on future continuation parameter is ready. As noted in #11256, there some serious issues with the parameter passed and with lock on locked mutextes :(. --- example/executor.cpp | 9 +- test/Jamfile.v2 | 12 ++- .../futures/future/then_deferred_pass.cpp | 4 + .../futures/future/then_executor_pass.cpp | 3 + test/test_10963.cpp | 17 ++++ test/test_10964.cpp | 85 ++++++++++++++++++- 6 files changed, 123 insertions(+), 7 deletions(-) diff --git a/example/executor.cpp b/example/executor.cpp index 10c77a00..69de41f0 100644 --- a/example/executor.cpp +++ b/example/executor.cpp @@ -27,8 +27,10 @@ #include #include #include +#include -boost::future p(boost::future) { +boost::future p(boost::future f) { + assert(f.is_ready()); return boost::make_ready_future(); } @@ -156,10 +158,13 @@ int main() && defined BOOST_THREAD_PROVIDES_EXECUTORS \ && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + boost::basic_thread_pool executor; // compiles boost::make_ready_future().then(&p); - boost::basic_thread_pool executor; + // ?? + boost::make_ready_future().then(executor, &p); + // doesn't compile boost::make_ready_future().then(executor, &p); #endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 22f52650..0c8fd430 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -947,11 +947,19 @@ rule thread-compile ( sources : reqs * : name ) [ thread-run2-noit ./experimental/parallel/v2/task_region_pass.cpp : task_region_p ] ; - explicit ts_ ; - test-suite ts_ + explicit ts_other ; + test-suite ts_other : [ thread-run2 ../example/this_executor.cpp : ex_this_executor ] [ thread-run2 ../example/default_executor.cpp : ex_default_executor ] ; + explicit ts_ ; + test-suite ts_ + : + #[ thread-compile test_10963.cpp : : test_10963_c ] + #[ thread-run test_10964.cpp ] + ; + + } diff --git a/test/sync/futures/future/then_deferred_pass.cpp b/test/sync/futures/future/then_deferred_pass.cpp index 455610f4..0a7848de 100644 --- a/test/sync/futures/future/then_deferred_pass.cpp +++ b/test/sync/futures/future/then_deferred_pass.cpp @@ -17,6 +17,7 @@ #include #include +#include #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION @@ -31,6 +32,8 @@ int p1() int p2(boost::future f) { + assert(f.is_ready()); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; BOOST_TEST(f.valid()); int i = f.get(); @@ -41,6 +44,7 @@ int p2(boost::future f) void p3(boost::future f) { + assert(f.is_ready()); BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; BOOST_TEST(f.valid()); int i = f.get(); diff --git a/test/sync/futures/future/then_executor_pass.cpp b/test/sync/futures/future/then_executor_pass.cpp index c3c2354b..8703fe51 100644 --- a/test/sync/futures/future/then_executor_pass.cpp +++ b/test/sync/futures/future/then_executor_pass.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION @@ -34,6 +35,7 @@ int p1() int p2(boost::future f) { + assert(f.is_ready()); BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; BOOST_TEST(f.valid()); int i = f.get(); @@ -44,6 +46,7 @@ int p2(boost::future f) void p3(boost::future f) { + assert(f.is_ready()); BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; BOOST_TEST(f.valid()); int i = f.get(); diff --git a/test/test_10963.cpp b/test/test_10963.cpp index b918b55d..1ec8d6cf 100644 --- a/test/test_10963.cpp +++ b/test/test_10963.cpp @@ -8,9 +8,12 @@ #if ! defined BOOST_NO_CXX11_DECLTYPE #define BOOST_RESULT_OF_USE_DECLTYPE #endif +#define BOOST_THREAD_PROVIDES_EXECUTORS #include #include +#include +#include struct TestCallback @@ -19,12 +22,14 @@ struct TestCallback result_type operator()(boost::future future) const { + assert(future.is_ready()); future.get(); return boost::make_ready_future(); } result_type operator()(boost::future > future) const { + assert(future.is_ready()); future.get(); return boost::make_ready_future(); } @@ -33,12 +38,24 @@ struct TestCallback int main() { #if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS + { boost::promise test_promise; boost::future test_future(test_promise.get_future()); auto f1 = test_future.then(TestCallback()); BOOST_STATIC_ASSERT(std::is_same > >::value); auto f2 = f1.then(TestCallback()); BOOST_STATIC_ASSERT(std::is_same > >::value); + } + { + boost::basic_thread_pool executor; + boost::promise test_promise; + boost::future test_future(test_promise.get_future()); + auto f1 = test_future.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same > >::value); + auto f2 = f1.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same > >::value); + + } #endif return 0; } diff --git a/test/test_10964.cpp b/test/test_10964.cpp index b8cc7b5c..0dbf4bb1 100644 --- a/test/test_10964.cpp +++ b/test/test_10964.cpp @@ -8,9 +8,12 @@ #if ! defined BOOST_NO_CXX11_DECLTYPE #define BOOST_RESULT_OF_USE_DECLTYPE #endif +#define BOOST_THREAD_PROVIDES_EXECUTORS #include #include +#include +#include struct TestCallback { @@ -18,13 +21,23 @@ struct TestCallback result_type operator()(boost::future future) const { - future.get(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + future.wait(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; return boost::make_ready_future(); } result_type operator()(boost::future > future) const { - future.get(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.get().is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + //boost::future ff = future.get(); + return boost::make_ready_future(); } }; @@ -51,13 +64,23 @@ int main() f2.wait(); } std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same > >::value); + boost::future f2 = f1.get(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + } +#if 0 + // @fixme this doesn't works. + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; { auto f1 = boost::make_ready_future().then(TestCallback()); BOOST_STATIC_ASSERT(std::is_same > >::value); auto f2 = f1.unwrap(); BOOST_STATIC_ASSERT(std::is_same >::value); auto f3 = f2.then(TestCallback()); - BOOST_STATIC_ASSERT(std::is_same > >::value); + BOOST_STATIC_ASSERT(std::is_same > >::value); f3.wait(); } std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; @@ -71,6 +94,62 @@ int main() f.then( TestCallback()).unwrap().then(TestCallback()).get(); } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same > >::value); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + auto f3 = f1.then(TestCallback()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + BOOST_STATIC_ASSERT(std::is_same > >::value); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + f3.wait(); + } + + + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + boost::basic_thread_pool executor; + + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + auto f1 = boost::make_ready_future().then(executor, TestCallback()); + //BOOST_STATIC_ASSERT(std::is_same > >::value); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + auto f3 = f1.then(executor, TestCallback()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + BOOST_STATIC_ASSERT(std::is_same > >::value); + f3.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + boost::basic_thread_pool executor; + + auto f1 = boost::make_ready_future().then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same > >::value); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + auto f2 = f1.unwrap(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + + BOOST_STATIC_ASSERT(std::is_same >::value); + auto f3 = f2.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same > >::value); + f3.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + boost::basic_thread_pool executor; + + auto f1 = boost::make_ready_future().then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same > >::value); + auto f2 = f1.unwrap(); + BOOST_STATIC_ASSERT(std::is_same >::value); + auto f3 = f2.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same > >::value); + f3.wait(); + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + #endif return 0; }