1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // Copyright (C) 2011 Vicente J. Botet Escriba 11 // 12 // Distributed under the Boost Software License, Version 1.0. (See accompanying 13 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 14 15 // <boost/thread/future.hpp> 16 17 // class future<R> 18 19 // const R& future::get(); 20 // R& future<R&>::get(); 21 // void future<void>::get(); 22 23 //#define BOOST_THREAD_VERSION 3 24 #define BOOST_THREAD_VERSION 4 25 //#define BOOST_THREAD_USES_LOG 26 #define BOOST_THREAD_USES_LOG_THREAD_ID 27 #include <boost/thread/detail/log.hpp> 28 29 #include <boost/thread/future.hpp> 30 #include <boost/thread/thread.hpp> 31 #include <boost/detail/lightweight_test.hpp> 32 33 #if defined BOOST_THREAD_USES_CHRONO 34 35 #ifdef BOOST_MSVC 36 #pragma warning(disable: 4127) // conditional expression is constant 37 #endif 38 39 namespace boost 40 { 41 template <typename T> 42 struct wrap 43 { wrapboost::wrap44 wrap(T const& v) : value(v){} 45 T value; 46 47 }; 48 49 template <typename T> make_exception_ptr(T v)50exception_ptr make_exception_ptr(T v) { 51 return copy_exception(wrap<T>(v)); 52 } 53 } 54 func1(boost::promise<int> p)55void func1(boost::promise<int> p) 56 { 57 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 58 p.set_value(3); 59 } 60 func2(boost::promise<int> p)61void func2(boost::promise<int> p) 62 { 63 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 64 p.set_exception(boost::make_exception_ptr(3)); 65 } 66 67 int j = 0; 68 func3(boost::promise<int &> p)69void func3(boost::promise<int&> p) 70 { 71 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 72 j = 5; 73 p.set_value(j); 74 } 75 func4(boost::promise<int &> p)76void func4(boost::promise<int&> p) 77 { 78 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 79 p.set_exception(boost::make_exception_ptr(3.5)); 80 } 81 func5(boost::promise<void> p)82void func5(boost::promise<void> p) 83 { 84 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 85 p.set_value(); 86 } 87 func6(boost::promise<void> p)88void func6(boost::promise<void> p) 89 { 90 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 91 p.set_exception(boost::make_exception_ptr(4)); 92 } 93 94 main()95int main() 96 { 97 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 98 { 99 typedef int T; 100 { 101 boost::promise<T> p; 102 boost::future<T> f = p.get_future(); 103 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 104 boost::thread(func1, boost::move(p)).detach(); 105 #else 106 p.set_value(3); 107 #endif 108 BOOST_TEST(f.valid()); 109 BOOST_TEST(f.get() == 3); 110 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 111 BOOST_TEST(!f.valid()); 112 #endif 113 } 114 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 115 { 116 boost::promise<T> p; 117 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 118 boost::future<T> f = p.get_future(); 119 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 120 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 121 boost::thread(func2, boost::move(p)).detach(); 122 #else 123 p.set_exception(boost::make_exception_ptr(3)); 124 #endif 125 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 126 try 127 { 128 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 129 BOOST_TEST(f.valid()); 130 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 131 BOOST_TEST(f.get() == 3); 132 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 133 BOOST_TEST(false); 134 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 135 } 136 catch (boost::wrap<int> const& i) 137 { 138 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 139 BOOST_TEST(i.value == 3); 140 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 141 } 142 catch (...) 143 { 144 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 145 BOOST_TEST(false); 146 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 147 } 148 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 149 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 150 BOOST_TEST(!f.valid()); 151 #endif 152 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 153 } 154 } 155 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 156 { 157 typedef int& T; 158 { 159 boost::promise<T> p; 160 boost::future<T> f = p.get_future(); 161 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 162 boost::thread(func3, boost::move(p)).detach(); 163 #else 164 int j=5; 165 p.set_value(j); 166 #endif 167 BOOST_TEST(f.valid()); 168 BOOST_TEST(f.get() == 5); 169 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 170 BOOST_TEST(!f.valid()); 171 #endif 172 } 173 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 174 { 175 boost::promise<T> p; 176 boost::future<T> f = p.get_future(); 177 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 178 boost::thread(func4, boost::move(p)).detach(); 179 #else 180 p.set_exception(boost::make_exception_ptr(3.5)); 181 #endif 182 try 183 { 184 BOOST_TEST(f.valid()); 185 BOOST_TEST(f.get() == 3); 186 BOOST_TEST(false); 187 } 188 catch (boost::wrap<double> const& i) 189 { 190 BOOST_TEST(i.value == 3.5); 191 } 192 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 193 BOOST_TEST(!f.valid()); 194 #endif 195 } 196 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 197 { 198 boost::promise<T> p; 199 boost::future<T> f = p.get_future(); 200 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 201 boost::thread(func4, boost::move(p)).detach(); 202 #else 203 p.set_exception(boost::make_exception_ptr(3.5)); 204 #endif 205 try 206 { 207 BOOST_TEST(f.valid()); 208 boost::exception_ptr ptr = f.get_exception_ptr(); 209 } 210 catch (...) 211 { 212 BOOST_TEST(false); 213 } 214 BOOST_TEST(f.valid()); 215 } 216 } 217 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 218 219 typedef void T; 220 { 221 boost::promise<T> p; 222 boost::future<T> f = p.get_future(); 223 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 224 boost::thread(func5, boost::move(p)).detach(); 225 #else 226 p.set_value(); 227 #endif 228 BOOST_TEST(f.valid()); 229 f.get(); 230 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 231 BOOST_TEST(!f.valid()); 232 #endif 233 } 234 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 235 { 236 boost::promise<T> p; 237 boost::future<T> f = p.get_future(); 238 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 239 boost::thread(func6, boost::move(p)).detach(); 240 #else 241 p.set_exception(boost::make_exception_ptr(4)); 242 #endif 243 try 244 { 245 BOOST_TEST(f.valid()); 246 f.get(); 247 BOOST_TEST(false); 248 } 249 catch (boost::wrap<int> const& i) 250 { 251 BOOST_TEST(i.value == 4); 252 } 253 catch (...) 254 { 255 BOOST_TEST(false); 256 } 257 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 258 BOOST_TEST(!f.valid()); 259 #endif 260 } 261 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 262 263 return boost::report_errors(); 264 } 265 266 #else 267 #error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" 268 #endif 269