• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)50 exception_ptr make_exception_ptr(T v) {
51   return copy_exception(wrap<T>(v));
52 }
53 }
54 
func1(boost::promise<int> p)55 void 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)61 void 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)69 void 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)76 void 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)82 void 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)88 void 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()95 int 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