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 namespace boost 30 { 31 template <typename T> 32 struct wrap 33 { wrapboost::wrap34 wrap(T const& v) : value(v){} 35 T value; 36 37 }; 38 39 template <typename T> make_exception_ptr(T v)40exception_ptr make_exception_ptr(T v) { 41 return copy_exception(wrap<T>(v)); 42 } 43 } 44 func1(boost::promise<int> p)45void func1(boost::promise<int> p) 46 { 47 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 48 p.set_value(3); 49 } 50 func2(boost::promise<int> p)51void func2(boost::promise<int> p) 52 { 53 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 54 p.set_exception(boost::make_exception_ptr(3)); 55 } 56 57 int j = 0; 58 func3(boost::promise<int &> p)59void func3(boost::promise<int&> p) 60 { 61 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 62 j = 5; 63 p.set_value(j); 64 } 65 func4(boost::promise<int &> p)66void func4(boost::promise<int&> p) 67 { 68 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 69 p.set_exception(boost::make_exception_ptr(3.5)); 70 } 71 func5(boost::promise<void> p)72void func5(boost::promise<void> p) 73 { 74 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 75 p.set_value(); 76 } 77 func6(boost::promise<void> p)78void func6(boost::promise<void> p) 79 { 80 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 81 p.set_exception(boost::make_exception_ptr(4)); 82 } 83 84 main()85int main() 86 { 87 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 88 { 89 typedef int T; 90 { 91 boost::promise<T> p; 92 boost::future<T> f = p.get_future(); 93 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 94 boost::thread(func1, boost::move(p)).detach(); 95 #else 96 p.set_value(3); 97 #endif 98 BOOST_TEST(f.valid()); 99 BOOST_TEST(f.get_or(4) == 3); 100 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 101 BOOST_TEST(!f.valid()); 102 #endif 103 } 104 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 105 { 106 boost::promise<T> p; 107 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 108 boost::future<T> f = p.get_future(); 109 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 110 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 111 boost::thread(func2, boost::move(p)).detach(); 112 #else 113 p.set_exception(boost::make_exception_ptr(3)); 114 #endif 115 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 116 try 117 { 118 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 119 BOOST_TEST(f.valid()); 120 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 121 BOOST_TEST(f.get_or(4) == 4); 122 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 123 } 124 catch (...) 125 { 126 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 127 BOOST_TEST(false); 128 } 129 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 130 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 131 BOOST_TEST(!f.valid()); 132 #endif 133 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 134 } 135 } 136 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 137 { 138 typedef int& T; 139 { 140 boost::promise<T> p; 141 boost::future<T> f = p.get_future(); 142 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 143 boost::thread(func3, boost::move(p)).detach(); 144 #else 145 int j=5; 146 p.set_value(j); 147 #endif 148 BOOST_TEST(f.valid()); 149 int k=4; 150 BOOST_TEST(f.get_or(boost::ref(k)) == 5); 151 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 152 BOOST_TEST(!f.valid()); 153 #endif 154 } 155 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 156 { 157 boost::promise<T> p; 158 boost::future<T> f = p.get_future(); 159 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 160 boost::thread(func4, boost::move(p)).detach(); 161 #else 162 p.set_exception(boost::make_exception_ptr(3.5)); 163 #endif 164 try 165 { 166 BOOST_TEST(f.valid()); 167 int j=4; 168 BOOST_TEST(f.get_or(boost::ref(j)) == 4); 169 } 170 catch (...) 171 { 172 BOOST_TEST(false); 173 } 174 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 175 BOOST_TEST(!f.valid()); 176 #endif 177 } 178 } 179 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 180 181 182 return boost::report_errors(); 183 } 184 185 #else 186 #error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" 187 #endif 188