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)48 boost::exception_ptr make_exception_ptr(T v) {
49   return boost::copy_exception(wrap<T>(v));
50 }
51 
func1(boost::promise<int> p)52 void 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)58 void 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)66 void 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)73 void 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)79 void 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)85 void 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()92 int 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