Chris@102
|
1 #ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP
|
Chris@102
|
2 #define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP
|
Chris@102
|
3
|
Chris@102
|
4 //////////////////////////////////////////////////////////////////////////////
|
Chris@102
|
5 //
|
Chris@102
|
6 // (C) Copyright Vicente J. Botet Escriba 2014-2015. Distributed under the Boost
|
Chris@102
|
7 // Software License, Version 1.0. (See accompanying file
|
Chris@102
|
8 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
9 //
|
Chris@102
|
10 // See http://www.boost.org/libs/thread for documentation.
|
Chris@102
|
11 //
|
Chris@102
|
12 //////////////////////////////////////////////////////////////////////////////
|
Chris@102
|
13 #include <boost/thread/detail/config.hpp>
|
Chris@102
|
14
|
Chris@102
|
15 #include <boost/thread/future.hpp>
|
Chris@102
|
16 #if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@102
|
17 #include <boost/thread/executors/basic_thread_pool.hpp>
|
Chris@102
|
18 #endif
|
Chris@102
|
19 #include <boost/thread/experimental/exception_list.hpp>
|
Chris@102
|
20 #include <boost/thread/experimental/parallel/v2/inline_namespace.hpp>
|
Chris@102
|
21 #include <boost/thread/detail/move.hpp>
|
Chris@102
|
22
|
Chris@102
|
23 #include <boost/config/abi_prefix.hpp>
|
Chris@102
|
24
|
Chris@102
|
25 #define BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
Chris@102
|
26
|
Chris@102
|
27 namespace boost
|
Chris@102
|
28 {
|
Chris@102
|
29 namespace experimental
|
Chris@102
|
30 {
|
Chris@102
|
31 namespace parallel
|
Chris@102
|
32 {
|
Chris@102
|
33 BOOST_THREAD_INLINE_NAMESPACE(v2)
|
Chris@102
|
34 {
|
Chris@102
|
35 class BOOST_SYMBOL_VISIBLE task_canceled_exception: public std::exception
|
Chris@102
|
36 {
|
Chris@102
|
37 public:
|
Chris@102
|
38 //task_canceled_exception() BOOST_NOEXCEPT {}
|
Chris@102
|
39 //task_canceled_exception(const task_canceled_exception&) BOOST_NOEXCEPT {}
|
Chris@102
|
40 //task_canceled_exception& operator=(const task_canceled_exception&) BOOST_NOEXCEPT {}
|
Chris@102
|
41 virtual const char* what() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@102
|
42 { return "task_canceled_exception";}
|
Chris@102
|
43 };
|
Chris@102
|
44
|
Chris@102
|
45 template <class Executor>
|
Chris@102
|
46 class task_region_handle_gen;
|
Chris@102
|
47
|
Chris@102
|
48 namespace detail
|
Chris@102
|
49 {
|
Chris@102
|
50 void handle_task_region_exceptions(exception_list& errors)
|
Chris@102
|
51 {
|
Chris@102
|
52 try {
|
Chris@102
|
53 throw;
|
Chris@102
|
54 }
|
Chris@102
|
55 #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
Chris@102
|
56 catch (task_canceled_exception& ex)
|
Chris@102
|
57 {
|
Chris@102
|
58 }
|
Chris@102
|
59 #endif
|
Chris@102
|
60 catch (exception_list const& el)
|
Chris@102
|
61 {
|
Chris@102
|
62 for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it)
|
Chris@102
|
63 {
|
Chris@102
|
64 boost::exception_ptr const& e = *it;
|
Chris@102
|
65 try {
|
Chris@102
|
66 rethrow_exception(e);
|
Chris@102
|
67 }
|
Chris@102
|
68 catch (...)
|
Chris@102
|
69 {
|
Chris@102
|
70 handle_task_region_exceptions(errors);
|
Chris@102
|
71 }
|
Chris@102
|
72 }
|
Chris@102
|
73 }
|
Chris@102
|
74 catch (...)
|
Chris@102
|
75 {
|
Chris@102
|
76 errors.add(boost::current_exception());
|
Chris@102
|
77 }
|
Chris@102
|
78 }
|
Chris@102
|
79
|
Chris@102
|
80 #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
Chris@102
|
81 template <class TRH, class F>
|
Chris@102
|
82 struct wrapped
|
Chris@102
|
83 {
|
Chris@102
|
84 TRH& tr;
|
Chris@102
|
85 F f;
|
Chris@102
|
86 wrapped(TRH& tr, BOOST_THREAD_RV_REF(F) f) : tr(tr), f(move(f))
|
Chris@102
|
87 {}
|
Chris@102
|
88 void operator()()
|
Chris@102
|
89 {
|
Chris@102
|
90 try
|
Chris@102
|
91 {
|
Chris@102
|
92 f();
|
Chris@102
|
93 }
|
Chris@102
|
94 catch (...)
|
Chris@102
|
95 {
|
Chris@102
|
96 lock_guard<mutex> lk(tr.mtx);
|
Chris@102
|
97 tr.canceled = true;
|
Chris@102
|
98 throw;
|
Chris@102
|
99 }
|
Chris@102
|
100 }
|
Chris@102
|
101 };
|
Chris@102
|
102 #endif
|
Chris@102
|
103 }
|
Chris@102
|
104
|
Chris@102
|
105 template <class Executor>
|
Chris@102
|
106 class task_region_handle_gen
|
Chris@102
|
107 {
|
Chris@102
|
108 private:
|
Chris@102
|
109 // Private members and friends
|
Chris@102
|
110 #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
Chris@102
|
111 template <class TRH, class F>
|
Chris@102
|
112 friend struct detail::wrapped;
|
Chris@102
|
113 #endif
|
Chris@102
|
114 template <typename F>
|
Chris@102
|
115 friend void task_region(BOOST_THREAD_FWD_REF(F) f);
|
Chris@102
|
116 template<typename F>
|
Chris@102
|
117 friend void task_region_final(BOOST_THREAD_FWD_REF(F) f);
|
Chris@102
|
118 template <class Ex, typename F>
|
Chris@102
|
119 friend void task_region(Ex&, BOOST_THREAD_FWD_REF(F) f);
|
Chris@102
|
120 template<class Ex, typename F>
|
Chris@102
|
121 friend void task_region_final(Ex&, BOOST_THREAD_FWD_REF(F) f);
|
Chris@102
|
122
|
Chris@102
|
123 void wait_all()
|
Chris@102
|
124 {
|
Chris@102
|
125 wait_for_all(group.begin(), group.end());
|
Chris@102
|
126
|
Chris@102
|
127 for (group_type::iterator it = group.begin(); it != group.end(); ++it)
|
Chris@102
|
128 {
|
Chris@102
|
129 future<void>& f = *it;
|
Chris@102
|
130 if (f.has_exception())
|
Chris@102
|
131 {
|
Chris@102
|
132 try
|
Chris@102
|
133 {
|
Chris@102
|
134 boost::rethrow_exception(f.get_exception_ptr());
|
Chris@102
|
135 }
|
Chris@102
|
136 catch (...)
|
Chris@102
|
137 {
|
Chris@102
|
138 detail::handle_task_region_exceptions(exs);
|
Chris@102
|
139 }
|
Chris@102
|
140 }
|
Chris@102
|
141 }
|
Chris@102
|
142 if (exs.size() != 0)
|
Chris@102
|
143 {
|
Chris@102
|
144 boost::throw_exception(exs);
|
Chris@102
|
145 }
|
Chris@102
|
146 }
|
Chris@102
|
147 protected:
|
Chris@102
|
148 #if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@102
|
149 task_region_handle_gen()
|
Chris@102
|
150 {}
|
Chris@102
|
151 #endif
|
Chris@102
|
152
|
Chris@102
|
153 #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@102
|
154 task_region_handle_gen()
|
Chris@102
|
155 : canceled(false)
|
Chris@102
|
156 , ex(0)
|
Chris@102
|
157 {}
|
Chris@102
|
158 task_region_handle_gen(Executor& ex)
|
Chris@102
|
159 : canceled(false)
|
Chris@102
|
160 , ex(&ex)
|
Chris@102
|
161 {}
|
Chris@102
|
162
|
Chris@102
|
163 #endif
|
Chris@102
|
164
|
Chris@102
|
165 #if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@102
|
166 task_region_handle_gen()
|
Chris@102
|
167 : ex(0)
|
Chris@102
|
168 {}
|
Chris@102
|
169 task_region_handle_gen(Executor& ex)
|
Chris@102
|
170 : ex(&ex)
|
Chris@102
|
171 {}
|
Chris@102
|
172 #endif
|
Chris@102
|
173
|
Chris@102
|
174 #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@102
|
175 task_region_handle_gen()
|
Chris@102
|
176 : canceled(false)
|
Chris@102
|
177 {
|
Chris@102
|
178 }
|
Chris@102
|
179 #endif
|
Chris@102
|
180
|
Chris@102
|
181 ~task_region_handle_gen()
|
Chris@102
|
182 {
|
Chris@102
|
183 //wait_all();
|
Chris@102
|
184 }
|
Chris@102
|
185
|
Chris@102
|
186 #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
Chris@102
|
187 mutable mutex mtx;
|
Chris@102
|
188 bool canceled;
|
Chris@102
|
189 #endif
|
Chris@102
|
190 #if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@102
|
191 Executor* ex;
|
Chris@102
|
192 #endif
|
Chris@102
|
193 exception_list exs;
|
Chris@102
|
194 typedef csbl::vector<future<void> > group_type;
|
Chris@102
|
195 group_type group;
|
Chris@102
|
196
|
Chris@102
|
197 public:
|
Chris@102
|
198 BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&))
|
Chris@102
|
199 BOOST_DELETED_FUNCTION(task_region_handle_gen& operator=(const task_region_handle_gen&))
|
Chris@102
|
200 BOOST_DELETED_FUNCTION(task_region_handle_gen* operator&() const)
|
Chris@102
|
201
|
Chris@102
|
202 public:
|
Chris@102
|
203 template<typename F>
|
Chris@102
|
204 void run(BOOST_THREAD_FWD_REF(F) f)
|
Chris@102
|
205 {
|
Chris@102
|
206 #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
Chris@102
|
207 {
|
Chris@102
|
208 lock_guard<mutex> lk(mtx);
|
Chris@102
|
209 if (canceled) {
|
Chris@102
|
210 boost::throw_exception(task_canceled_exception());
|
Chris@102
|
211 }
|
Chris@102
|
212 }
|
Chris@102
|
213 #if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@102
|
214 group.push_back(async(*ex, detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f))));
|
Chris@102
|
215 #else
|
Chris@102
|
216 group.push_back(async(detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f))));
|
Chris@102
|
217 #endif
|
Chris@102
|
218 #else
|
Chris@102
|
219 #if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@102
|
220 group.push_back(async(*ex, forward<F>(f)));
|
Chris@102
|
221 #else
|
Chris@102
|
222 group.push_back(async(forward<F>(f)));
|
Chris@102
|
223 #endif
|
Chris@102
|
224 #endif
|
Chris@102
|
225 }
|
Chris@102
|
226
|
Chris@102
|
227 void wait()
|
Chris@102
|
228 {
|
Chris@102
|
229 #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
Chris@102
|
230 {
|
Chris@102
|
231 lock_guard<mutex> lk(mtx);
|
Chris@102
|
232 if (canceled) {
|
Chris@102
|
233 boost::throw_exception(task_canceled_exception());
|
Chris@102
|
234 }
|
Chris@102
|
235 }
|
Chris@102
|
236 #endif
|
Chris@102
|
237 wait_all();
|
Chris@102
|
238 }
|
Chris@102
|
239 };
|
Chris@102
|
240 #if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@102
|
241 typedef basic_thread_pool default_executor;
|
Chris@102
|
242 #else
|
Chris@102
|
243 typedef int default_executor;
|
Chris@102
|
244 #endif
|
Chris@102
|
245 class task_region_handle :
|
Chris@102
|
246 public task_region_handle_gen<default_executor>
|
Chris@102
|
247 {
|
Chris@102
|
248 default_executor tp;
|
Chris@102
|
249 template <typename F>
|
Chris@102
|
250 friend void task_region(BOOST_THREAD_FWD_REF(F) f);
|
Chris@102
|
251 template<typename F>
|
Chris@102
|
252 friend void task_region_final(BOOST_THREAD_FWD_REF(F) f);
|
Chris@102
|
253
|
Chris@102
|
254 protected:
|
Chris@102
|
255 task_region_handle() : task_region_handle_gen<default_executor>()
|
Chris@102
|
256 {
|
Chris@102
|
257 #if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@102
|
258 ex = &tp;
|
Chris@102
|
259 #endif
|
Chris@102
|
260 }
|
Chris@102
|
261 BOOST_DELETED_FUNCTION(task_region_handle(const task_region_handle&))
|
Chris@102
|
262 BOOST_DELETED_FUNCTION(task_region_handle& operator=(const task_region_handle&))
|
Chris@102
|
263 BOOST_DELETED_FUNCTION(task_region_handle* operator&() const)
|
Chris@102
|
264
|
Chris@102
|
265 };
|
Chris@102
|
266
|
Chris@102
|
267 template <typename Executor, typename F>
|
Chris@102
|
268 void task_region_final(Executor& ex, BOOST_THREAD_FWD_REF(F) f)
|
Chris@102
|
269 {
|
Chris@102
|
270 task_region_handle_gen<Executor> tr(ex);
|
Chris@102
|
271 try
|
Chris@102
|
272 {
|
Chris@102
|
273 f(tr);
|
Chris@102
|
274 }
|
Chris@102
|
275 catch (...)
|
Chris@102
|
276 {
|
Chris@102
|
277 detail::handle_task_region_exceptions(tr.exs);
|
Chris@102
|
278 }
|
Chris@102
|
279 tr.wait_all();
|
Chris@102
|
280 }
|
Chris@102
|
281
|
Chris@102
|
282 template <typename Executor, typename F>
|
Chris@102
|
283 void task_region(Executor& ex, BOOST_THREAD_FWD_REF(F) f)
|
Chris@102
|
284 {
|
Chris@102
|
285 task_region_final(ex, forward<F>(f));
|
Chris@102
|
286 }
|
Chris@102
|
287
|
Chris@102
|
288 template <typename F>
|
Chris@102
|
289 void task_region_final(BOOST_THREAD_FWD_REF(F) f)
|
Chris@102
|
290 {
|
Chris@102
|
291 task_region_handle tr;
|
Chris@102
|
292 try
|
Chris@102
|
293 {
|
Chris@102
|
294 f(tr);
|
Chris@102
|
295 }
|
Chris@102
|
296 catch (...)
|
Chris@102
|
297 {
|
Chris@102
|
298 detail::handle_task_region_exceptions(tr.exs);
|
Chris@102
|
299 }
|
Chris@102
|
300 tr.wait_all();
|
Chris@102
|
301 }
|
Chris@102
|
302
|
Chris@102
|
303 template <typename F>
|
Chris@102
|
304 void task_region(BOOST_THREAD_FWD_REF(F) f)
|
Chris@102
|
305 {
|
Chris@102
|
306 task_region_final(forward<F>(f));
|
Chris@102
|
307 }
|
Chris@102
|
308
|
Chris@102
|
309 } // v2
|
Chris@102
|
310 } // parallel
|
Chris@102
|
311 } // experimental
|
Chris@102
|
312 } // boost
|
Chris@102
|
313
|
Chris@102
|
314 #include <boost/config/abi_suffix.hpp>
|
Chris@102
|
315
|
Chris@102
|
316 #endif // header
|