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 template <typename T> 40 struct wrap 41 { wrapwrap42 wrap(T const& v) : value(v){} 43 T value; 44 45 }; 46 47 template <typename T> make_exception_ptr(T v)48boost::exception_ptr make_exception_ptr(T v) { 49 return boost::copy_exception(wrap<T>(v)); 50 } 51 func1(boost::promise<int> p)52void func1(boost::promise<int> p) 53 { 54 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 55 p.set_value(3); 56 } 57 func2(boost::promise<int> p)58void func2(boost::promise<int> p) 59 { 60 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 61 p.set_exception(::make_exception_ptr(3)); 62 } 63 64 int j = 0; 65 func3(boost::promise<int &> p)66void func3(boost::promise<int&> p) 67 { 68 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 69 j = 5; 70 p.set_value(j); 71 } 72 func4(boost::promise<int &> p)73void func4(boost::promise<int&> p) 74 { 75 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 76 p.set_exception(::make_exception_ptr(3.5)); 77 } 78 func5(boost::promise<void> p)79void func5(boost::promise<void> p) 80 { 81 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 82 p.set_value(); 83 } 84 func6(boost::promise<void> p)85void func6(boost::promise<void> p) 86 { 87 boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); 88 p.set_exception(::make_exception_ptr(4)); 89 } 90 91 main()92int main() 93 { 94 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 95 { 96 typedef int T; 97 { 98 boost::promise<T> p; 99 boost::future<T> f = p.get_future(); 100 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 101 boost::thread(func1, boost::move(p)).detach(); 102 #else 103 p.set_value(3); 104 #endif 105 BOOST_TEST(f.valid()); 106 BOOST_TEST(f.get() == 3); 107 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 108 BOOST_TEST(!f.valid()); 109 #endif 110 } 111 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 112 { 113 boost::promise<T> p; 114 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 115 boost::future<T> f = p.get_future(); 116 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 117 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 118 boost::thread(func2, boost::move(p)).detach(); 119 #else 120 p.set_exception(::make_exception_ptr(3)); 121 #endif 122 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 123 try 124 { 125 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 126 BOOST_TEST(f.valid()); 127 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 128 BOOST_TEST(f.get() == 3); 129 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 130 BOOST_TEST(false); 131 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 132 } 133 catch (::wrap<int> const& i) 134 { 135 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 136 BOOST_TEST(i.value == 3); 137 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 138 } 139 catch (...) 140 { 141 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 142 BOOST_TEST(false); 143 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 144 } 145 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 146 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 147 BOOST_TEST(!f.valid()); 148 #endif 149 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 150 } 151 } 152 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 153 { 154 typedef int& T; 155 { 156 boost::promise<T> p; 157 boost::future<T> f = p.get_future(); 158 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 159 boost::thread(func3, boost::move(p)).detach(); 160 #else 161 int j=5; 162 p.set_value(j); 163 #endif 164 BOOST_TEST(f.valid()); 165 BOOST_TEST(f.get() == 5); 166 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 167 BOOST_TEST(!f.valid()); 168 #endif 169 } 170 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 171 { 172 boost::promise<T> p; 173 boost::future<T> f = p.get_future(); 174 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 175 boost::thread(func4, boost::move(p)).detach(); 176 #else 177 p.set_exception(::make_exception_ptr(3.5)); 178 #endif 179 try 180 { 181 BOOST_TEST(f.valid()); 182 BOOST_TEST(f.get() == 3); 183 BOOST_TEST(false); 184 } 185 catch (::wrap<double> const& i) 186 { 187 BOOST_TEST(i.value == 3.5); 188 } 189 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 190 BOOST_TEST(!f.valid()); 191 #endif 192 } 193 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 194 { 195 boost::promise<T> p; 196 boost::future<T> f = p.get_future(); 197 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 198 boost::thread(func4, boost::move(p)).detach(); 199 #else 200 p.set_exception(::make_exception_ptr(3.5)); 201 #endif 202 try 203 { 204 BOOST_TEST(f.valid()); 205 boost::exception_ptr ptr = f.get_exception_ptr(); 206 } 207 catch (...) 208 { 209 BOOST_TEST(false); 210 } 211 BOOST_TEST(f.valid()); 212 } 213 } 214 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 215 216 typedef void T; 217 { 218 boost::promise<T> p; 219 boost::future<T> f = p.get_future(); 220 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 221 boost::thread(func5, boost::move(p)).detach(); 222 #else 223 p.set_value(); 224 #endif 225 BOOST_TEST(f.valid()); 226 f.get(); 227 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 228 BOOST_TEST(!f.valid()); 229 #endif 230 } 231 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 232 { 233 boost::promise<T> p; 234 boost::future<T> f = p.get_future(); 235 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) 236 boost::thread(func6, boost::move(p)).detach(); 237 #else 238 p.set_exception(::make_exception_ptr(4)); 239 #endif 240 try 241 { 242 BOOST_TEST(f.valid()); 243 f.get(); 244 BOOST_TEST(false); 245 } 246 catch (::wrap<int> const& i) 247 { 248 BOOST_TEST(i.value == 4); 249 } 250 catch (...) 251 { 252 BOOST_TEST(false); 253 } 254 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET 255 BOOST_TEST(!f.valid()); 256 #endif 257 } 258 BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; 259 260 return boost::report_errors(); 261 } 262 263 #else 264 #error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" 265 #endif 266