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