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