task_region.hpp 7.9 KB

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