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 // class packaged_task<R>
17
18 // void operator()();
19
20
21 //#define BOOST_THREAD_VERSION 3
22 #define BOOST_THREAD_VERSION 4
23
24 #include <boost/thread/future.hpp>
25 #include <boost/detail/lightweight_test.hpp>
26
27 #if defined BOOST_THREAD_USES_CHRONO
28
29 #if BOOST_THREAD_VERSION == 4
30 #define BOOST_THREAD_DETAIL_SIGNATURE double()
31 #else
32 #define BOOST_THREAD_DETAIL_SIGNATURE double
33 #endif
34
35 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
36 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
37 #define BOOST_THREAD_DETAIL_SIGNATURE_2 double(int, char)
38 #define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 + 3 +'a'
39 #else
40 #define BOOST_THREAD_DETAIL_SIGNATURE_2 double()
41 #define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5
42 #endif
43 #else
44 #define BOOST_THREAD_DETAIL_SIGNATURE_2 double
45 #define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5
46 #endif
47 class E : public std::exception
48 {
49 public:
50 long data;
E(long i)51 explicit E(long i) :
52 data(i)
53 {
54 }
55
what() const56 const char* what() const throw() { return ""; }
57
~E()58 ~E() throw() {}
59 };
60
61 class A
62 {
63 long data_;
64
65 public:
A(long i)66 explicit A(long i) :
67 data_(i)
68 {
69 }
70
operator ()() const71 long operator()() const
72 {
73 if (data_ == 0) BOOST_THROW_EXCEPTION(E(6));
74 return data_;
75 }
operator ()(long i,long j) const76 long operator()(long i, long j) const
77 {
78 if (j == 'z') BOOST_THROW_EXCEPTION(E(6));
79 return data_ + i + j;
80 }
~A()81 ~A() {}
82 };
83
func0(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p)84 void func0(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p)
85 {
86 boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
87 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
88 p(3, 'a');
89 #else
90 p();
91 #endif
92 }
93
func1(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p)94 void func1(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p)
95 {
96 boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
97 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
98 p(3, 'z');
99 #else
100 p();
101 #endif
102 }
103
func2(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p)104 void func2(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p)
105 {
106 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
107 p(3, 'a');
108 #else
109 p();
110 #endif
111 try
112 {
113 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
114 p(3, 'c');
115 #else
116 p();
117 #endif
118 }
119 catch (const boost::future_error& e)
120 {
121 BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
122 }
123 }
124
func3(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p)125 void func3(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p)
126 {
127 try
128 {
129 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
130 p(3, 'a');
131 #else
132 p();
133 #endif
134 }
135 catch (const boost::future_error& e)
136 {
137 BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state));
138 }
139 }
140
main()141 int main()
142 {
143 {
144 boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(A(5));
145 boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
146 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
147 boost::thread(func0, boost::move(p)).detach();
148 #else
149 //p();
150 #endif
151 //BOOST_TEST(f.get() == 5.0);
152 }
153 {
154 boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(A(0));
155 boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
156 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
157 boost::thread(func1, boost::move(p)).detach();
158 #endif
159 try
160 {
161 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
162 #else
163 p();
164 #endif
165 f.get();
166 BOOST_TEST(false);
167 }
168 catch (const E& e)
169 {
170 BOOST_TEST(e.data == 6);
171 }
172 catch (...)
173 {
174 BOOST_TEST(false);
175 }
176 }
177 {
178 boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(A(5));
179 boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
180 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
181 boost::thread t(func2, boost::move(p));
182 #else
183 p();
184 #endif
185 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
186 BOOST_TEST(f.get() == 105);
187 t.join();
188 #else
189 BOOST_TEST(f.get() == 5.0);
190 #endif
191 }
192 {
193 boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p;
194 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
195 boost::thread t(func3, boost::move(p));
196 t.join();
197 #else
198 try
199 {
200 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
201 p(3, 'a');
202 #else
203 p();
204 #endif
205 }
206 catch (const boost::future_error& e)
207 {
208 BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state));
209 }
210 #endif
211 }
212
213 return boost::report_errors();
214 }
215
216 #else
217 #error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
218 #endif
219