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