1 // Copyright (C) 2013 Vicente J. Botet Escriba 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 // <boost/thread/future.hpp> 7 8 // class future<R> 9 10 // R future::get_or(R&&); 11 // R& future<R&>::get_or(R&); 12 13 #define BOOST_THREAD_VERSION 4 14 //#define BOOST_THREAD_USES_LOG 15 #define BOOST_THREAD_USES_LOG_THREAD_ID 16 #include <boost/thread/detail/log.hpp> 17 18 #include <boost/thread/future.hpp> 19 #include <boost/thread/thread.hpp> 20 #include <boost/core/ref.hpp> 21 #include <boost/detail/lightweight_test.hpp> 22 23 #if defined BOOST_THREAD_USES_CHRONO 24 25 #ifdef BOOST_MSVC 26 #pragma warning(disable: 4127) // conditional expression is constant 27 #endif 28 29 template <typename T> 30 struct wrap 31 { wrapwrap32 wrap(T const& v) : value(v){} 33 T value; 34 35 }; 36 37 template <typename T> make_exception_ptr(T v)38boost::exception_ptr make_exception_ptr(T v) { 39 return boost::copy_exception(wrap<T>(v)); 40 } 41 func1(boost::promise<int> p)42void func1(boost::promise<int> p) 43 { 44 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 45 p.set_value(3); 46 } 47 func2(boost::promise<int> p)48void func2(boost::promise<int> p) 49 { 50 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 51 p.set_exception(::make_exception_ptr(3)); 52 } 53 54 int j = 0; 55 func3(boost::promise<int &> p)56void func3(boost::promise<int&> p) 57 { 58 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 59 j = 5; 60 p.set_value(j); 61 } 62 func4(boost::promise<int &> p)63void func4(boost::promise<int&> p) 64 { 65 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 66 p.set_exception(::make_exception_ptr(3.5)); 67 } 68 func5(boost::promise<void> p)69void func5(boost::promise<void> p) 70 { 71 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 72 p.set_value(); 73 } 74 func6(boost::promise<void> p)75void func6(boost::promise<void> p) 76 { 77 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 78 p.set_exception(::make_exception_ptr(4)); 79 } 80 81 main()82int main() 83 { 84 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 85 { 86 typedef int T; 87 { 88 boost::promise<T> p; 89 boost::future<T> f = p.get_future(); 90 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 91 boost::thread(func1, boost::move(p)).detach(); 92 #else 93 p.set_value(3); 94 #endif 95 BOOST_TEST(f.valid()); 96 BOOST_TEST(f.get_or(4) == 3); 97 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 98 BOOST_TEST(!f.valid()); 99 #endif 100 } 101 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 102 { 103 boost::promise<T> p; 104 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 105 boost::future<T> f = p.get_future(); 106 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 107 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 108 boost::thread(func2, boost::move(p)).detach(); 109 #else 110 p.set_exception(::make_exception_ptr(3)); 111 #endif 112 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 113 try 114 { 115 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 116 BOOST_TEST(f.valid()); 117 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 118 BOOST_TEST(f.get_or(4) == 4); 119 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 120 } 121 catch (...) 122 { 123 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 124 BOOST_TEST(false); 125 } 126 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 127 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 128 BOOST_TEST(!f.valid()); 129 #endif 130 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 131 } 132 } 133 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 134 { 135 typedef int& T; 136 { 137 boost::promise<T> p; 138 boost::future<T> f = p.get_future(); 139 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 140 boost::thread(func3, boost::move(p)).detach(); 141 #else 142 int j=5; 143 p.set_value(j); 144 #endif 145 BOOST_TEST(f.valid()); 146 int k=4; 147 BOOST_TEST(f.get_or(boost::ref(k)) == 5); 148 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 149 BOOST_TEST(!f.valid()); 150 #endif 151 } 152 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 153 { 154 boost::promise<T> p; 155 boost::future<T> f = p.get_future(); 156 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 157 boost::thread(func4, boost::move(p)).detach(); 158 #else 159 p.set_exception(::make_exception_ptr(3.5)); 160 #endif 161 try 162 { 163 BOOST_TEST(f.valid()); 164 int j=4; 165 BOOST_TEST(f.get_or(boost::ref(j)) == 4); 166 } 167 catch (...) 168 { 169 BOOST_TEST(false); 170 } 171 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 172 BOOST_TEST(!f.valid()); 173 #endif 174 } 175 } 176 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 177 178 179 return boost::report_errors(); 180 } 181 182 #else 183 #error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" 184 #endif 185