passenger 4.0.20 → 4.0.21

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (496) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.gitignore +1 -0
  5. data/.travis.yml +1 -1
  6. data/NEWS +15 -0
  7. data/README.md +5 -3
  8. data/Rakefile +1 -0
  9. data/bin/passenger-config +1 -5
  10. data/bin/passenger-install-apache2-module +53 -5
  11. data/bin/passenger-install-nginx-module +19 -6
  12. data/bin/passenger-memory-stats +3 -3
  13. data/build/agents.rb +11 -8
  14. data/build/apache2.rb +9 -5
  15. data/build/basics.rb +15 -21
  16. data/build/common_library.rb +16 -6
  17. data/build/cplusplus_support.rb +5 -5
  18. data/build/cxx_tests.rb +3 -3
  19. data/build/documentation.rb +1 -1
  20. data/build/misc.rb +4 -37
  21. data/build/node_tests.rb +29 -0
  22. data/build/oxt_tests.rb +1 -1
  23. data/build/packaging.rb +29 -10
  24. data/build/preprocessor.rb +2 -1
  25. data/build/test_basics.rb +15 -6
  26. data/debian.template/locations.ini.template +1 -0
  27. data/debian.template/passenger.install.template +1 -0
  28. data/dev/copy_boost_headers.rb +7 -3
  29. data/dev/run_travis.sh +32 -16
  30. data/doc/Users guide Apache.idmap.txt +22 -34
  31. data/doc/Users guide Apache.txt +20 -234
  32. data/doc/Users guide Nginx.idmap.txt +84 -66
  33. data/doc/Users guide Nginx.txt +50 -1
  34. data/doc/Users guide Standalone.idmap.txt +74 -0
  35. data/doc/Users guide Standalone.txt +22 -9
  36. data/doc/Users guide.txt +51 -0
  37. data/doc/users_guide_snippets/environment_variables.txt +0 -3
  38. data/doc/users_guide_snippets/installation.txt +337 -380
  39. data/doc/users_guide_snippets/installation/run_installer.txt +58 -0
  40. data/doc/users_guide_snippets/installation/verify_running_epilogue.txt +6 -0
  41. data/doc/users_guide_snippets/support_information.txt +2 -9
  42. data/doc/users_guide_snippets/troubleshooting/default.txt +112 -0
  43. data/doc/users_guide_snippets/troubleshooting/rails.txt +56 -0
  44. data/doc/users_guide_snippets/where_to_get_support.txt +9 -0
  45. data/ext/apache2/Bucket.h +1 -1
  46. data/ext/apache2/Configuration.hpp +0 -44
  47. data/ext/apache2/CreateDirConfig.cpp +1 -1
  48. data/ext/apache2/CreateDirConfig.cpp.erb +1 -1
  49. data/ext/apache2/Hooks.cpp +28 -21
  50. data/ext/apache2/MergeDirConfig.cpp +1 -0
  51. data/ext/apache2/MergeDirConfig.cpp.erb +1 -1
  52. data/ext/apache2/SetHeaders.cpp +73 -0
  53. data/ext/apache2/SetHeaders.cpp.erb +88 -0
  54. data/ext/boost/algorithm/string/detail/find_format.hpp +5 -5
  55. data/ext/boost/algorithm/string/detail/find_format_all.hpp +5 -5
  56. data/ext/boost/algorithm/string/detail/finder.hpp +1 -1
  57. data/ext/boost/algorithm/string/formatter.hpp +2 -2
  58. data/ext/boost/assert.hpp +6 -1
  59. data/ext/boost/atomic.hpp +18 -0
  60. data/ext/boost/atomic/atomic.hpp +241 -0
  61. data/ext/boost/atomic/detail/base.hpp +585 -0
  62. data/ext/boost/atomic/detail/cas32strong.hpp +885 -0
  63. data/ext/boost/atomic/detail/cas32weak.hpp +947 -0
  64. data/ext/boost/atomic/detail/cas64strong.hpp +443 -0
  65. data/ext/boost/atomic/detail/config.hpp +54 -0
  66. data/ext/boost/atomic/detail/gcc-alpha.hpp +368 -0
  67. data/ext/boost/atomic/detail/gcc-armv6plus.hpp +252 -0
  68. data/ext/boost/atomic/detail/gcc-cas.hpp +157 -0
  69. data/ext/boost/atomic/detail/gcc-ppc.hpp +2850 -0
  70. data/ext/boost/atomic/detail/gcc-sparcv9.hpp +1259 -0
  71. data/ext/boost/atomic/detail/gcc-x86.hpp +1766 -0
  72. data/ext/boost/atomic/detail/generic-cas.hpp +206 -0
  73. data/ext/boost/atomic/detail/interlocked.hpp +200 -0
  74. data/ext/boost/atomic/detail/linux-arm.hpp +189 -0
  75. data/ext/boost/atomic/detail/lockpool.hpp +97 -0
  76. data/ext/boost/atomic/detail/platform.hpp +62 -0
  77. data/ext/boost/atomic/detail/type-classification.hpp +45 -0
  78. data/ext/boost/chrono/config.hpp +8 -3
  79. data/ext/boost/chrono/duration.hpp +9 -10
  80. data/ext/boost/chrono/system_clocks.hpp +1 -1
  81. data/ext/boost/chrono/time_point.hpp +4 -3
  82. data/ext/boost/config/auto_link.hpp +53 -52
  83. data/ext/boost/config/compiler/borland.hpp +1 -0
  84. data/ext/boost/config/compiler/clang.hpp +24 -1
  85. data/ext/boost/config/compiler/codegear.hpp +1 -0
  86. data/ext/boost/config/compiler/common_edg.hpp +1 -0
  87. data/ext/boost/config/compiler/cray.hpp +1 -0
  88. data/ext/boost/config/compiler/digitalmars.hpp +1 -0
  89. data/ext/boost/config/compiler/gcc.hpp +29 -3
  90. data/ext/boost/config/compiler/gcc_xml.hpp +2 -1
  91. data/ext/boost/config/compiler/hp_acc.hpp +1 -0
  92. data/ext/boost/config/compiler/intel.hpp +1 -1
  93. data/ext/boost/config/compiler/metrowerks.hpp +1 -0
  94. data/ext/boost/config/compiler/mpw.hpp +1 -0
  95. data/ext/boost/config/compiler/pathscale.hpp +1 -0
  96. data/ext/boost/config/compiler/pgi.hpp +1 -0
  97. data/ext/boost/config/compiler/sunpro_cc.hpp +1 -0
  98. data/ext/boost/config/compiler/vacpp.hpp +3 -2
  99. data/ext/boost/config/compiler/visualc.hpp +25 -11
  100. data/ext/boost/config/platform/vxworks.hpp +353 -15
  101. data/ext/boost/config/select_compiler_config.hpp +4 -4
  102. data/ext/boost/config/stdlib/dinkumware.hpp +10 -3
  103. data/ext/boost/config/stdlib/libstdcpp3.hpp +2 -1
  104. data/ext/boost/config/suffix.hpp +45 -19
  105. data/ext/boost/date_time/format_date_parser.hpp +1 -11
  106. data/ext/boost/date_time/strings_from_facet.hpp +5 -3
  107. data/ext/boost/detail/atomic_redef_macros.hpp +19 -0
  108. data/ext/boost/detail/atomic_undef_macros.hpp +39 -0
  109. data/ext/boost/detail/endian.hpp +52 -4
  110. data/ext/boost/detail/scoped_enum_emulation.hpp +10 -10
  111. data/ext/boost/detail/select_type.hpp +36 -0
  112. data/ext/boost/exception/current_exception_cast.hpp +1 -1
  113. data/ext/boost/exception/detail/error_info_impl.hpp +3 -5
  114. data/ext/boost/exception/detail/exception_ptr.hpp +3 -3
  115. data/ext/boost/exception/detail/is_output_streamable.hpp +1 -1
  116. data/ext/boost/exception/detail/object_hex_dump.hpp +1 -1
  117. data/ext/boost/exception/detail/type_info.hpp +1 -1
  118. data/ext/boost/exception/diagnostic_information.hpp +15 -14
  119. data/ext/boost/exception/exception.hpp +1 -1
  120. data/ext/boost/exception/get_error_info.hpp +1 -1
  121. data/ext/boost/exception/info.hpp +12 -13
  122. data/ext/boost/exception/to_string.hpp +6 -1
  123. data/ext/boost/exception/to_string_stub.hpp +9 -1
  124. data/ext/boost/foreach.hpp +5 -5
  125. data/ext/boost/function/function_template.hpp +6 -6
  126. data/ext/boost/functional/hash/detail/float_functions.hpp +90 -0
  127. data/ext/boost/functional/hash/detail/hash_float.hpp +11 -2
  128. data/ext/boost/functional/hash/extensions.hpp +14 -2
  129. data/ext/boost/functional/hash/hash.hpp +26 -5
  130. data/ext/boost/get_pointer.hpp +17 -2
  131. data/ext/boost/integer_traits.hpp +1 -1
  132. data/ext/boost/lexical_cast.hpp +615 -395
  133. data/ext/boost/libs/atomic/lockpool.cpp +24 -0
  134. data/ext/boost/libs/system/src/error_code.cpp +25 -18
  135. data/ext/boost/libs/thread/src/future.cpp +7 -5
  136. data/ext/boost/libs/thread/src/pthread/once.cpp +9 -3
  137. data/ext/boost/libs/thread/src/pthread/once_atomic.cpp +90 -0
  138. data/ext/boost/libs/thread/src/pthread/thread.cpp +129 -95
  139. data/ext/boost/libs/thread/src/pthread/timeconv.inl +20 -1
  140. data/ext/boost/limits.hpp +1 -1
  141. data/ext/boost/math/policies/policy.hpp +10 -0
  142. data/ext/boost/math/special_functions/detail/round_fwd.hpp +17 -4
  143. data/ext/boost/math/special_functions/fpclassify.hpp +114 -45
  144. data/ext/boost/math/special_functions/math_fwd.hpp +195 -83
  145. data/ext/boost/math/special_functions/sign.hpp +13 -8
  146. data/ext/boost/math/tools/config.hpp +38 -16
  147. data/ext/boost/move/algorithm.hpp +275 -0
  148. data/ext/boost/move/core.hpp +332 -0
  149. data/ext/boost/move/detail/config_begin.hpp +23 -0
  150. data/ext/boost/move/detail/config_end.hpp +20 -0
  151. data/ext/boost/move/detail/meta_utils.hpp +158 -0
  152. data/ext/boost/move/iterator.hpp +298 -0
  153. data/ext/boost/move/move.hpp +10 -1256
  154. data/ext/boost/move/traits.hpp +142 -0
  155. data/ext/boost/move/utility.hpp +194 -0
  156. data/ext/boost/mpl/assert.hpp +72 -4
  157. data/ext/boost/noncopyable.hpp +15 -3
  158. data/ext/boost/pointer_to_other.hpp +55 -0
  159. data/ext/boost/range/concepts.hpp +4 -4
  160. data/ext/boost/range/detail/extract_optional_type.hpp +1 -1
  161. data/ext/boost/range/empty.hpp +1 -1
  162. data/ext/boost/range/iterator_range_core.hpp +4 -1
  163. data/ext/boost/range/iterator_range_io.hpp +2 -2
  164. data/ext/boost/ratio/config.hpp +6 -0
  165. data/ext/boost/ratio/detail/overflow_helpers.hpp +2 -2
  166. data/ext/boost/smart_ptr/allocate_shared_array.hpp +250 -0
  167. data/ext/boost/smart_ptr/detail/allocate_array_helper.hpp +169 -0
  168. data/ext/boost/smart_ptr/detail/array_deleter.hpp +124 -0
  169. data/ext/boost/smart_ptr/detail/array_traits.hpp +53 -0
  170. data/ext/boost/smart_ptr/detail/array_utility.hpp +178 -0
  171. data/ext/boost/smart_ptr/detail/make_array_helper.hpp +157 -0
  172. data/ext/boost/smart_ptr/detail/operator_bool.hpp +16 -9
  173. data/ext/boost/smart_ptr/detail/shared_count.hpp +78 -7
  174. data/ext/boost/smart_ptr/detail/sp_convertible.hpp +15 -0
  175. data/ext/boost/smart_ptr/detail/sp_counted_base.hpp +12 -6
  176. data/ext/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp +1 -0
  177. data/ext/boost/smart_ptr/detail/sp_counted_base_aix.hpp +1 -0
  178. data/ext/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp +1 -0
  179. data/ext/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp +1 -0
  180. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp +1 -0
  181. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +1 -0
  182. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp +1 -0
  183. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp +1 -0
  184. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp +1 -0
  185. data/ext/boost/smart_ptr/detail/sp_counted_base_nt.hpp +1 -0
  186. data/ext/boost/smart_ptr/detail/sp_counted_base_pt.hpp +1 -0
  187. data/ext/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp +162 -0
  188. data/ext/boost/smart_ptr/detail/sp_counted_base_solaris.hpp +1 -0
  189. data/ext/boost/smart_ptr/detail/sp_counted_base_spin.hpp +1 -0
  190. data/ext/boost/smart_ptr/detail/sp_counted_base_sync.hpp +1 -0
  191. data/ext/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp +1 -0
  192. data/ext/boost/smart_ptr/detail/sp_counted_impl.hpp +15 -0
  193. data/ext/boost/smart_ptr/detail/sp_forward.hpp +39 -0
  194. data/ext/boost/smart_ptr/detail/sp_has_sync.hpp +19 -3
  195. data/ext/boost/smart_ptr/detail/sp_if_array.hpp +31 -0
  196. data/ext/boost/smart_ptr/detail/sp_nullptr_t.hpp +45 -0
  197. data/ext/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +5 -12
  198. data/ext/boost/smart_ptr/enable_shared_from_this.hpp +4 -4
  199. data/ext/boost/smart_ptr/make_shared.hpp +5 -1060
  200. data/ext/boost/smart_ptr/make_shared_array.hpp +247 -0
  201. data/ext/boost/smart_ptr/make_shared_object.hpp +1128 -0
  202. data/ext/boost/smart_ptr/scoped_array.hpp +32 -7
  203. data/ext/boost/smart_ptr/scoped_ptr.hpp +31 -5
  204. data/ext/boost/smart_ptr/shared_array.hpp +135 -20
  205. data/ext/boost/smart_ptr/shared_ptr.hpp +444 -126
  206. data/ext/boost/smart_ptr/weak_ptr.hpp +39 -28
  207. data/ext/boost/static_assert.hpp +74 -17
  208. data/ext/boost/system/error_code.hpp +76 -68
  209. data/ext/boost/system/system_error.hpp +5 -1
  210. data/ext/boost/thread/barrier.hpp +6 -2
  211. data/ext/boost/thread/completion_latch.hpp +233 -0
  212. data/ext/boost/thread/condition.hpp +6 -1
  213. data/ext/boost/thread/detail/async_func.hpp +571 -0
  214. data/ext/boost/thread/detail/config.hpp +248 -40
  215. data/ext/boost/thread/detail/counter.hpp +93 -0
  216. data/ext/boost/thread/detail/delete.hpp +12 -0
  217. data/ext/boost/thread/detail/invoke.hpp +1351 -0
  218. data/ext/boost/thread/detail/is_convertible.hpp +48 -0
  219. data/ext/boost/thread/detail/lockable_wrapper.hpp +45 -0
  220. data/ext/boost/thread/detail/log.hpp +83 -0
  221. data/ext/boost/thread/detail/make_tuple_indices.hpp +224 -0
  222. data/ext/boost/thread/detail/move.hpp +32 -16
  223. data/ext/boost/thread/detail/thread.hpp +236 -41
  224. data/ext/boost/thread/detail/thread_group.hpp +55 -9
  225. data/ext/boost/thread/detail/thread_interruption.hpp +4 -1
  226. data/ext/boost/thread/exceptions.hpp +2 -0
  227. data/ext/boost/thread/externally_locked.hpp +351 -0
  228. data/ext/boost/thread/externally_locked_stream.hpp +170 -0
  229. data/ext/boost/thread/future.hpp +2517 -455
  230. data/ext/boost/thread/future_error_code.hpp +61 -0
  231. data/ext/boost/thread/is_locked_by_this_thread.hpp +39 -0
  232. data/ext/boost/thread/latch.hpp +142 -0
  233. data/ext/boost/thread/lock_algorithms.hpp +468 -0
  234. data/ext/boost/thread/lock_concepts.hpp +197 -0
  235. data/ext/boost/thread/lock_factories.hpp +78 -0
  236. data/ext/boost/thread/lock_guard.hpp +88 -0
  237. data/ext/boost/thread/lock_options.hpp +31 -0
  238. data/ext/boost/thread/lock_traits.hpp +45 -0
  239. data/ext/boost/thread/lock_types.hpp +1226 -0
  240. data/ext/boost/thread/lockable_adapter.hpp +226 -0
  241. data/ext/boost/thread/lockable_concepts.hpp +157 -0
  242. data/ext/boost/thread/lockable_traits.hpp +207 -0
  243. data/ext/boost/thread/locks.hpp +5 -1816
  244. data/ext/boost/thread/mutex.hpp +33 -1
  245. data/ext/boost/thread/null_mutex.hpp +243 -0
  246. data/ext/boost/thread/once.hpp +10 -1
  247. data/ext/boost/thread/poly_lockable.hpp +68 -0
  248. data/ext/boost/thread/poly_lockable_adapter.hpp +89 -0
  249. data/ext/boost/thread/poly_shared_lockable.hpp +135 -0
  250. data/ext/boost/thread/poly_shared_lockable_adapter.hpp +170 -0
  251. data/ext/boost/thread/pthread/condition_variable.hpp +74 -26
  252. data/ext/boost/thread/pthread/condition_variable_fwd.hpp +54 -27
  253. data/ext/boost/thread/pthread/mutex.hpp +101 -38
  254. data/ext/boost/thread/pthread/once.hpp +459 -44
  255. data/ext/boost/thread/pthread/once_atomic.hpp +313 -0
  256. data/ext/boost/thread/pthread/recursive_mutex.hpp +19 -10
  257. data/ext/boost/thread/pthread/shared_mutex.hpp +226 -61
  258. data/ext/boost/thread/pthread/shared_mutex_assert.hpp +724 -0
  259. data/ext/boost/thread/pthread/thread_data.hpp +53 -50
  260. data/ext/boost/thread/pthread/timespec.hpp +96 -12
  261. data/ext/boost/thread/recursive_mutex.hpp +44 -1
  262. data/ext/boost/thread/reverse_lock.hpp +3 -2
  263. data/ext/boost/thread/scoped_thread.hpp +285 -0
  264. data/ext/boost/thread/shared_lock_guard.hpp +2 -1
  265. data/ext/boost/thread/shared_mutex.hpp +23 -0
  266. data/ext/boost/thread/strict_lock.hpp +235 -0
  267. data/ext/boost/thread/sync_bounded_queue.hpp +594 -0
  268. data/ext/boost/thread/sync_queue.hpp +516 -0
  269. data/ext/boost/thread/synchronized_value.hpp +1001 -0
  270. data/ext/boost/thread/testable_mutex.hpp +148 -0
  271. data/ext/boost/thread/thread.hpp +1 -13
  272. data/ext/boost/thread/thread_functors.hpp +57 -0
  273. data/ext/boost/thread/thread_guard.hpp +46 -0
  274. data/ext/boost/thread/thread_only.hpp +29 -0
  275. data/ext/boost/thread/v2/shared_mutex.hpp +1062 -0
  276. data/ext/boost/thread/v2/thread.hpp +37 -10
  277. data/ext/boost/thread/xtime.hpp +2 -1
  278. data/ext/boost/token_functions.hpp +16 -16
  279. data/ext/boost/type_traits/add_lvalue_reference.hpp +26 -0
  280. data/ext/boost/type_traits/add_reference.hpp +1 -1
  281. data/ext/boost/type_traits/add_rvalue_reference.hpp +4 -4
  282. data/ext/boost/type_traits/aligned_storage.hpp +13 -0
  283. data/ext/boost/type_traits/common_type.hpp +11 -12
  284. data/ext/boost/type_traits/config.hpp +1 -1
  285. data/ext/boost/type_traits/detail/common_type_imp.hpp +1 -1
  286. data/ext/boost/type_traits/detail/has_binary_operator.hpp +1 -1
  287. data/ext/boost/type_traits/detail/is_function_ptr_tester.hpp +1 -1
  288. data/ext/boost/type_traits/has_left_shift.hpp +49 -0
  289. data/ext/boost/type_traits/has_right_shift.hpp +49 -0
  290. data/ext/boost/type_traits/has_trivial_move_assign.hpp +57 -0
  291. data/ext/boost/type_traits/has_trivial_move_constructor.hpp +57 -0
  292. data/ext/boost/type_traits/intrinsics.hpp +18 -2
  293. data/ext/boost/type_traits/is_abstract.hpp +1 -1
  294. data/ext/boost/type_traits/is_array.hpp +1 -1
  295. data/ext/boost/type_traits/is_const.hpp +1 -1
  296. data/ext/boost/type_traits/is_convertible.hpp +78 -17
  297. data/ext/boost/type_traits/is_function.hpp +6 -1
  298. data/ext/boost/type_traits/is_integral.hpp +6 -1
  299. data/ext/boost/type_traits/is_nothrow_move_assignable.hpp +84 -0
  300. data/ext/boost/type_traits/is_nothrow_move_constructible.hpp +84 -0
  301. data/ext/boost/type_traits/is_pod.hpp +3 -1
  302. data/ext/boost/type_traits/is_rvalue_reference.hpp +1 -1
  303. data/ext/boost/type_traits/is_volatile.hpp +1 -1
  304. data/ext/boost/type_traits/make_signed.hpp +153 -0
  305. data/ext/boost/type_traits/make_unsigned.hpp +16 -0
  306. data/ext/boost/type_traits/remove_const.hpp +1 -1
  307. data/ext/boost/type_traits/remove_cv.hpp +1 -1
  308. data/ext/boost/type_traits/remove_reference.hpp +1 -1
  309. data/ext/boost/type_traits/remove_volatile.hpp +1 -1
  310. data/ext/boost/unordered/detail/allocate.hpp +1120 -0
  311. data/ext/boost/unordered/detail/buckets.hpp +876 -0
  312. data/ext/boost/unordered/detail/equivalent.hpp +680 -0
  313. data/ext/boost/unordered/detail/extract_key.hpp +183 -0
  314. data/ext/boost/unordered/detail/fwd.hpp +23 -0
  315. data/ext/boost/unordered/detail/table.hpp +861 -0
  316. data/ext/boost/unordered/detail/unique.hpp +622 -0
  317. data/ext/boost/unordered/detail/util.hpp +260 -0
  318. data/ext/boost/unordered/unordered_map.hpp +1652 -0
  319. data/ext/boost/unordered/unordered_map_fwd.hpp +65 -0
  320. data/ext/boost/unordered/unordered_set.hpp +1549 -0
  321. data/ext/boost/unordered/unordered_set_fwd.hpp +63 -0
  322. data/ext/boost/unordered_map.hpp +18 -0
  323. data/ext/boost/unordered_set.hpp +18 -0
  324. data/ext/boost/utility/addressof.hpp +2 -2
  325. data/ext/boost/utility/result_of.hpp +8 -1
  326. data/ext/boost/version.hpp +2 -2
  327. data/ext/common/Account.h +1 -1
  328. data/ext/common/AccountsDatabase.h +1 -1
  329. data/ext/common/AgentsStarter.cpp +3 -1
  330. data/ext/common/AgentsStarter.h +2 -2
  331. data/ext/common/ApplicationPool2/AppTypes.cpp +24 -6
  332. data/ext/common/ApplicationPool2/AppTypes.h +17 -8
  333. data/ext/common/ApplicationPool2/Common.h +12 -12
  334. data/ext/common/ApplicationPool2/DirectSpawner.h +2 -2
  335. data/ext/common/ApplicationPool2/DummySpawner.h +3 -3
  336. data/ext/common/ApplicationPool2/Group.h +6 -6
  337. data/ext/common/ApplicationPool2/Implementation.cpp +19 -19
  338. data/ext/common/ApplicationPool2/PipeWatcher.h +5 -5
  339. data/ext/common/ApplicationPool2/Pool.h +21 -21
  340. data/ext/common/ApplicationPool2/Process.h +6 -6
  341. data/ext/common/ApplicationPool2/Session.h +1 -1
  342. data/ext/common/ApplicationPool2/SmartSpawner.h +24 -12
  343. data/ext/common/ApplicationPool2/Socket.h +2 -2
  344. data/ext/common/ApplicationPool2/Spawner.h +64 -14
  345. data/ext/common/ApplicationPool2/SpawnerFactory.h +7 -7
  346. data/ext/common/ApplicationPool2/SuperGroup.h +5 -5
  347. data/ext/common/BackgroundEventLoop.cpp +4 -4
  348. data/ext/common/BackgroundEventLoop.h +1 -1
  349. data/ext/common/Constants.h +13 -1
  350. data/ext/common/EventedBufferedInput.h +8 -8
  351. data/ext/common/Exceptions.cpp +71 -0
  352. data/ext/common/Exceptions.h +60 -7
  353. data/ext/common/FileDescriptor.h +4 -4
  354. data/ext/common/MessageClient.h +1 -1
  355. data/ext/common/MessageServer.h +5 -5
  356. data/ext/common/MultiLibeio.cpp +3 -3
  357. data/ext/common/MultiLibeio.h +2 -2
  358. data/ext/common/RandomGenerator.h +11 -11
  359. data/ext/common/ResourceLocator.h +8 -1
  360. data/ext/common/SafeLibev.h +12 -12
  361. data/ext/common/ServerInstanceDir.h +11 -3
  362. data/ext/common/UnionStation.h +10 -10
  363. data/ext/common/Utils.cpp +11 -13
  364. data/ext/common/Utils.h +9 -9
  365. data/ext/common/Utils/BlockingQueue.h +10 -10
  366. data/ext/common/Utils/BufferedIO.h +1 -1
  367. data/ext/common/Utils/CachedFileStat.hpp +2 -2
  368. data/ext/common/Utils/FileChangeChecker.h +1 -1
  369. data/ext/common/Utils/HashMap.h +13 -4
  370. data/ext/common/Utils/IOUtils.cpp +33 -10
  371. data/ext/common/Utils/IniFile.h +3 -3
  372. data/ext/common/Utils/Lock.h +2 -2
  373. data/ext/common/Utils/MessagePassing.h +10 -10
  374. data/ext/common/Utils/ProcessMetricsCollector.h +24 -6
  375. data/ext/common/Utils/ScopeGuard.h +5 -5
  376. data/ext/common/Utils/jsoncpp.cpp +2 -0
  377. data/ext/common/agents/HelperAgent/FileBackedPipe.h +26 -26
  378. data/ext/common/agents/HelperAgent/Main.cpp +18 -18
  379. data/ext/common/agents/HelperAgent/RequestHandler.cpp +4 -4
  380. data/ext/common/agents/HelperAgent/RequestHandler.h +30 -21
  381. data/ext/common/agents/LoggingAgent/AdminController.h +1 -1
  382. data/ext/common/agents/LoggingAgent/FilterSupport.h +13 -11
  383. data/ext/common/agents/LoggingAgent/LoggingServer.h +11 -11
  384. data/ext/common/agents/LoggingAgent/Main.cpp +9 -9
  385. data/ext/common/agents/LoggingAgent/RemoteSender.h +3 -3
  386. data/ext/common/agents/SpawnPreparer.cpp +1 -0
  387. data/ext/common/agents/Watchdog/AgentWatcher.cpp +8 -7
  388. data/ext/common/agents/Watchdog/Main.cpp +81 -73
  389. data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +1 -1
  390. data/ext/libev/Changes +57 -0
  391. data/ext/libev/LICENSE +2 -1
  392. data/ext/libev/Makefile.in +110 -50
  393. data/ext/libev/README +8 -8
  394. data/ext/libev/aclocal.m4 +1503 -861
  395. data/ext/libev/config.guess +290 -304
  396. data/ext/libev/config.sub +77 -198
  397. data/ext/libev/configure +1735 -890
  398. data/ext/libev/configure.ac +3 -2
  399. data/ext/libev/ev++.h +6 -6
  400. data/ext/libev/ev.c +541 -214
  401. data/ext/libev/ev.h +106 -100
  402. data/ext/libev/ev_epoll.c +1 -1
  403. data/ext/libev/ev_kqueue.c +20 -4
  404. data/ext/libev/ev_vars.h +15 -16
  405. data/ext/libev/ev_win32.c +12 -2
  406. data/ext/libev/ev_wrap.h +162 -160
  407. data/ext/libev/event.c +29 -6
  408. data/ext/libev/event.h +9 -2
  409. data/ext/libev/ltmain.sh +2632 -1384
  410. data/ext/nginx/ConfigurationCommands.c +1 -1
  411. data/ext/nginx/ConfigurationCommands.c.erb +3 -1
  412. data/ext/nginx/ContentHandler.c +25 -2
  413. data/ext/nginx/CreateLocationConfig.c +1 -0
  414. data/ext/nginx/CreateLocationConfig.c.erb +1 -1
  415. data/ext/nginx/MergeLocationConfig.c +1 -0
  416. data/ext/nginx/MergeLocationConfig.c.erb +1 -1
  417. data/ext/nginx/config +12 -0
  418. data/ext/oxt/dynamic_thread_group.hpp +7 -4
  419. data/ext/oxt/system_calls.cpp +5 -1
  420. data/ext/oxt/system_calls.hpp +3 -0
  421. data/helper-scripts/node-loader.js +117 -249
  422. data/lib/phusion_passenger.rb +27 -5
  423. data/lib/phusion_passenger/abstract_installer.rb +104 -9
  424. data/lib/phusion_passenger/admin_tools/memory_stats.rb +10 -9
  425. data/lib/phusion_passenger/apache2/config_options.rb +6 -3
  426. data/lib/phusion_passenger/common_library.rb +7 -1
  427. data/lib/phusion_passenger/constants.rb +6 -0
  428. data/lib/phusion_passenger/loader_shared_helpers.rb +7 -4
  429. data/lib/phusion_passenger/nginx/config_options.rb +2 -1
  430. data/lib/phusion_passenger/packaging.rb +3 -0
  431. data/lib/phusion_passenger/platform_info/apache.rb +43 -6
  432. data/lib/phusion_passenger/platform_info/apache_detector.rb +15 -5
  433. data/lib/phusion_passenger/platform_info/compiler.rb +167 -32
  434. data/lib/phusion_passenger/platform_info/cxx_portability.rb +133 -77
  435. data/lib/phusion_passenger/platform_info/depcheck.rb +17 -7
  436. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +3 -3
  437. data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
  438. data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +5 -6
  439. data/lib/phusion_passenger/platform_info/linux.rb +2 -1
  440. data/lib/phusion_passenger/platform_info/operating_system.rb +1 -1
  441. data/lib/phusion_passenger/platform_info/ruby.rb +18 -3
  442. data/lib/phusion_passenger/standalone/runtime_installer.rb +6 -2
  443. data/lib/phusion_passenger/standalone/start_command.rb +8 -2
  444. data/lib/phusion_passenger/utils/ansi_colors.rb +9 -0
  445. data/lib/phusion_passenger/utils/hosts_file_parser.rb +4 -2
  446. data/node_lib/phusion_passenger/httplib_emulation.js +141 -0
  447. data/node_lib/phusion_passenger/line_reader.js +154 -0
  448. data/node_lib/phusion_passenger/request_handler.js +65 -0
  449. data/node_lib/phusion_passenger/session_protocol_parser.js +113 -0
  450. data/resources/templates/apache2/deployment_example.txt.erb +2 -1
  451. data/resources/templates/apache2/installing_against_a_different_apache.txt.erb +14 -0
  452. data/resources/templates/apache2/multiple_apache_installations_detected.txt.erb +15 -0
  453. data/resources/templates/apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb +4 -5
  454. data/resources/templates/general_error_with_html.html.template +1 -1
  455. data/resources/templates/installer_common/gem_install_permission_problems.txt.erb +17 -0
  456. data/resources/templates/installer_common/low_amount_of_memory_warning.txt.erb +6 -4
  457. data/resources/templates/installer_common/world_inaccessible_directories.txt.erb +16 -0
  458. data/resources/templates/nginx/deployment_example.txt.erb +2 -1
  459. data/resources/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +4 -5
  460. data/resources/templates/standalone/config.erb +1 -0
  461. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +3 -3
  462. data/test/cxx/ApplicationPool2/PoolTest.cpp +4 -4
  463. data/test/cxx/ApplicationPool2/ProcessTest.cpp +5 -5
  464. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +5 -5
  465. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +1 -1
  466. data/test/cxx/EventedBufferedInputTest.cpp +6 -6
  467. data/test/cxx/FileBackedPipeTest.cpp +1 -1
  468. data/test/cxx/MessagePassingTest.cpp +1 -1
  469. data/test/cxx/MessageServerTest.cpp +4 -4
  470. data/test/cxx/RequestHandlerTest.cpp +7 -7
  471. data/test/cxx/UnionStationTest.cpp +2 -2
  472. data/test/node/line_reader_spec.js +338 -0
  473. data/test/node/spec_helper.js +27 -0
  474. data/test/ruby/standalone/runtime_installer_spec.rb +2 -1
  475. metadata +131 -22
  476. metadata.gz.asc +7 -7
  477. data/ext/boost/functional/hash/detail/container_fwd_0x.hpp +0 -29
  478. data/ext/boost/lambda/core.hpp +0 -79
  479. data/ext/boost/lambda/detail/actions.hpp +0 -174
  480. data/ext/boost/lambda/detail/arity_code.hpp +0 -110
  481. data/ext/boost/lambda/detail/function_adaptors.hpp +0 -789
  482. data/ext/boost/lambda/detail/is_instance_of.hpp +0 -104
  483. data/ext/boost/lambda/detail/lambda_config.hpp +0 -48
  484. data/ext/boost/lambda/detail/lambda_functor_base.hpp +0 -615
  485. data/ext/boost/lambda/detail/lambda_functors.hpp +0 -324
  486. data/ext/boost/lambda/detail/lambda_fwd.hpp +0 -74
  487. data/ext/boost/lambda/detail/lambda_traits.hpp +0 -578
  488. data/ext/boost/lambda/detail/member_ptr.hpp +0 -737
  489. data/ext/boost/lambda/detail/operator_actions.hpp +0 -139
  490. data/ext/boost/lambda/detail/operator_lambda_func_base.hpp +0 -271
  491. data/ext/boost/lambda/detail/operator_return_type_traits.hpp +0 -917
  492. data/ext/boost/lambda/detail/operators.hpp +0 -370
  493. data/ext/boost/lambda/detail/ret.hpp +0 -325
  494. data/ext/boost/lambda/detail/return_type_traits.hpp +0 -282
  495. data/ext/boost/lambda/detail/select_functions.hpp +0 -74
  496. data/ext/boost/lambda/lambda.hpp +0 -34
@@ -0,0 +1,170 @@
1
+ // (C) Copyright 2012 Vicente J. Botet Escriba
2
+ // Distributed under the Boost Software License, Version 1.0. (See
3
+ // accompanying file LICENSE_1_0.txt or copy at
4
+ // http://www.boost.org/LICENSE_1_0.txt)
5
+
6
+
7
+ #ifndef BOOST_THREAD_EXTERNALLY_LOCKED_STREAM_HPP
8
+ #define BOOST_THREAD_EXTERNALLY_LOCKED_STREAM_HPP
9
+
10
+ #include <boost/thread/detail/config.hpp>
11
+ #include <boost/thread/detail/move.hpp>
12
+ #include <boost/thread/detail/delete.hpp>
13
+
14
+ #include <boost/thread/externally_locked.hpp>
15
+ #include <boost/thread/lock_traits.hpp>
16
+ #include <boost/thread/recursive_mutex.hpp>
17
+ #include <boost/thread/strict_lock.hpp>
18
+
19
+ #include <boost/config/abi_prefix.hpp>
20
+
21
+ namespace boost
22
+ {
23
+
24
+ template <typename Stream, typename RecursiveMutex=recursive_mutex>
25
+ class externally_locked_stream;
26
+
27
+ template <class Stream, typename RecursiveMutex=recursive_mutex>
28
+ class stream_guard
29
+ {
30
+
31
+ friend class externally_locked_stream<Stream, RecursiveMutex> ;
32
+ public:
33
+ typedef typename externally_locked_stream<Stream, RecursiveMutex>::mutex_type mutex_type;
34
+
35
+ BOOST_THREAD_MOVABLE_ONLY( stream_guard)
36
+
37
+ stream_guard(externally_locked_stream<Stream, RecursiveMutex>& mtx) :
38
+ mtx_(&mtx)
39
+ {
40
+ mtx.lock();
41
+ }
42
+
43
+ stream_guard(externally_locked_stream<Stream, RecursiveMutex>& mtx, adopt_lock_t) :
44
+ mtx_(&mtx)
45
+ {
46
+ }
47
+
48
+ stream_guard(BOOST_THREAD_RV_REF(stream_guard) rhs) BOOST_NOEXCEPT
49
+ : mtx_(rhs.mtx_)
50
+ {
51
+ rhs.mtx_= 0;
52
+ }
53
+
54
+ ~stream_guard()
55
+ {
56
+ if (mtx_ != 0) mtx_->unlock();
57
+ }
58
+
59
+ bool owns_lock(const mutex_type * l) const BOOST_NOEXCEPT
60
+ {
61
+ return l == mtx_->mutex();
62
+ }
63
+
64
+ /**
65
+ * @Requires mtx_
66
+ */
67
+ Stream& get() const
68
+ {
69
+ BOOST_THREAD_ASSERT_PRECONDITION( mtx_, lock_error() );
70
+ return mtx_->get(*this);
71
+ }
72
+ Stream& bypass() const
73
+ {
74
+ return get();
75
+ }
76
+
77
+
78
+ private:
79
+ externally_locked_stream<Stream, RecursiveMutex>* mtx_;
80
+ };
81
+
82
+ template <typename Stream, typename RecursiveMutex>
83
+ struct is_strict_lock_sur_parole<stream_guard<Stream, RecursiveMutex> > : true_type
84
+ {
85
+ };
86
+
87
+ /**
88
+ * externally_locked_stream cloaks a reference to an stream of type Stream, and actually
89
+ * provides full access to that object through the get and set member functions, provided you
90
+ * pass a reference to a strict lock object.
91
+ */
92
+
93
+ //[externally_locked_stream
94
+ template <typename Stream, typename RecursiveMutex>
95
+ class externally_locked_stream: public externally_locked<Stream&, RecursiveMutex>
96
+ {
97
+ typedef externally_locked<Stream&, RecursiveMutex> base_type;
98
+ public:
99
+ BOOST_THREAD_NO_COPYABLE( externally_locked_stream)
100
+
101
+ /**
102
+ * Effects: Constructs an externally locked object storing the cloaked reference object.
103
+ */
104
+ externally_locked_stream(Stream& stream, RecursiveMutex& mtx) BOOST_NOEXCEPT :
105
+ base_type(stream, mtx)
106
+ {
107
+ }
108
+
109
+ stream_guard<Stream, RecursiveMutex> hold() BOOST_NOEXCEPT
110
+ {
111
+ return stream_guard<Stream, RecursiveMutex> (*this);
112
+ }
113
+ Stream& bypass() const
114
+ {
115
+ stream_guard<Stream, RecursiveMutex> lk(*this);
116
+ return get(lk);
117
+ }
118
+ };
119
+ //]
120
+
121
+ template <typename Stream, typename RecursiveMutex, typename T>
122
+ inline const stream_guard<Stream, RecursiveMutex>& operator<<(const stream_guard<Stream, RecursiveMutex>& lck, T arg)
123
+ {
124
+ lck.get() << arg;
125
+ return lck;
126
+ }
127
+
128
+ template <typename Stream, typename RecursiveMutex>
129
+ inline const stream_guard<Stream, RecursiveMutex>& operator<<(const stream_guard<Stream, RecursiveMutex>& lck, Stream& (*arg)(Stream&))
130
+ {
131
+ lck.get() << arg;
132
+ return lck;
133
+ }
134
+
135
+ template <typename Stream, typename RecursiveMutex, typename T>
136
+ inline const stream_guard<Stream, RecursiveMutex>& operator>>(const stream_guard<Stream, RecursiveMutex>& lck, T& arg)
137
+ {
138
+ lck.get() >> arg;
139
+ return lck;
140
+ }
141
+
142
+ template <typename Stream, typename RecursiveMutex, typename T>
143
+ inline stream_guard<Stream, RecursiveMutex> operator<<(externally_locked_stream<Stream, RecursiveMutex>& mtx, T arg)
144
+ {
145
+ stream_guard<Stream, RecursiveMutex> lk(mtx);
146
+ mtx.get(lk) << arg;
147
+ return boost::move(lk);
148
+ }
149
+
150
+ template <typename Stream, typename RecursiveMutex>
151
+ inline stream_guard<Stream, RecursiveMutex> operator<<(externally_locked_stream<Stream, RecursiveMutex>& mtx, Stream& (*arg)(Stream&))
152
+ {
153
+ stream_guard<Stream, RecursiveMutex> lk(mtx);
154
+ mtx.get(lk) << arg;
155
+ return boost::move(lk);
156
+ }
157
+
158
+ template <typename Stream, typename RecursiveMutex, typename T>
159
+ inline stream_guard<Stream, RecursiveMutex> operator>>(externally_locked_stream<Stream, RecursiveMutex>& mtx, T& arg)
160
+ {
161
+ stream_guard<Stream, RecursiveMutex> lk(mtx);
162
+ mtx.get(lk) >> arg;
163
+ return boost::move(lk);
164
+ }
165
+
166
+ }
167
+
168
+ #include <boost/config/abi_suffix.hpp>
169
+
170
+ #endif // header
@@ -1,5 +1,5 @@
1
1
  // (C) Copyright 2008-10 Anthony Williams
2
- // (C) Copyright 2011-2012 Vicente J. Botet Escriba
2
+ // (C) Copyright 2011-2013 Vicente J. Botet Escriba
3
3
  //
4
4
  // Distributed under the Boost Software License, Version 1.0. (See
5
5
  // accompanying file LICENSE_1_0.txt or copy at
@@ -15,17 +15,21 @@
15
15
 
16
16
  #ifndef BOOST_NO_EXCEPTIONS
17
17
 
18
+ //#include <boost/thread/detail/log.hpp>
18
19
  #include <boost/detail/scoped_enum_emulation.hpp>
19
20
  #include <stdexcept>
20
21
  #include <boost/thread/detail/move.hpp>
22
+ #include <boost/thread/detail/async_func.hpp>
21
23
  #include <boost/thread/thread_time.hpp>
22
24
  #include <boost/thread/mutex.hpp>
23
25
  #include <boost/thread/condition_variable.hpp>
26
+ #include <boost/thread/lock_algorithms.hpp>
27
+ #include <boost/thread/lock_types.hpp>
24
28
  #include <boost/exception_ptr.hpp>
25
29
  #include <boost/shared_ptr.hpp>
26
30
  #include <boost/scoped_ptr.hpp>
27
31
  #include <boost/type_traits/is_fundamental.hpp>
28
- #include <boost/type_traits/is_convertible.hpp>
32
+ #include <boost/thread/detail/is_convertible.hpp>
29
33
  #include <boost/type_traits/remove_reference.hpp>
30
34
  #include <boost/type_traits/remove_cv.hpp>
31
35
  #include <boost/mpl/if.hpp>
@@ -36,11 +40,13 @@
36
40
  #include <boost/bind.hpp>
37
41
  #include <boost/ref.hpp>
38
42
  #include <boost/scoped_array.hpp>
43
+ #include <boost/enable_shared_from_this.hpp>
39
44
  #include <boost/utility/enable_if.hpp>
40
45
  #include <list>
41
46
  #include <boost/next_prior.hpp>
42
47
  #include <vector>
43
- #include <boost/system/error_code.hpp>
48
+
49
+ #include <boost/thread/future_error_code.hpp>
44
50
  #ifdef BOOST_THREAD_USES_CHRONO
45
51
  #include <boost/chrono/system_clocks.hpp>
46
52
  #endif
@@ -50,7 +56,7 @@
50
56
  #endif
51
57
 
52
58
  #include <boost/utility/result_of.hpp>
53
- #include <boost/thread/thread.hpp>
59
+ #include <boost/thread/thread_only.hpp>
54
60
 
55
61
  #if defined BOOST_THREAD_PROVIDES_FUTURE
56
62
  #define BOOST_THREAD_FUTURE future
@@ -58,34 +64,13 @@
58
64
  #define BOOST_THREAD_FUTURE unique_future
59
65
  #endif
60
66
 
61
-
62
67
  namespace boost
63
68
  {
64
69
 
65
- //enum class future_errc
66
- BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc)
67
- {
68
- broken_promise,
69
- future_already_retrieved,
70
- promise_already_satisfied,
71
- no_state
72
- }
73
- BOOST_SCOPED_ENUM_DECLARE_END(future_errc)
74
-
75
- namespace system
76
- {
77
- template <>
78
- struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type {};
79
-
80
- #ifdef BOOST_NO_CXX11_SCOPED_ENUMS
81
- template <>
82
- struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { };
83
- #endif
84
- }
85
-
86
70
  //enum class launch
87
71
  BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch)
88
72
  {
73
+ none = 0,
89
74
  async = 1,
90
75
  deferred = 2,
91
76
  any = async | deferred
@@ -101,26 +86,6 @@ namespace boost
101
86
  }
102
87
  BOOST_SCOPED_ENUM_DECLARE_END(future_status)
103
88
 
104
- BOOST_THREAD_DECL
105
- const system::error_category& future_category() BOOST_NOEXCEPT;
106
-
107
- namespace system
108
- {
109
- inline
110
- error_code
111
- make_error_code(future_errc e) //BOOST_NOEXCEPT
112
- {
113
- return error_code(underlying_cast<int>(e), boost::future_category());
114
- }
115
-
116
- inline
117
- error_condition
118
- make_error_condition(future_errc e) //BOOST_NOEXCEPT
119
- {
120
- return error_condition(underlying_cast<int>(e), future_category());
121
- }
122
- }
123
-
124
89
  class BOOST_SYMBOL_VISIBLE future_error
125
90
  : public std::logic_error
126
91
  {
@@ -136,11 +101,6 @@ namespace boost
136
101
  {
137
102
  return ec_;
138
103
  }
139
- const char* what() const BOOST_THREAD_NOEXCEPT_OR_THROW
140
- {
141
- return code().message().c_str();
142
- }
143
-
144
104
  };
145
105
 
146
106
  class BOOST_SYMBOL_VISIBLE future_uninitialized:
@@ -205,29 +165,107 @@ namespace boost
205
165
 
206
166
  namespace future_state
207
167
  {
208
- enum state { uninitialized, waiting, ready, moved };
168
+ enum state { uninitialized, waiting, ready, moved, deferred };
209
169
  }
210
170
 
211
171
  namespace detail
212
172
  {
213
- struct future_object_base
173
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
174
+ template<typename F, typename Rp, typename Fp>
175
+ struct future_deferred_continuation;
176
+ template<typename F, typename Rp, typename Fp>
177
+ struct future_async_continuation;
178
+ #endif
179
+
180
+ struct relocker
181
+ {
182
+ boost::unique_lock<boost::mutex>& lock_;
183
+ bool unlocked_;
184
+
185
+ relocker(boost::unique_lock<boost::mutex>& lk):
186
+ lock_(lk)
187
+ {
188
+ lock_.unlock();
189
+ unlocked_=true;
190
+ }
191
+ ~relocker()
192
+ {
193
+ if (unlocked_) {
194
+ lock_.lock();
195
+ }
196
+ }
197
+ void lock() {
198
+ if (unlocked_) {
199
+ lock_.lock();
200
+ unlocked_=false;
201
+ }
202
+ }
203
+ private:
204
+ relocker& operator=(relocker const&);
205
+ };
206
+
207
+ struct future_object_base : enable_shared_from_this<future_object_base>
214
208
  {
209
+
215
210
  boost::exception_ptr exception;
216
211
  bool done;
217
- bool thread_was_interrupted;
212
+ bool is_deferred_;
213
+ launch policy_;
214
+ bool is_constructed;
218
215
  boost::mutex mutex;
219
216
  boost::condition_variable waiters;
220
217
  typedef std::list<boost::condition_variable_any*> waiter_list;
221
218
  waiter_list external_waiters;
222
219
  boost::function<void()> callback;
220
+ //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
221
+ bool thread_was_interrupted;
222
+ //#endif
223
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
224
+ typedef shared_ptr<future_object_base> continuation_ptr_type;
225
+ #else
226
+ typedef shared_ptr<void> continuation_ptr_type;
227
+ #endif
228
+ continuation_ptr_type continuation_ptr;
229
+
223
230
 
231
+ //#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
232
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>&)
233
+ {
234
+ }
235
+ //#endif
224
236
  future_object_base():
225
237
  done(false),
226
- thread_was_interrupted(false)
238
+ is_deferred_(false),
239
+ policy_(launch::none),
240
+ is_constructed(false)
241
+
242
+ // This declaration should be only included conditinally, but are included to maintain the same layout.
243
+ //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
244
+ , thread_was_interrupted(false)
245
+ //#endif
246
+ // This declaration should be only included conditinally, but are included to maintain the same layout.
247
+ //#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
248
+ , continuation_ptr()
249
+ //#endif
227
250
  {}
228
251
  virtual ~future_object_base()
229
252
  {}
230
253
 
254
+ void set_deferred()
255
+ {
256
+ is_deferred_ = true;
257
+ set_launch_policy(launch::deferred);
258
+ }
259
+ void set_async()
260
+ {
261
+ is_deferred_ = false;
262
+ set_launch_policy(launch::async);
263
+ }
264
+ void set_launch_policy(launch policy)
265
+ {
266
+ policy_ = policy;
267
+ }
268
+
231
269
  waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv)
232
270
  {
233
271
  boost::unique_lock<boost::mutex> lock(mutex);
@@ -241,7 +279,31 @@ namespace boost
241
279
  external_waiters.erase(it);
242
280
  }
243
281
 
244
- void mark_finished_internal()
282
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
283
+ void do_continuation(boost::unique_lock<boost::mutex>& lock)
284
+ {
285
+ if (continuation_ptr) {
286
+ continuation_ptr->launch_continuation(lock);
287
+ if (! lock.owns_lock())
288
+ lock.lock();
289
+ continuation_ptr.reset();
290
+ }
291
+ }
292
+ #else
293
+ void do_continuation(boost::unique_lock<boost::mutex>&)
294
+ {
295
+ }
296
+ #endif
297
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
298
+ void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
299
+ {
300
+ continuation_ptr= continuation;
301
+ if (done) {
302
+ do_continuation(lock);
303
+ }
304
+ }
305
+ #endif
306
+ void mark_finished_internal(boost::unique_lock<boost::mutex>& lock)
245
307
  {
246
308
  done=true;
247
309
  waiters.notify_all();
@@ -250,24 +312,13 @@ namespace boost
250
312
  {
251
313
  (*it)->notify_all();
252
314
  }
315
+ do_continuation(lock);
253
316
  }
254
-
255
- struct relocker
317
+ void make_ready()
256
318
  {
257
- boost::unique_lock<boost::mutex>& lock;
258
-
259
- relocker(boost::unique_lock<boost::mutex>& lock_):
260
- lock(lock_)
261
- {
262
- lock.unlock();
263
- }
264
- ~relocker()
265
- {
266
- lock.lock();
267
- }
268
- private:
269
- relocker& operator=(relocker const&);
270
- };
319
+ boost::unique_lock<boost::mutex> lock(mutex);
320
+ mark_finished_internal(lock);
321
+ }
271
322
 
272
323
  void do_callback(boost::unique_lock<boost::mutex>& lock)
273
324
  {
@@ -280,27 +331,49 @@ namespace boost
280
331
  }
281
332
 
282
333
 
283
- void wait(bool rethrow=true)
334
+ void wait_internal(boost::unique_lock<boost::mutex> &lock, bool rethrow=true)
284
335
  {
285
- boost::unique_lock<boost::mutex> lock(mutex);
286
- do_callback(lock);
287
- while(!done)
288
- {
289
- waiters.wait(lock);
290
- }
291
- if(rethrow && thread_was_interrupted)
336
+ do_callback(lock);
337
+ //if (!done) // fixme why this doesn't work?
338
+ {
339
+ if (is_deferred_)
292
340
  {
293
- throw boost::thread_interrupted();
341
+ is_deferred_=false;
342
+ execute(lock);
343
+ //lock.unlock();
294
344
  }
295
- if(rethrow && exception)
345
+ else
296
346
  {
297
- boost::rethrow_exception(exception);
347
+ while(!done)
348
+ {
349
+ waiters.wait(lock);
350
+ }
351
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
352
+ if(rethrow && thread_was_interrupted)
353
+ {
354
+ throw boost::thread_interrupted();
355
+ }
356
+ #endif
357
+ if(rethrow && exception)
358
+ {
359
+ boost::rethrow_exception(exception);
360
+ }
298
361
  }
362
+ }
363
+ }
364
+ void wait(bool rethrow=true)
365
+ {
366
+ boost::unique_lock<boost::mutex> lock(mutex);
367
+ wait_internal(lock, rethrow);
299
368
  }
300
369
 
370
+ #if defined BOOST_THREAD_USES_DATETIME
301
371
  bool timed_wait_until(boost::system_time const& target_time)
302
372
  {
303
373
  boost::unique_lock<boost::mutex> lock(mutex);
374
+ if (is_deferred_)
375
+ return false;
376
+
304
377
  do_callback(lock);
305
378
  while(!done)
306
379
  {
@@ -312,7 +385,7 @@ namespace boost
312
385
  }
313
386
  return true;
314
387
  }
315
-
388
+ #endif
316
389
  #ifdef BOOST_THREAD_USES_CHRONO
317
390
 
318
391
  template <class Clock, class Duration>
@@ -320,6 +393,8 @@ namespace boost
320
393
  wait_until(const chrono::time_point<Clock, Duration>& abs_time)
321
394
  {
322
395
  boost::unique_lock<boost::mutex> lock(mutex);
396
+ if (is_deferred_)
397
+ return future_status::deferred;
323
398
  do_callback(lock);
324
399
  while(!done)
325
400
  {
@@ -332,38 +407,95 @@ namespace boost
332
407
  return future_status::ready;
333
408
  }
334
409
  #endif
335
- void mark_exceptional_finish_internal(boost::exception_ptr const& e)
410
+ void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
336
411
  {
337
412
  exception=e;
338
- mark_finished_internal();
413
+ mark_finished_internal(lock);
339
414
  }
340
415
  void mark_exceptional_finish()
341
416
  {
342
- boost::lock_guard<boost::mutex> lock(mutex);
343
- mark_exceptional_finish_internal(boost::current_exception());
417
+ boost::unique_lock<boost::mutex> lock(mutex);
418
+ mark_exceptional_finish_internal(boost::current_exception(), lock);
344
419
  }
420
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
345
421
  void mark_interrupted_finish()
346
422
  {
347
- boost::lock_guard<boost::mutex> lock(mutex);
423
+ boost::unique_lock<boost::mutex> lock(mutex);
348
424
  thread_was_interrupted=true;
349
- mark_finished_internal();
425
+ mark_finished_internal(lock);
426
+ }
427
+ void set_interrupted_at_thread_exit()
428
+ {
429
+ unique_lock<boost::mutex> lk(mutex);
430
+ thread_was_interrupted=true;
431
+ if (has_value(lk))
432
+ {
433
+ throw_exception(promise_already_satisfied());
434
+ }
435
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
436
+ }
437
+ #endif
438
+ void set_exception_at_thread_exit(exception_ptr e)
439
+ {
440
+ unique_lock<boost::mutex> lk(mutex);
441
+ if (has_value(lk))
442
+ {
443
+ throw_exception(promise_already_satisfied());
444
+ }
445
+ exception=e;
446
+ this->is_constructed = true;
447
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
350
448
  }
351
449
  bool has_value()
352
450
  {
353
451
  boost::lock_guard<boost::mutex> lock(mutex);
354
- return done && !(exception || thread_was_interrupted);
452
+ return done && !(exception
453
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
454
+ || thread_was_interrupted
455
+ #endif
456
+ );
457
+ }
458
+ bool has_value(unique_lock<boost::mutex>& )
459
+ {
460
+ return done && !(exception
461
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
462
+ || thread_was_interrupted
463
+ #endif
464
+ );
355
465
  }
356
466
  bool has_exception()
357
467
  {
358
468
  boost::lock_guard<boost::mutex> lock(mutex);
359
- return done && (exception || thread_was_interrupted);
469
+ return done && (exception
470
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
471
+ || thread_was_interrupted
472
+ #endif
473
+ );
474
+ }
475
+ bool has_exception(unique_lock<boost::mutex>&)
476
+ {
477
+ return done && (exception
478
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
479
+ || thread_was_interrupted
480
+ #endif
481
+ );
482
+ }
483
+ bool is_deferred() const BOOST_NOEXCEPT {
484
+ return is_deferred_;
485
+ }
486
+
487
+ launch launch_policy() const BOOST_NOEXCEPT
488
+ {
489
+ return policy_;
360
490
  }
361
491
 
362
492
  template<typename F,typename U>
363
493
  void set_wait_callback(F f,U* u)
364
494
  {
495
+ boost::lock_guard<boost::mutex> lock(mutex);
365
496
  callback=boost::bind(f,boost::ref(*u));
366
497
  }
498
+ virtual void execute(boost::unique_lock<boost::mutex>&) {}
367
499
 
368
500
  private:
369
501
  future_object_base(future_object_base const&);
@@ -373,22 +505,27 @@ namespace boost
373
505
  template<typename T>
374
506
  struct future_traits
375
507
  {
376
- typedef boost::scoped_ptr<T> storage_type;
508
+ typedef boost::scoped_ptr<T> storage_type;
509
+ struct dummy;
377
510
  #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
378
- typedef T const& source_reference_type;
379
- struct dummy;
380
- typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
381
- typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type;
511
+ typedef T const& source_reference_type;
512
+ //typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
513
+ typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
514
+ //typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type;
515
+ typedef T move_dest_type;
382
516
  #elif defined BOOST_THREAD_USES_MOVE
383
- typedef T& source_reference_type;
384
- typedef typename boost::mpl::if_<boost::has_move_emulation_enabled<T>,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
385
- typedef typename boost::mpl::if_<boost::has_move_emulation_enabled<T>,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
517
+ typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,T&>::type source_reference_type;
518
+ //typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
519
+ //typedef typename boost::mpl::if_c<boost::enable_move_utility_emulation<T>::value,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
520
+ typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
521
+ typedef T move_dest_type;
386
522
  #else
387
- typedef T& source_reference_type;
388
- typedef typename boost::mpl::if_<boost::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
389
- typedef typename boost::mpl::if_<boost::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
523
+ typedef T& source_reference_type;
524
+ typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
525
+ typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
390
526
  #endif
391
527
 
528
+
392
529
  typedef const T& shared_future_get_result_type;
393
530
 
394
531
  static void init(storage_type& storage,source_reference_type t)
@@ -398,7 +535,11 @@ namespace boost
398
535
 
399
536
  static void init(storage_type& storage,rvalue_source_type t)
400
537
  {
538
+ #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
539
+ storage.reset(new T(boost::forward<T>(t)));
540
+ #else
401
541
  storage.reset(new T(static_cast<rvalue_source_type>(t)));
542
+ #endif
402
543
  }
403
544
 
404
545
  static void cleanup(storage_type& storage)
@@ -412,8 +553,8 @@ namespace boost
412
553
  {
413
554
  typedef T* storage_type;
414
555
  typedef T& source_reference_type;
415
- struct rvalue_source_type
416
- {};
556
+ //struct rvalue_source_type
557
+ //{};
417
558
  typedef T& move_dest_type;
418
559
  typedef T& shared_future_get_result_type;
419
560
 
@@ -447,6 +588,7 @@ namespace boost
447
588
 
448
589
  };
449
590
 
591
+ // Used to create stand-alone futures
450
592
  template<typename T>
451
593
  struct future_object:
452
594
  detail::future_object_base
@@ -463,42 +605,163 @@ namespace boost
463
605
  result(0)
464
606
  {}
465
607
 
466
- void mark_finished_with_result_internal(source_reference_type result_)
608
+ ~future_object()
609
+ {}
610
+
611
+ void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
467
612
  {
468
613
  future_traits<T>::init(result,result_);
469
- mark_finished_internal();
614
+ this->mark_finished_internal(lock);
470
615
  }
471
616
 
472
- void mark_finished_with_result_internal(rvalue_source_type result_)
617
+ void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
473
618
  {
619
+ #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
620
+ future_traits<T>::init(result,boost::forward<T>(result_));
621
+ #else
474
622
  future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
475
- mark_finished_internal();
623
+ #endif
624
+ this->mark_finished_internal(lock);
476
625
  }
477
626
 
478
627
  void mark_finished_with_result(source_reference_type result_)
479
628
  {
480
- boost::lock_guard<boost::mutex> lock(mutex);
481
- mark_finished_with_result_internal(result_);
629
+ boost::unique_lock<boost::mutex> lock(mutex);
630
+ this->mark_finished_with_result_internal(result_, lock);
482
631
  }
483
632
 
484
633
  void mark_finished_with_result(rvalue_source_type result_)
485
634
  {
486
- boost::lock_guard<boost::mutex> lock(mutex);
487
- mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_));
635
+ boost::unique_lock<boost::mutex> lock(mutex);
636
+
637
+ #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
638
+ mark_finished_with_result_internal(boost::forward<T>(result_), lock);
639
+ #else
640
+ mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
641
+ #endif
488
642
  }
489
643
 
490
- move_dest_type get()
644
+
645
+ virtual move_dest_type get()
491
646
  {
492
647
  wait();
493
- return static_cast<move_dest_type>(*result);
648
+ return boost::move(*result);
494
649
  }
495
650
 
496
651
  shared_future_get_result_type get_sh()
497
652
  {
498
653
  wait();
499
- return static_cast<shared_future_get_result_type>(*result);
654
+ return *result;
655
+ }
656
+
657
+ // todo move this to detail::future_object_base
658
+ future_state::state get_state()
659
+ {
660
+ boost::lock_guard<boost::mutex> guard(mutex);
661
+ if(!done)
662
+ {
663
+ return future_state::waiting;
664
+ }
665
+ else
666
+ {
667
+ return future_state::ready;
668
+ }
669
+ }
670
+
671
+
672
+ //void set_value_at_thread_exit(const T & result_)
673
+ void set_value_at_thread_exit(source_reference_type result_)
674
+ {
675
+ unique_lock<boost::mutex> lk(this->mutex);
676
+ if (this->has_value(lk))
677
+ {
678
+ throw_exception(promise_already_satisfied());
679
+ }
680
+ //future_traits<T>::init(result,result_);
681
+ result.reset(new T(result_));
682
+
683
+ this->is_constructed = true;
684
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
685
+ }
686
+ //void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_)
687
+ void set_value_at_thread_exit(rvalue_source_type result_)
688
+ {
689
+ unique_lock<boost::mutex> lk(this->mutex);
690
+ if (this->has_value(lk))
691
+ throw_exception(promise_already_satisfied());
692
+ result.reset(new T(boost::move(result_)));
693
+ //future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
694
+ this->is_constructed = true;
695
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
696
+ }
697
+
698
+
699
+ private:
700
+ future_object(future_object const&);
701
+ future_object& operator=(future_object const&);
702
+ };
703
+
704
+ template<typename T>
705
+ struct future_object<T&>:
706
+ detail::future_object_base
707
+ {
708
+ typedef typename future_traits<T&>::storage_type storage_type;
709
+ typedef typename future_traits<T&>::source_reference_type source_reference_type;
710
+ //typedef typename future_traits<T&>::rvalue_source_type rvalue_source_type;
711
+ typedef typename future_traits<T&>::move_dest_type move_dest_type;
712
+ typedef typename future_traits<T&>::shared_future_get_result_type shared_future_get_result_type;
713
+
714
+ T* result;
715
+
716
+ future_object():
717
+ result(0)
718
+ {}
719
+
720
+ ~future_object()
721
+ {
722
+ }
723
+
724
+ void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
725
+ {
726
+ //future_traits<T>::init(result,result_);
727
+ result= &result_;
728
+ mark_finished_internal(lock);
729
+ }
730
+
731
+ // void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
732
+ // {
733
+ // future_traits<T&>::init(result,static_cast<rvalue_source_type>(result_));
734
+ // mark_finished_internal(lock);
735
+ // }
736
+
737
+ void mark_finished_with_result(source_reference_type result_)
738
+ {
739
+ boost::unique_lock<boost::mutex> lock(mutex);
740
+ mark_finished_with_result_internal(result_, lock);
741
+ }
742
+
743
+ // void mark_finished_with_result(rvalue_source_type result_)
744
+ // {
745
+ // boost::unique_lock<boost::mutex> lock(mutex);
746
+ // mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
747
+ // }
748
+
749
+
750
+ T& get()
751
+ {
752
+ wait();
753
+ //return static_cast<T&>(*result);
754
+ return *result;
755
+ }
756
+
757
+ T& get_sh()
758
+ {
759
+ wait();
760
+ //return static_cast<shared_future_get_result_type>(*result);
761
+ return *result;
500
762
  }
501
763
 
764
+ // todo move this to detail::future_object_base
502
765
  future_state::state get_state()
503
766
  {
504
767
  boost::lock_guard<boost::mutex> guard(mutex);
@@ -512,6 +775,27 @@ namespace boost
512
775
  }
513
776
  }
514
777
 
778
+ void set_value_at_thread_exit(T& result_)
779
+ {
780
+ unique_lock<boost::mutex> lk(this->mutex);
781
+ if (this->has_value(lk))
782
+ throw_exception(promise_already_satisfied());
783
+ //future_traits<T>::init(result,result_);
784
+ result= &result_;
785
+ this->is_constructed = true;
786
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
787
+ }
788
+ // void set_value_at_thread_exit(rvalue_source_type result_)
789
+ // {
790
+ // unique_lock<boost::mutex> lk(this->mutex);
791
+ // if (this->has_value())
792
+ // throw_exception(promise_already_satisfied());
793
+ // future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
794
+ // this->is_constructed = true;
795
+ // get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
796
+ // }
797
+
798
+
515
799
  private:
516
800
  future_object(future_object const&);
517
801
  future_object& operator=(future_object const&);
@@ -526,25 +810,26 @@ namespace boost
526
810
  future_object()
527
811
  {}
528
812
 
529
- void mark_finished_with_result_internal()
813
+ void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
530
814
  {
531
- mark_finished_internal();
815
+ mark_finished_internal(lock);
532
816
  }
533
817
 
534
818
  void mark_finished_with_result()
535
819
  {
536
- boost::lock_guard<boost::mutex> lock(mutex);
537
- mark_finished_with_result_internal();
820
+ boost::unique_lock<boost::mutex> lock(mutex);
821
+ mark_finished_with_result_internal(lock);
538
822
  }
539
823
 
540
824
  void get()
541
825
  {
542
- wait();
826
+ this->wait();
543
827
  }
544
828
  void get_sh()
545
829
  {
546
830
  wait();
547
831
  }
832
+ // todo move this to detail::future_object_base
548
833
  future_state::state get_state()
549
834
  {
550
835
  boost::lock_guard<boost::mutex> guard(mutex);
@@ -557,50 +842,279 @@ namespace boost
557
842
  return future_state::ready;
558
843
  }
559
844
  }
845
+ void set_value_at_thread_exit()
846
+ {
847
+ unique_lock<boost::mutex> lk(this->mutex);
848
+ if (this->has_value(lk))
849
+ {
850
+ throw_exception(promise_already_satisfied());
851
+ }
852
+ this->is_constructed = true;
853
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
854
+ }
560
855
  private:
561
856
  future_object(future_object const&);
562
857
  future_object& operator=(future_object const&);
563
858
  };
564
859
 
565
- // template<typename T, typename Allocator>
566
- // struct future_object_alloc: public future_object<T>
567
- // {
568
- // typedef future_object<T> base;
569
- // Allocator alloc_;
570
- //
571
- // public:
572
- // explicit future_object_alloc(const Allocator& a)
573
- // : alloc_(a) {}
574
- //
575
- // };
576
- class future_waiter
860
+ /////////////////////////
861
+ /// future_async_object
862
+ /////////////////////////
863
+ template<typename Rp, typename Fp>
864
+ struct future_async_object: future_object<Rp>
577
865
  {
578
- struct registered_waiter;
579
- typedef std::vector<int>::size_type count_type;
866
+ typedef future_object<Rp> base_type;
867
+ typedef typename base_type::move_dest_type move_dest_type;
580
868
 
581
- struct registered_waiter
582
- {
583
- boost::shared_ptr<detail::future_object_base> future_;
584
- detail::future_object_base::waiter_list::iterator wait_iterator;
585
- count_type index;
869
+ boost::thread thr_;
586
870
 
587
- registered_waiter(boost::shared_ptr<detail::future_object_base> const& a_future,
588
- detail::future_object_base::waiter_list::iterator wait_iterator_,
589
- count_type index_):
590
- future_(a_future),wait_iterator(wait_iterator_),index(index_)
591
- {}
871
+ public:
872
+ explicit future_async_object(BOOST_THREAD_FWD_REF(Fp) f) :
873
+ thr_(&future_async_object::run, this, boost::forward<Fp>(f))
874
+ {
875
+ this->set_async();
876
+ }
592
877
 
593
- };
878
+ ~future_async_object()
879
+ {
880
+ if (thr_.joinable()) thr_.join();
881
+ }
594
882
 
595
- struct all_futures_lock
883
+ move_dest_type get()
884
+ {
885
+ if (thr_.joinable()) thr_.join();
886
+ // fixme Is the lock needed during the whole scope?
887
+ //this->wait();
888
+ boost::unique_lock<boost::mutex> lock(this->mutex);
889
+ this->wait_internal(lock);
890
+
891
+ //return static_cast<move_dest_type>(*(this->result));
892
+ //return boost::move<Rp>(*(this->result));
893
+ return boost::move(*(this->result));
894
+ }
895
+ static void run(future_async_object* that, BOOST_THREAD_FWD_REF(Fp) f)
896
+ {
897
+ try
596
898
  {
597
- #ifdef _MANAGED
598
- typedef std::ptrdiff_t count_type_portable;
599
- #else
600
- typedef count_type count_type_portable;
899
+ that->mark_finished_with_result(f());
900
+ }
901
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
902
+ catch(thread_interrupted& )
903
+ {
904
+ that->mark_interrupted_finish();
905
+ }
601
906
  #endif
602
- count_type_portable count;
603
- boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
907
+ catch(...)
908
+ {
909
+ that->mark_exceptional_finish();
910
+ }
911
+ }
912
+ };
913
+
914
+ template<typename Fp>
915
+ struct future_async_object<void, Fp>: public future_object<void>
916
+ {
917
+ typedef future_object<void> base_type;
918
+ boost::thread thr_;
919
+
920
+ public:
921
+ explicit future_async_object(BOOST_THREAD_FWD_REF(Fp) f) :
922
+ thr_(&future_async_object::run, this, boost::forward<Fp>(f))
923
+ {
924
+ this->set_async();
925
+ }
926
+
927
+ ~future_async_object()
928
+ {
929
+ if (thr_.joinable()) thr_.join();
930
+ }
931
+
932
+ static void run(future_async_object* that, BOOST_THREAD_FWD_REF(Fp) f)
933
+ {
934
+ try
935
+ {
936
+ f();
937
+ that->mark_finished_with_result();
938
+ }
939
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
940
+ catch(thread_interrupted& )
941
+ {
942
+ that->mark_interrupted_finish();
943
+ }
944
+ #endif
945
+ catch(...)
946
+ {
947
+ that->mark_exceptional_finish();
948
+ }
949
+ }
950
+ };
951
+
952
+ template<typename Rp, typename Fp>
953
+ struct future_async_object<Rp&, Fp>: future_object<Rp&>
954
+ {
955
+ typedef future_object<Rp&> base_type;
956
+ typedef typename base_type::move_dest_type move_dest_type;
957
+
958
+ boost::thread thr_;
959
+
960
+ public:
961
+ explicit future_async_object(BOOST_THREAD_FWD_REF(Fp) f) :
962
+ thr_(&future_async_object::run, this, boost::forward<Fp>(f))
963
+ {
964
+ this->set_async();
965
+ }
966
+
967
+ ~future_async_object()
968
+ {
969
+ if (thr_.joinable()) thr_.join();
970
+ }
971
+
972
+ move_dest_type get()
973
+ {
974
+ if (thr_.joinable()) thr_.join();
975
+ // fixme Is the lock needed during the whole scope?
976
+ //this->wait();
977
+ boost::unique_lock<boost::mutex> lock(this->mutex);
978
+ this->wait_internal(lock);
979
+
980
+ //return static_cast<move_dest_type>(*(this->result));
981
+ return boost::move(*(this->result));
982
+ }
983
+ static void run(future_async_object* that, BOOST_THREAD_FWD_REF(Fp) f)
984
+ {
985
+ try
986
+ {
987
+ that->mark_finished_with_result(f());
988
+ }
989
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
990
+ catch(thread_interrupted& )
991
+ {
992
+ that->mark_interrupted_finish();
993
+ }
994
+ #endif
995
+ catch(...)
996
+ {
997
+ that->mark_exceptional_finish();
998
+ }
999
+ }
1000
+ };
1001
+
1002
+ //////////////////////////
1003
+ /// future_deferred_object
1004
+ //////////////////////////
1005
+ template<typename Rp, typename Fp>
1006
+ struct future_deferred_object: future_object<Rp>
1007
+ {
1008
+ typedef future_object<Rp> base_type;
1009
+ Fp func_;
1010
+
1011
+ public:
1012
+ explicit future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f)
1013
+ : func_(boost::forward<Fp>(f))
1014
+ {
1015
+ this->set_deferred();
1016
+ }
1017
+
1018
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
1019
+ try
1020
+ {
1021
+ this->mark_finished_with_result_internal(func_(), lck);
1022
+ }
1023
+ catch (...)
1024
+ {
1025
+ this->mark_exceptional_finish_internal(current_exception(), lck);
1026
+ }
1027
+ }
1028
+ };
1029
+ template<typename Rp, typename Fp>
1030
+ struct future_deferred_object<Rp&,Fp>: future_object<Rp&>
1031
+ {
1032
+ typedef future_object<Rp&> base_type;
1033
+ Fp func_;
1034
+
1035
+ public:
1036
+ explicit future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f)
1037
+ : func_(boost::forward<Fp>(f))
1038
+ {
1039
+ this->set_deferred();
1040
+ }
1041
+
1042
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
1043
+ try
1044
+ {
1045
+ this->mark_finished_with_result_internal(func_(), lck);
1046
+ }
1047
+ catch (...)
1048
+ {
1049
+ this->mark_exceptional_finish_internal(current_exception(), lck);
1050
+ }
1051
+ }
1052
+ };
1053
+
1054
+ template<typename Fp>
1055
+ struct future_deferred_object<void,Fp>: future_object<void>
1056
+ {
1057
+ typedef future_object<void> base_type;
1058
+ Fp func_;
1059
+
1060
+ public:
1061
+ explicit future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f)
1062
+ : func_(boost::forward<Fp>(f))
1063
+ {
1064
+ this->set_deferred();
1065
+ }
1066
+
1067
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
1068
+ try
1069
+ {
1070
+ func_();
1071
+ this->mark_finished_with_result_internal(lck);
1072
+ }
1073
+ catch (...)
1074
+ {
1075
+ this->mark_exceptional_finish_internal(current_exception(), lck);
1076
+ }
1077
+ }
1078
+ };
1079
+
1080
+ // template<typename T, typename Allocator>
1081
+ // struct future_object_alloc: public future_object<T>
1082
+ // {
1083
+ // typedef future_object<T> base;
1084
+ // Allocator alloc_;
1085
+ //
1086
+ // public:
1087
+ // explicit future_object_alloc(const Allocator& a)
1088
+ // : alloc_(a) {}
1089
+ //
1090
+ // };
1091
+ class future_waiter
1092
+ {
1093
+ struct registered_waiter;
1094
+ typedef std::vector<int>::size_type count_type;
1095
+
1096
+ struct registered_waiter
1097
+ {
1098
+ boost::shared_ptr<detail::future_object_base> future_;
1099
+ detail::future_object_base::waiter_list::iterator wait_iterator;
1100
+ count_type index;
1101
+
1102
+ registered_waiter(boost::shared_ptr<detail::future_object_base> const& a_future,
1103
+ detail::future_object_base::waiter_list::iterator wait_iterator_,
1104
+ count_type index_):
1105
+ future_(a_future),wait_iterator(wait_iterator_),index(index_)
1106
+ {}
1107
+ };
1108
+
1109
+ struct all_futures_lock
1110
+ {
1111
+ #ifdef _MANAGED
1112
+ typedef std::ptrdiff_t count_type_portable;
1113
+ #else
1114
+ typedef count_type count_type_portable;
1115
+ #endif
1116
+ count_type_portable count;
1117
+ boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
604
1118
 
605
1119
  all_futures_lock(std::vector<registered_waiter>& futures):
606
1120
  count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
@@ -610,7 +1124,7 @@ namespace boost
610
1124
  #if defined __DECCXX || defined __SUNPRO_CC || defined __hpux
611
1125
  locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex).move();
612
1126
  #else
613
- locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex);
1127
+ locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex); // TODO shouldn't be moved explicitly
614
1128
  #endif
615
1129
  }
616
1130
  }
@@ -805,70 +1319,53 @@ namespace boost
805
1319
  template <typename R>
806
1320
  class packaged_task;
807
1321
 
808
- template <typename R>
809
- class BOOST_THREAD_FUTURE
1322
+ namespace detail
810
1323
  {
811
- private:
1324
+ /// Common implementation for all the futures independently of the return type
1325
+ class base_future
1326
+ {
1327
+ //BOOST_THREAD_MOVABLE(base_future)
1328
+
1329
+ };
1330
+ /// Common implementation for future and shared_future.
1331
+ template <typename R>
1332
+ class basic_future : public base_future
1333
+ {
1334
+ protected:
812
1335
 
813
1336
  typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
814
1337
 
815
1338
  future_ptr future_;
816
1339
 
817
- friend class shared_future<R>;
818
- friend class promise<R>;
819
- friend class packaged_task<R>;
820
- friend class detail::future_waiter;
821
-
822
- typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
823
-
824
- BOOST_THREAD_FUTURE(future_ptr a_future):
825
- future_(a_future)
826
- {}
1340
+ basic_future(future_ptr a_future):
1341
+ future_(a_future)
1342
+ {
1343
+ }
1344
+ // Copy construction from a shared_future
1345
+ explicit basic_future(const shared_future<R>&) BOOST_NOEXCEPT;
827
1346
 
828
- public:
829
- BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
1347
+ public:
830
1348
  typedef future_state::state state;
831
1349
 
832
- BOOST_THREAD_FUTURE()
833
- {}
834
-
835
- ~BOOST_THREAD_FUTURE()
836
- {}
1350
+ BOOST_THREAD_MOVABLE(basic_future)
1351
+ basic_future(): future_() {}
1352
+ ~basic_future() {}
837
1353
 
838
- BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
839
- future_(BOOST_THREAD_RV(other).future_)
1354
+ basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT:
1355
+ future_(BOOST_THREAD_RV(other).future_)
840
1356
  {
841
1357
  BOOST_THREAD_RV(other).future_.reset();
842
1358
  }
843
-
844
- BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
1359
+ basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT
845
1360
  {
846
1361
  future_=BOOST_THREAD_RV(other).future_;
847
1362
  BOOST_THREAD_RV(other).future_.reset();
848
1363
  return *this;
849
1364
  }
850
-
851
- shared_future<R> share()
852
- {
853
- return shared_future<R>(::boost::move(*this));
854
- }
855
-
856
- void swap(BOOST_THREAD_FUTURE& other)
857
- {
858
- future_.swap(other.future_);
859
- }
860
-
861
- // retrieving the value
862
- move_dest_type get()
1365
+ void swap(basic_future& that) BOOST_NOEXCEPT
863
1366
  {
864
- if(!future_)
865
- {
866
- boost::throw_exception(future_uninitialized());
867
- }
868
-
869
- return future_->get();
1367
+ future_.swap(that.future_);
870
1368
  }
871
-
872
1369
  // functions to check state, and wait for ready
873
1370
  state get_state() const BOOST_NOEXCEPT
874
1371
  {
@@ -894,6 +1391,12 @@ namespace boost
894
1391
  return future_ && future_->has_value();
895
1392
  }
896
1393
 
1394
+ launch launch_policy() const BOOST_NOEXCEPT
1395
+ {
1396
+ if ( future_ ) return future_->launch_policy();
1397
+ else return launch(launch::none);
1398
+ }
1399
+
897
1400
  bool valid() const BOOST_NOEXCEPT
898
1401
  {
899
1402
  return future_ != 0;
@@ -909,6 +1412,7 @@ namespace boost
909
1412
  future_->wait(false);
910
1413
  }
911
1414
 
1415
+ #if defined BOOST_THREAD_USES_DATETIME
912
1416
  template<typename Duration>
913
1417
  bool timed_wait(Duration const& rel_time) const
914
1418
  {
@@ -923,6 +1427,7 @@ namespace boost
923
1427
  }
924
1428
  return future_->timed_wait_until(abs_time);
925
1429
  }
1430
+ #endif
926
1431
  #ifdef BOOST_THREAD_USES_CHRONO
927
1432
  template <class Rep, class Period>
928
1433
  future_status
@@ -942,35 +1447,192 @@ namespace boost
942
1447
  return future_->wait_until(abs_time);
943
1448
  }
944
1449
  #endif
1450
+
1451
+ };
1452
+
1453
+ } // detail
1454
+ BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END
1455
+
1456
+ namespace detail
1457
+ {
1458
+ #if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005
1459
+ template <class Rp, class Fp>
1460
+ BOOST_THREAD_FUTURE<Rp>
1461
+ make_future_async_object(BOOST_THREAD_FWD_REF(Fp) f);
1462
+
1463
+ template <class Rp, class Fp>
1464
+ BOOST_THREAD_FUTURE<Rp>
1465
+ make_future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f);
1466
+ #endif // #if (!defined _MSC_VER || _MSC_VER >= 1400)
1467
+
1468
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1469
+ template <class F, class Rp, class Fp>
1470
+ BOOST_THREAD_FUTURE<Rp>
1471
+ make_future_async_continuation(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
1472
+
1473
+ template <class F, class Rp, class Fp>
1474
+ BOOST_THREAD_FUTURE<Rp>
1475
+ make_future_deferred_continuation(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
1476
+ #endif
1477
+
1478
+ }
1479
+
1480
+ template <typename R>
1481
+ class BOOST_THREAD_FUTURE : public detail::basic_future<R>
1482
+ {
1483
+ private:
1484
+ typedef detail::basic_future<R> base_type;
1485
+ typedef typename base_type::future_ptr future_ptr;
1486
+
1487
+ friend class shared_future<R>;
1488
+ friend class promise<R>;
1489
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1490
+ template <typename, typename, typename>
1491
+ friend struct detail::future_async_continuation;
1492
+ template <typename, typename, typename>
1493
+ friend struct detail::future_deferred_continuation;
1494
+ #endif
1495
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1496
+ template <class> friend class packaged_task; // todo check if this works in windows
1497
+ #else
1498
+ friend class packaged_task<R>;
1499
+ #endif
1500
+ friend class detail::future_waiter;
1501
+
1502
+ template <class Rp, class Fp>
1503
+ friend BOOST_THREAD_FUTURE<Rp>
1504
+ detail::make_future_async_object(BOOST_THREAD_FWD_REF(Fp) f);
1505
+
1506
+ template <class Rp, class Fp>
1507
+ friend BOOST_THREAD_FUTURE<Rp>
1508
+ detail::make_future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f);
1509
+
1510
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1511
+ template <class F, class Rp, class Fp>
1512
+ friend BOOST_THREAD_FUTURE<Rp>
1513
+ detail::make_future_async_continuation(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
1514
+
1515
+ template <class F, class Rp, class Fp>
1516
+ friend BOOST_THREAD_FUTURE<Rp>
1517
+ detail::make_future_deferred_continuation(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
1518
+ #endif
1519
+
1520
+ typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
1521
+
1522
+ BOOST_THREAD_FUTURE(future_ptr a_future):
1523
+ base_type(a_future)
1524
+ {
1525
+ }
1526
+
1527
+ public:
1528
+ BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
1529
+ typedef future_state::state state;
1530
+
1531
+ BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
1532
+
1533
+ ~BOOST_THREAD_FUTURE() {}
1534
+
1535
+ BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
1536
+ base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
1537
+ {
1538
+ }
1539
+
1540
+ BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
1541
+ {
1542
+ this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1543
+ return *this;
1544
+ }
1545
+
1546
+ shared_future<R> share()
1547
+ {
1548
+ return shared_future<R>(::boost::move(*this));
1549
+ }
1550
+
1551
+ void swap(BOOST_THREAD_FUTURE& other)
1552
+ {
1553
+ static_cast<base_type*>(this)->swap(other);
1554
+ }
1555
+
1556
+ // todo this functio�n must be private and friendship provided to the internal users.
1557
+ void set_async()
1558
+ {
1559
+ this->future_->set_async();
1560
+ }
1561
+ // todo this functio�n must be private and friendship provided to the internal users.
1562
+ void set_deferred()
1563
+ {
1564
+ this->future_->set_deferred();
1565
+ }
1566
+
1567
+ // retrieving the value
1568
+ move_dest_type get()
1569
+ {
1570
+ if(!this->future_)
1571
+ {
1572
+ boost::throw_exception(future_uninitialized());
1573
+ }
1574
+ #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
1575
+ future_ptr fut_=this->future_;
1576
+ this->future_.reset();
1577
+ return fut_->get();
1578
+
1579
+ #else
1580
+ return this->future_->get();
1581
+ #endif
1582
+ }
1583
+
1584
+
1585
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
1586
+
1587
+ // template<typename F>
1588
+ // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
1589
+
1590
+ //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
1591
+ // template<typename RF>
1592
+ // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&));
1593
+ // template<typename RF>
1594
+ // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&));
1595
+ //#endif
1596
+ template<typename F>
1597
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE&)>::type>
1598
+ then(BOOST_THREAD_FWD_REF(F) func);
1599
+ template<typename F>
1600
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE&)>::type>
1601
+ then(launch policy, BOOST_THREAD_FWD_REF(F) func);
1602
+ #endif
945
1603
  };
946
1604
 
947
1605
  BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
948
1606
 
949
1607
  template <typename R>
950
- class shared_future
1608
+ class shared_future : public detail::basic_future<R>
951
1609
  {
952
- typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
953
1610
 
954
- future_ptr future_;
1611
+ typedef detail::basic_future<R> base_type;
1612
+ typedef typename base_type::future_ptr future_ptr;
955
1613
 
956
1614
  friend class detail::future_waiter;
957
1615
  friend class promise<R>;
958
- friend class packaged_task<R>;
959
1616
 
1617
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
1618
+ template <class> friend class packaged_task;// todo check if this works in windows
1619
+ #else
1620
+ friend class packaged_task<R>;
1621
+ #endif
960
1622
  shared_future(future_ptr a_future):
961
- future_(a_future)
1623
+ base_type(a_future)
962
1624
  {}
963
1625
 
964
1626
  public:
965
1627
  BOOST_THREAD_MOVABLE(shared_future)
966
1628
 
967
1629
  shared_future(shared_future const& other):
968
- future_(other.future_)
1630
+ base_type(other)
969
1631
  {}
970
1632
 
971
1633
  typedef future_state::state state;
972
1634
 
973
- shared_future()
1635
+ BOOST_CONSTEXPR shared_future()
974
1636
  {}
975
1637
 
976
1638
  ~shared_future()
@@ -978,141 +1640,250 @@ namespace boost
978
1640
 
979
1641
  shared_future& operator=(shared_future const& other)
980
1642
  {
981
- future_=other.future_;
1643
+ shared_future(other).swap(*this);
982
1644
  return *this;
983
1645
  }
984
1646
  shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT :
985
- future_(BOOST_THREAD_RV(other).future_)
1647
+ base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
986
1648
  {
987
1649
  BOOST_THREAD_RV(other).future_.reset();
988
1650
  }
989
- shared_future(BOOST_THREAD_RV_REF_BEG BOOST_THREAD_FUTURE<R> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT :
990
- future_(BOOST_THREAD_RV(other).future_)
1651
+ shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT :
1652
+ base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
991
1653
  {
992
- BOOST_THREAD_RV(other).future_.reset();
993
1654
  }
1655
+
994
1656
  shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT
995
1657
  {
996
- future_.swap(BOOST_THREAD_RV(other).future_);
997
- BOOST_THREAD_RV(other).future_.reset();
1658
+ base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
998
1659
  return *this;
999
1660
  }
1000
- shared_future& operator=(BOOST_THREAD_RV_REF_BEG BOOST_THREAD_FUTURE<R> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT
1661
+ shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT
1001
1662
  {
1002
- future_.swap(BOOST_THREAD_RV(other).future_);
1003
- BOOST_THREAD_RV(other).future_.reset();
1663
+ base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
1664
+ //shared_future(boost::move(other)).swap(*this);
1665
+ //this->future_.swap(BOOST_THREAD_RV(other).future_);
1666
+ //BOOST_THREAD_RV(other).future_.reset();
1004
1667
  return *this;
1005
1668
  }
1006
1669
 
1007
1670
  void swap(shared_future& other) BOOST_NOEXCEPT
1008
1671
  {
1009
- future_.swap(other.future_);
1672
+ static_cast<base_type*>(this)->swap(other);
1010
1673
  }
1011
1674
 
1012
1675
  // retrieving the value
1013
1676
  typename detail::future_object<R>::shared_future_get_result_type get()
1014
1677
  {
1015
- if(!future_)
1678
+ if(!this->future_)
1016
1679
  {
1017
1680
  boost::throw_exception(future_uninitialized());
1018
1681
  }
1019
1682
 
1020
- return future_->get_sh();
1683
+ return this->future_->get_sh();
1021
1684
  }
1022
1685
 
1023
- // functions to check state, and wait for ready
1024
- state get_state() const BOOST_NOEXCEPT
1686
+ };
1687
+
1688
+ BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
1689
+
1690
+ namespace detail
1691
+ {
1692
+ /// Copy construction from a shared_future
1693
+ template <typename R>
1694
+ inline basic_future<R>::basic_future(const shared_future<R>& other) BOOST_NOEXCEPT
1695
+ : future_(other.future_)
1696
+ {
1697
+ }
1698
+ }
1699
+
1700
+ template <typename R>
1701
+ class promise
1702
+ {
1703
+ typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
1704
+
1705
+ future_ptr future_;
1706
+ bool future_obtained;
1707
+
1708
+ void lazy_init()
1025
1709
  {
1026
- if(!future_)
1710
+ #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
1711
+ #include <boost/detail/atomic_undef_macros.hpp>
1712
+ if(!atomic_load(&future_))
1027
1713
  {
1028
- return future_state::uninitialized;
1714
+ future_ptr blank;
1715
+ atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R>));
1029
1716
  }
1030
- return future_->get_state();
1717
+ #include <boost/detail/atomic_redef_macros.hpp>
1718
+ #endif
1031
1719
  }
1032
1720
 
1033
- bool valid() const BOOST_NOEXCEPT
1721
+ public:
1722
+ BOOST_THREAD_MOVABLE_ONLY(promise)
1723
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
1724
+ template <class Allocator>
1725
+ promise(boost::allocator_arg_t, Allocator a)
1034
1726
  {
1035
- return future_ != 0;
1727
+ typedef typename Allocator::template rebind<detail::future_object<R> >::other A2;
1728
+ A2 a2(a);
1729
+ typedef thread_detail::allocator_destructor<A2> D;
1730
+
1731
+ future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<R>(), D(a2, 1) );
1732
+ future_obtained = false;
1036
1733
  }
1734
+ #endif
1735
+ promise():
1736
+ #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
1737
+ future_(),
1738
+ #else
1739
+ future_(new detail::future_object<R>()),
1740
+ #endif
1741
+ future_obtained(false)
1742
+ {}
1037
1743
 
1038
- bool is_ready() const BOOST_NOEXCEPT
1744
+ ~promise()
1039
1745
  {
1040
- return get_state()==future_state::ready;
1746
+ if(future_)
1747
+ {
1748
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
1749
+
1750
+ if(!future_->done && !future_->is_constructed)
1751
+ {
1752
+ future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
1753
+ }
1754
+ }
1041
1755
  }
1042
1756
 
1043
- bool has_exception() const BOOST_NOEXCEPT
1757
+ // Assignment
1758
+ promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
1759
+ future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
1044
1760
  {
1045
- return future_ && future_->has_exception();
1761
+ BOOST_THREAD_RV(rhs).future_.reset();
1762
+ BOOST_THREAD_RV(rhs).future_obtained=false;
1763
+ }
1764
+ promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
1765
+ {
1766
+ future_=BOOST_THREAD_RV(rhs).future_;
1767
+ future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
1768
+ BOOST_THREAD_RV(rhs).future_.reset();
1769
+ BOOST_THREAD_RV(rhs).future_obtained=false;
1770
+ return *this;
1046
1771
  }
1047
1772
 
1048
- bool has_value() const BOOST_NOEXCEPT
1773
+ void swap(promise& other)
1049
1774
  {
1050
- return future_ && future_->has_value();
1775
+ future_.swap(other.future_);
1776
+ std::swap(future_obtained,other.future_obtained);
1051
1777
  }
1052
1778
 
1053
- void wait() const
1779
+ // Result retrieval
1780
+ BOOST_THREAD_FUTURE<R> get_future()
1054
1781
  {
1055
- if(!future_)
1782
+ lazy_init();
1783
+ if (future_.get()==0)
1056
1784
  {
1057
- boost::throw_exception(future_uninitialized());
1785
+ boost::throw_exception(promise_moved());
1058
1786
  }
1059
- future_->wait(false);
1787
+ if (future_obtained)
1788
+ {
1789
+ boost::throw_exception(future_already_retrieved());
1790
+ }
1791
+ future_obtained=true;
1792
+ return BOOST_THREAD_FUTURE<R>(future_);
1060
1793
  }
1061
1794
 
1062
- template<typename Duration>
1063
- bool timed_wait(Duration const& rel_time) const
1795
+ void set_value(typename detail::future_traits<R>::source_reference_type r)
1064
1796
  {
1065
- return timed_wait_until(boost::get_system_time()+rel_time);
1797
+ lazy_init();
1798
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
1799
+ if(future_->done)
1800
+ {
1801
+ boost::throw_exception(promise_already_satisfied());
1802
+ }
1803
+ future_->mark_finished_with_result_internal(r, lock);
1066
1804
  }
1067
1805
 
1068
- bool timed_wait_until(boost::system_time const& abs_time) const
1806
+ // void set_value(R && r);
1807
+ void set_value(typename detail::future_traits<R>::rvalue_source_type r)
1069
1808
  {
1070
- if(!future_)
1809
+ lazy_init();
1810
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
1811
+ if(future_->done)
1071
1812
  {
1072
- boost::throw_exception(future_uninitialized());
1813
+ boost::throw_exception(promise_already_satisfied());
1073
1814
  }
1074
- return future_->timed_wait_until(abs_time);
1815
+ #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
1816
+ future_->mark_finished_with_result_internal(boost::forward<R>(r), lock);
1817
+ #else
1818
+ future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r), lock);
1819
+ #endif
1075
1820
  }
1076
- #ifdef BOOST_THREAD_USES_CHRONO
1077
1821
 
1078
- template <class Rep, class Period>
1079
- future_status
1080
- wait_for(const chrono::duration<Rep, Period>& rel_time) const
1822
+ void set_exception(boost::exception_ptr p)
1081
1823
  {
1082
- return wait_until(chrono::steady_clock::now() + rel_time);
1824
+ lazy_init();
1825
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
1826
+ if(future_->done)
1827
+ {
1828
+ boost::throw_exception(promise_already_satisfied());
1829
+ }
1830
+ future_->mark_exceptional_finish_internal(p, lock);
1831
+ }
1083
1832
 
1833
+ // setting the result with deferred notification
1834
+ void set_value_at_thread_exit(const R& r)
1835
+ {
1836
+ if (future_.get()==0)
1837
+ {
1838
+ boost::throw_exception(promise_moved());
1839
+ }
1840
+ future_->set_value_at_thread_exit(r);
1084
1841
  }
1085
- template <class Clock, class Duration>
1086
- future_status
1087
- wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
1842
+
1843
+ void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
1088
1844
  {
1089
- if(!future_)
1845
+ if (future_.get()==0)
1090
1846
  {
1091
- boost::throw_exception(future_uninitialized());
1847
+ boost::throw_exception(promise_moved());
1092
1848
  }
1093
- return future_->wait_until(abs_time);
1849
+ future_->set_value_at_thread_exit(boost::move(r));
1850
+ }
1851
+ void set_exception_at_thread_exit(exception_ptr e)
1852
+ {
1853
+ if (future_.get()==0)
1854
+ {
1855
+ boost::throw_exception(promise_moved());
1856
+ }
1857
+ future_->set_exception_at_thread_exit(e);
1094
1858
  }
1095
- #endif
1096
- };
1097
1859
 
1098
- BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
1860
+ template<typename F>
1861
+ void set_wait_callback(F f)
1862
+ {
1863
+ lazy_init();
1864
+ future_->set_wait_callback(f,this);
1865
+ }
1866
+
1867
+ };
1099
1868
 
1100
1869
  template <typename R>
1101
- class promise
1870
+ class promise<R&>
1102
1871
  {
1103
- typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
1872
+ typedef boost::shared_ptr<detail::future_object<R&> > future_ptr;
1104
1873
 
1105
1874
  future_ptr future_;
1106
1875
  bool future_obtained;
1107
1876
 
1108
1877
  void lazy_init()
1109
1878
  {
1110
- #if defined BOOST_THREAD_PROMISE_LAZY
1879
+ #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
1880
+ #include <boost/detail/atomic_undef_macros.hpp>
1111
1881
  if(!atomic_load(&future_))
1112
1882
  {
1113
1883
  future_ptr blank;
1114
- atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R>));
1884
+ atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R&>));
1115
1885
  }
1886
+ #include <boost/detail/atomic_redef_macros.hpp>
1116
1887
  #endif
1117
1888
  }
1118
1889
 
@@ -1122,19 +1893,19 @@ namespace boost
1122
1893
  template <class Allocator>
1123
1894
  promise(boost::allocator_arg_t, Allocator a)
1124
1895
  {
1125
- typedef typename Allocator::template rebind<detail::future_object<R> >::other A2;
1896
+ typedef typename Allocator::template rebind<detail::future_object<R&> >::other A2;
1126
1897
  A2 a2(a);
1127
1898
  typedef thread_detail::allocator_destructor<A2> D;
1128
1899
 
1129
- future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<R>(), D(a2, 1) );
1900
+ future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<R&>(), D(a2, 1) );
1130
1901
  future_obtained = false;
1131
1902
  }
1132
1903
  #endif
1133
1904
  promise():
1134
- #if defined BOOST_THREAD_PROMISE_LAZY
1905
+ #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
1135
1906
  future_(),
1136
1907
  #else
1137
- future_(new detail::future_object<R>()),
1908
+ future_(new detail::future_object<R&>()),
1138
1909
  #endif
1139
1910
  future_obtained(false)
1140
1911
  {}
@@ -1143,11 +1914,11 @@ namespace boost
1143
1914
  {
1144
1915
  if(future_)
1145
1916
  {
1146
- boost::lock_guard<boost::mutex> lock(future_->mutex);
1917
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
1147
1918
 
1148
- if(!future_->done)
1919
+ if(!future_->done && !future_->is_constructed)
1149
1920
  {
1150
- future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
1921
+ future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
1151
1922
  }
1152
1923
  }
1153
1924
  }
@@ -1175,7 +1946,7 @@ namespace boost
1175
1946
  }
1176
1947
 
1177
1948
  // Result retrieval
1178
- BOOST_THREAD_FUTURE<R> get_future()
1949
+ BOOST_THREAD_FUTURE<R&> get_future()
1179
1950
  {
1180
1951
  lazy_init();
1181
1952
  if (future_.get()==0)
@@ -1187,47 +1958,49 @@ namespace boost
1187
1958
  boost::throw_exception(future_already_retrieved());
1188
1959
  }
1189
1960
  future_obtained=true;
1190
- return BOOST_THREAD_FUTURE<R>(future_);
1961
+ return BOOST_THREAD_FUTURE<R&>(future_);
1191
1962
  }
1192
1963
 
1193
- void set_value(typename detail::future_traits<R>::source_reference_type r)
1964
+ void set_value(R& r)
1194
1965
  {
1195
1966
  lazy_init();
1196
- boost::lock_guard<boost::mutex> lock(future_->mutex);
1967
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
1197
1968
  if(future_->done)
1198
1969
  {
1199
1970
  boost::throw_exception(promise_already_satisfied());
1200
1971
  }
1201
- future_->mark_finished_with_result_internal(r);
1972
+ future_->mark_finished_with_result_internal(r, lock);
1202
1973
  }
1203
1974
 
1204
- // void set_value(R && r);
1205
- void set_value(typename detail::future_traits<R>::rvalue_source_type r)
1975
+ void set_exception(boost::exception_ptr p)
1206
1976
  {
1207
1977
  lazy_init();
1208
- boost::lock_guard<boost::mutex> lock(future_->mutex);
1978
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
1209
1979
  if(future_->done)
1210
1980
  {
1211
1981
  boost::throw_exception(promise_already_satisfied());
1212
1982
  }
1213
- future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r));
1983
+ future_->mark_exceptional_finish_internal(p, lock);
1214
1984
  }
1215
1985
 
1216
- void set_exception(boost::exception_ptr p)
1986
+ // setting the result with deferred notification
1987
+ void set_value_at_thread_exit(R& r)
1217
1988
  {
1218
- lazy_init();
1219
- boost::lock_guard<boost::mutex> lock(future_->mutex);
1220
- if(future_->done)
1221
- {
1222
- boost::throw_exception(promise_already_satisfied());
1223
- }
1224
- future_->mark_exceptional_finish_internal(p);
1989
+ if (future_.get()==0)
1990
+ {
1991
+ boost::throw_exception(promise_moved());
1992
+ }
1993
+ future_->set_value_at_thread_exit(r);
1225
1994
  }
1226
1995
 
1227
- // setting the result with deferred notification
1228
- //void set_value_at_thread_exit(const R& r); // NOT YET IMPLEMENTED
1229
- //void set_value_at_thread_exit(see below); // NOT YET IMPLEMENTED
1230
- //void set_exception_at_thread_exit(exception_ptr p); // NOT YET IMPLEMENTED
1996
+ void set_exception_at_thread_exit(exception_ptr e)
1997
+ {
1998
+ if (future_.get()==0)
1999
+ {
2000
+ boost::throw_exception(promise_moved());
2001
+ }
2002
+ future_->set_exception_at_thread_exit(e);
2003
+ }
1231
2004
 
1232
2005
  template<typename F>
1233
2006
  void set_wait_callback(F f)
@@ -1237,7 +2010,6 @@ namespace boost
1237
2010
  }
1238
2011
 
1239
2012
  };
1240
-
1241
2013
  template <>
1242
2014
  class promise<void>
1243
2015
  {
@@ -1248,7 +2020,7 @@ namespace boost
1248
2020
 
1249
2021
  void lazy_init()
1250
2022
  {
1251
- #if defined BOOST_THREAD_PROMISE_LAZY
2023
+ #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
1252
2024
  if(!atomic_load(&future_))
1253
2025
  {
1254
2026
  future_ptr blank;
@@ -1272,7 +2044,7 @@ namespace boost
1272
2044
  }
1273
2045
  #endif
1274
2046
  promise():
1275
- #if defined BOOST_THREAD_PROMISE_LAZY
2047
+ #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
1276
2048
  future_(),
1277
2049
  #else
1278
2050
  future_(new detail::future_object<void>),
@@ -1284,11 +2056,11 @@ namespace boost
1284
2056
  {
1285
2057
  if(future_)
1286
2058
  {
1287
- boost::lock_guard<boost::mutex> lock(future_->mutex);
2059
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
1288
2060
 
1289
- if(!future_->done)
2061
+ if(!future_->done && !future_->is_constructed)
1290
2062
  {
1291
- future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
2063
+ future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
1292
2064
  }
1293
2065
  }
1294
2066
  }
@@ -1337,23 +2109,42 @@ namespace boost
1337
2109
  void set_value()
1338
2110
  {
1339
2111
  lazy_init();
1340
- boost::lock_guard<boost::mutex> lock(future_->mutex);
2112
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
1341
2113
  if(future_->done)
1342
2114
  {
1343
2115
  boost::throw_exception(promise_already_satisfied());
1344
2116
  }
1345
- future_->mark_finished_with_result_internal();
2117
+ future_->mark_finished_with_result_internal(lock);
1346
2118
  }
1347
2119
 
1348
2120
  void set_exception(boost::exception_ptr p)
1349
2121
  {
1350
2122
  lazy_init();
1351
- boost::lock_guard<boost::mutex> lock(future_->mutex);
2123
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
1352
2124
  if(future_->done)
1353
2125
  {
1354
2126
  boost::throw_exception(promise_already_satisfied());
1355
2127
  }
1356
- future_->mark_exceptional_finish_internal(p);
2128
+ future_->mark_exceptional_finish_internal(p,lock);
2129
+ }
2130
+
2131
+ // setting the result with deferred notification
2132
+ void set_value_at_thread_exit()
2133
+ {
2134
+ if (future_.get()==0)
2135
+ {
2136
+ boost::throw_exception(promise_moved());
2137
+ }
2138
+ future_->set_value_at_thread_exit();
2139
+ }
2140
+
2141
+ void set_exception_at_thread_exit(exception_ptr e)
2142
+ {
2143
+ if (future_.get()==0)
2144
+ {
2145
+ boost::throw_exception(promise_moved());
2146
+ }
2147
+ future_->set_exception_at_thread_exit(e);
1357
2148
  }
1358
2149
 
1359
2150
  template<typename F>
@@ -1379,8 +2170,20 @@ namespace boost
1379
2170
 
1380
2171
  namespace detail
1381
2172
  {
1382
- template<typename R>
1383
- struct task_base:
2173
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2174
+ template<typename R>
2175
+ struct task_base;
2176
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2177
+ template<typename R, typename ...ArgTypes>
2178
+ struct task_base<R(ArgTypes...)>:
2179
+ #else
2180
+ template<typename R>
2181
+ struct task_base<R()>:
2182
+ #endif
2183
+ #else
2184
+ template<typename R>
2185
+ struct task_base:
2186
+ #endif
1384
2187
  detail::future_object<R>
1385
2188
  {
1386
2189
  bool started;
@@ -1393,7 +2196,13 @@ namespace boost
1393
2196
  {
1394
2197
  started=false;
1395
2198
  }
2199
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2200
+ virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
2201
+ void run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2202
+ #else
2203
+ virtual void do_run()=0;
1396
2204
  void run()
2205
+ #endif
1397
2206
  {
1398
2207
  {
1399
2208
  boost::lock_guard<boost::mutex> lk(this->mutex);
@@ -1403,29 +2212,65 @@ namespace boost
1403
2212
  }
1404
2213
  started=true;
1405
2214
  }
2215
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2216
+ do_run(boost::forward<ArgTypes>(args)...);
2217
+ #else
1406
2218
  do_run();
2219
+ #endif
2220
+ }
2221
+
2222
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2223
+ virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
2224
+ void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2225
+ #else
2226
+ virtual void do_apply()=0;
2227
+ void apply()
2228
+ #endif
2229
+ {
2230
+ {
2231
+ boost::lock_guard<boost::mutex> lk(this->mutex);
2232
+ if(started)
2233
+ {
2234
+ boost::throw_exception(task_already_started());
2235
+ }
2236
+ started=true;
2237
+ }
2238
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2239
+ do_apply(boost::forward<ArgTypes>(args)...);
2240
+ #else
2241
+ do_apply();
2242
+ #endif
1407
2243
  }
1408
2244
 
1409
2245
  void owner_destroyed()
1410
2246
  {
1411
- boost::lock_guard<boost::mutex> lk(this->mutex);
2247
+ boost::unique_lock<boost::mutex> lk(this->mutex);
1412
2248
  if(!started)
1413
2249
  {
1414
2250
  started=true;
1415
- this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()));
2251
+ this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk);
1416
2252
  }
1417
2253
  }
1418
2254
 
1419
-
1420
- virtual void do_run()=0;
1421
2255
  };
1422
2256
 
1423
-
1424
-
1425
-
1426
- template<typename R,typename F>
2257
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2258
+ template<typename F, typename R>
2259
+ struct task_object;
2260
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2261
+ template<typename F, typename R, typename ...ArgTypes>
2262
+ struct task_object<F, R(ArgTypes...)>:
2263
+ task_base<R(ArgTypes...)>
2264
+ #else
2265
+ template<typename F, typename R>
2266
+ struct task_object<F, R()>:
2267
+ task_base<R()>
2268
+ #endif
2269
+ #else
2270
+ template<typename F, typename R>
1427
2271
  struct task_object:
1428
2272
  task_base<R>
2273
+ #endif
1429
2274
  {
1430
2275
  private:
1431
2276
  task_object(task_object&);
@@ -1434,25 +2279,63 @@ namespace boost
1434
2279
  task_object(F const& f_):
1435
2280
  f(f_)
1436
2281
  {}
1437
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1438
2282
  task_object(BOOST_THREAD_RV_REF(F) f_):
1439
- f(boost::forward<F>(f_))
2283
+ f(boost::move(f_))
1440
2284
  {}
2285
+
2286
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2287
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2288
+ {
2289
+ try
2290
+ {
2291
+ this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
2292
+ }
1441
2293
  #else
1442
- task_object(BOOST_THREAD_RV_REF(F) f_):
1443
- f(boost::move(f_))
1444
- {}
2294
+ void do_apply()
2295
+ {
2296
+ try
2297
+ {
2298
+ this->set_value_at_thread_exit(f());
2299
+ }
1445
2300
  #endif
1446
- void do_run()
2301
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2302
+ catch(thread_interrupted& )
2303
+ {
2304
+ this->set_interrupted_at_thread_exit();
2305
+ }
2306
+ #endif
2307
+ catch(...)
2308
+ {
2309
+ this->set_exception_at_thread_exit(current_exception());
2310
+ }
2311
+ }
2312
+
2313
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2314
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
1447
2315
  {
1448
2316
  try
1449
2317
  {
1450
- this->mark_finished_with_result(f());
2318
+ this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
1451
2319
  }
2320
+ #else
2321
+ void do_run()
2322
+ {
2323
+ try
2324
+ {
2325
+ #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2326
+ R res((f()));
2327
+ this->mark_finished_with_result(boost::move(res));
2328
+ #else
2329
+ this->mark_finished_with_result(f());
2330
+ #endif
2331
+ }
2332
+ #endif
2333
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
1452
2334
  catch(thread_interrupted& )
1453
2335
  {
1454
2336
  this->mark_interrupted_finish();
1455
2337
  }
2338
+ #endif
1456
2339
  catch(...)
1457
2340
  {
1458
2341
  this->mark_exceptional_finish();
@@ -1460,37 +2343,269 @@ namespace boost
1460
2343
  }
1461
2344
  };
1462
2345
 
1463
- template<typename R>
1464
- struct task_object<R,R (*)()>:
1465
- task_base<R>
1466
- {
1467
- private:
1468
- task_object(task_object&);
1469
- public:
2346
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2347
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2348
+ template<typename F, typename R, typename ...ArgTypes>
2349
+ struct task_object<F, R&(ArgTypes...)>:
2350
+ task_base<R&(ArgTypes...)>
2351
+ #else
2352
+ template<typename F, typename R>
2353
+ struct task_object<F, R&()>:
2354
+ task_base<R&()>
2355
+ #endif
2356
+ #else
2357
+ template<typename F, typename R>
2358
+ struct task_object<F,R&>:
2359
+ task_base<R&>
2360
+ #endif
2361
+ {
2362
+ private:
2363
+ task_object(task_object&);
2364
+ public:
2365
+ F f;
2366
+ task_object(F const& f_):
2367
+ f(f_)
2368
+ {}
2369
+ task_object(BOOST_THREAD_RV_REF(F) f_):
2370
+ f(boost::move(f_))
2371
+ {}
2372
+
2373
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2374
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2375
+ {
2376
+ try
2377
+ {
2378
+ this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
2379
+ }
2380
+ #else
2381
+ void do_apply()
2382
+ {
2383
+ try
2384
+ {
2385
+ this->set_value_at_thread_exit(f());
2386
+ }
2387
+ #endif
2388
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2389
+ catch(thread_interrupted& )
2390
+ {
2391
+ this->set_interrupted_at_thread_exit();
2392
+ }
2393
+ #endif
2394
+ catch(...)
2395
+ {
2396
+ this->set_exception_at_thread_exit(current_exception());
2397
+ }
2398
+ }
2399
+
2400
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2401
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2402
+ {
2403
+ try
2404
+ {
2405
+ this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
2406
+ }
2407
+ #else
2408
+ void do_run()
2409
+ {
2410
+ try
2411
+ {
2412
+ R& res((f()));
2413
+ this->mark_finished_with_result(res);
2414
+ }
2415
+ #endif
2416
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2417
+ catch(thread_interrupted& )
2418
+ {
2419
+ this->mark_interrupted_finish();
2420
+ }
2421
+ #endif
2422
+ catch(...)
2423
+ {
2424
+ this->mark_exceptional_finish();
2425
+ }
2426
+ }
2427
+ };
2428
+
2429
+ #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
2430
+
2431
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2432
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2433
+ template<typename R, typename ...ArgTypes>
2434
+ struct task_object<R (*)(ArgTypes...), R(ArgTypes...)>:
2435
+ task_base<R(ArgTypes...)>
2436
+ #else
2437
+ template<typename R>
2438
+ struct task_object<R (*)(), R()>:
2439
+ task_base<R()>
2440
+ #endif
2441
+ #else
2442
+ template<typename R>
2443
+ struct task_object<R (*)(), R> :
2444
+ task_base<R>
2445
+ #endif
2446
+ {
2447
+ private:
2448
+ task_object(task_object&);
2449
+ public:
1470
2450
  R (*f)();
1471
2451
  task_object(R (*f_)()):
1472
2452
  f(f_)
1473
2453
  {}
2454
+
2455
+
2456
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2457
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2458
+ {
2459
+ try
2460
+ {
2461
+ this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
2462
+ }
2463
+ #else
2464
+ void do_apply()
2465
+ {
2466
+ try
2467
+ {
2468
+ R r((f()));
2469
+ this->set_value_at_thread_exit(boost::move(r));
2470
+ }
2471
+ #endif
2472
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2473
+ catch(thread_interrupted& )
2474
+ {
2475
+ this->set_interrupted_at_thread_exit();
2476
+ }
2477
+ #endif
2478
+ catch(...)
2479
+ {
2480
+ this->set_exception_at_thread_exit(current_exception());
2481
+ }
2482
+ }
2483
+
2484
+
2485
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2486
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2487
+ {
2488
+ try
2489
+ {
2490
+ this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
2491
+ }
2492
+ #else
1474
2493
  void do_run()
1475
2494
  {
1476
2495
  try
1477
2496
  {
1478
- this->mark_finished_with_result(f());
2497
+ R res((f()));
2498
+ this->mark_finished_with_result(boost::move(res));
1479
2499
  }
2500
+ #endif
2501
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
1480
2502
  catch(thread_interrupted& )
1481
2503
  {
1482
2504
  this->mark_interrupted_finish();
1483
2505
  }
2506
+ #endif
1484
2507
  catch(...)
1485
2508
  {
1486
2509
  this->mark_exceptional_finish();
1487
2510
  }
1488
2511
  }
1489
2512
  };
2513
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2514
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2515
+ template<typename R, typename ...ArgTypes>
2516
+ struct task_object<R& (*)(ArgTypes...), R&(ArgTypes...)>:
2517
+ task_base<R&(ArgTypes...)>
2518
+ #else
2519
+ template<typename R>
2520
+ struct task_object<R& (*)(), R&()>:
2521
+ task_base<R&()>
2522
+ #endif
2523
+ #else
2524
+ template<typename R>
2525
+ struct task_object<R& (*)(), R&> :
2526
+ task_base<R&>
2527
+ #endif
2528
+ {
2529
+ private:
2530
+ task_object(task_object&);
2531
+ public:
2532
+ R& (*f)();
2533
+ task_object(R& (*f_)()):
2534
+ f(f_)
2535
+ {}
2536
+
2537
+
2538
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2539
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2540
+ {
2541
+ try
2542
+ {
2543
+ this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
2544
+ }
2545
+ #else
2546
+ void do_apply()
2547
+ {
2548
+ try
2549
+ {
2550
+ this->set_value_at_thread_exit(f());
2551
+ }
2552
+ #endif
2553
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2554
+ catch(thread_interrupted& )
2555
+ {
2556
+ this->set_interrupted_at_thread_exit();
2557
+ }
2558
+ #endif
2559
+ catch(...)
2560
+ {
2561
+ this->set_exception_at_thread_exit(current_exception());
2562
+ }
2563
+ }
2564
+
1490
2565
 
2566
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2567
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2568
+ {
2569
+ try
2570
+ {
2571
+ this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
2572
+ }
2573
+ #else
2574
+ void do_run()
2575
+ {
2576
+ try
2577
+ {
2578
+ this->mark_finished_with_result(f());
2579
+ }
2580
+ #endif
2581
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2582
+ catch(thread_interrupted& )
2583
+ {
2584
+ this->mark_interrupted_finish();
2585
+ }
2586
+ #endif
2587
+ catch(...)
2588
+ {
2589
+ this->mark_exceptional_finish();
2590
+ }
2591
+ }
2592
+ };
2593
+ #endif
2594
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2595
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2596
+ template<typename F, typename ...ArgTypes>
2597
+ struct task_object<F, void(ArgTypes...)>:
2598
+ task_base<void(ArgTypes...)>
2599
+ #else
2600
+ template<typename F>
2601
+ struct task_object<F, void()>:
2602
+ task_base<void()>
2603
+ #endif
2604
+ #else
1491
2605
  template<typename F>
1492
- struct task_object<void,F>:
1493
- task_base<void>
2606
+ struct task_object<F,void>:
2607
+ task_base<void>
2608
+ #endif
1494
2609
  {
1495
2610
  private:
1496
2611
  task_object(task_object&);
@@ -1499,27 +2614,58 @@ namespace boost
1499
2614
  task_object(F const& f_):
1500
2615
  f(f_)
1501
2616
  {}
1502
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1503
- task_object(BOOST_THREAD_RV_REF(F) f_):
1504
- f(boost::forward<F>(f_))
1505
- {}
1506
- #else
1507
2617
  task_object(BOOST_THREAD_RV_REF(F) f_):
1508
2618
  f(boost::move(f_))
1509
2619
  {}
2620
+
2621
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2622
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2623
+ {
2624
+ try
2625
+ {
2626
+ f(boost::forward<ArgTypes>(args)...);
2627
+ #else
2628
+ void do_apply()
2629
+ {
2630
+ try
2631
+ {
2632
+ f();
2633
+ #endif
2634
+ this->set_value_at_thread_exit();
2635
+ }
2636
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2637
+ catch(thread_interrupted& )
2638
+ {
2639
+ this->set_interrupted_at_thread_exit();
2640
+ }
1510
2641
  #endif
2642
+ catch(...)
2643
+ {
2644
+ this->set_exception_at_thread_exit(current_exception());
2645
+ }
2646
+ }
1511
2647
 
2648
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2649
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2650
+ {
2651
+ try
2652
+ {
2653
+ f(boost::forward<ArgTypes>(args)...);
2654
+ #else
1512
2655
  void do_run()
1513
2656
  {
1514
2657
  try
1515
2658
  {
1516
2659
  f();
2660
+ #endif
1517
2661
  this->mark_finished_with_result();
1518
2662
  }
2663
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
1519
2664
  catch(thread_interrupted& )
1520
2665
  {
1521
2666
  this->mark_interrupted_finish();
1522
2667
  }
2668
+ #endif
1523
2669
  catch(...)
1524
2670
  {
1525
2671
  this->mark_exceptional_finish();
@@ -1527,9 +2673,21 @@ namespace boost
1527
2673
  }
1528
2674
  };
1529
2675
 
2676
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2677
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2678
+ template<typename ...ArgTypes>
2679
+ struct task_object<void (*)(ArgTypes...), void(ArgTypes...)>:
2680
+ task_base<void(ArgTypes...)>
2681
+ #else
2682
+ template<>
2683
+ struct task_object<void (*)(), void()>:
2684
+ task_base<void()>
2685
+ #endif
2686
+ #else
1530
2687
  template<>
1531
- struct task_object<void,void (*)()>:
1532
- task_base<void>
2688
+ struct task_object<void (*)(),void>:
2689
+ task_base<void>
2690
+ #endif
1533
2691
  {
1534
2692
  private:
1535
2693
  task_object(task_object&);
@@ -1538,17 +2696,55 @@ namespace boost
1538
2696
  task_object(void (*f_)()):
1539
2697
  f(f_)
1540
2698
  {}
2699
+
2700
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2701
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2702
+ {
2703
+ try
2704
+ {
2705
+ f(boost::forward<ArgTypes>(args)...);
2706
+ #else
2707
+ void do_apply()
2708
+ {
2709
+ try
2710
+ {
2711
+ f();
2712
+ #endif
2713
+ this->set_value_at_thread_exit();
2714
+ }
2715
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
2716
+ catch(thread_interrupted& )
2717
+ {
2718
+ this->set_interrupted_at_thread_exit();
2719
+ }
2720
+ #endif
2721
+ catch(...)
2722
+ {
2723
+ this->set_exception_at_thread_exit(current_exception());
2724
+ }
2725
+ }
2726
+
2727
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2728
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
2729
+ {
2730
+ try
2731
+ {
2732
+ f(boost::forward<ArgTypes>(args)...);
2733
+ #else
1541
2734
  void do_run()
1542
2735
  {
1543
2736
  try
1544
2737
  {
1545
2738
  f();
2739
+ #endif
1546
2740
  this->mark_finished_with_result();
1547
2741
  }
2742
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
1548
2743
  catch(thread_interrupted& )
1549
2744
  {
1550
2745
  this->mark_interrupted_finish();
1551
2746
  }
2747
+ #endif
1552
2748
  catch(...)
1553
2749
  {
1554
2750
  this->mark_exceptional_finish();
@@ -1558,12 +2754,30 @@ namespace boost
1558
2754
 
1559
2755
  }
1560
2756
 
2757
+
2758
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2759
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2760
+ template<typename R, typename ...ArgTypes>
2761
+ class packaged_task<R(ArgTypes...)>
2762
+ {
2763
+ typedef boost::shared_ptr<detail::task_base<R(ArgTypes...)> > task_ptr;
2764
+ boost::shared_ptr<detail::task_base<R(ArgTypes...)> > task;
2765
+ #else
2766
+ template<typename R>
2767
+ class packaged_task<R()>
2768
+ {
2769
+ typedef boost::shared_ptr<detail::task_base<R()> > task_ptr;
2770
+ boost::shared_ptr<detail::task_base<R()> > task;
2771
+ #endif
2772
+ #else
1561
2773
  template<typename R>
1562
2774
  class packaged_task
1563
2775
  {
1564
- typedef boost::shared_ptr<detail::task_base<R> > task_ptr;
1565
- boost::shared_ptr<detail::task_base<R> > task;
2776
+ typedef boost::shared_ptr<detail::task_base<R> > task_ptr;
2777
+ boost::shared_ptr<detail::task_base<R> > task;
2778
+ #endif
1566
2779
  bool future_obtained;
2780
+ struct dummy;
1567
2781
 
1568
2782
  public:
1569
2783
  typedef R result_type;
@@ -1574,73 +2788,184 @@ namespace boost
1574
2788
  {}
1575
2789
 
1576
2790
  // construction and destruction
2791
+ #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
1577
2792
 
1578
- explicit packaged_task(R(*f)()):
1579
- task(new detail::task_object<R,R(*)()>(f)),future_obtained(false)
1580
- {}
1581
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1582
- template <class F>
1583
- explicit packaged_task(BOOST_THREAD_RV_REF(F) f):
1584
- task(new detail::task_object<R,
1585
- typename remove_cv<typename remove_reference<F>::type>::type
1586
- >(boost::forward<F>(f))),future_obtained(false)
1587
- {}
1588
- #else
1589
- template <class F>
1590
- explicit packaged_task(F const& f):
1591
- task(new detail::task_object<R,F>(f)),future_obtained(false)
1592
- {}
1593
- template <class F>
1594
- explicit packaged_task(BOOST_THREAD_RV_REF(F) f):
1595
- task(new detail::task_object<R,F>(boost::move(f))),future_obtained(false)
1596
- {}
1597
- #endif
1598
-
1599
- #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
1600
- template <class Allocator>
1601
- packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
2793
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2794
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2795
+ explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args)
1602
2796
  {
1603
- typedef R(*FR)();
1604
- typedef typename Allocator::template rebind<detail::task_object<R,FR> >::other A2;
1605
- A2 a2(a);
1606
- typedef thread_detail::allocator_destructor<A2> D;
1607
-
1608
- task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(f), D(a2, 1) );
1609
- future_obtained = false;
2797
+ typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...);
2798
+ typedef detail::task_object<FR,R(ArgTypes...)> task_object_type;
2799
+ task= task_ptr(new task_object_type(f, boost::forward<ArgTypes>(args)...));
2800
+ future_obtained=false;
1610
2801
  }
1611
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1612
- template <class F, class Allocator>
1613
- packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
2802
+ #else
2803
+ explicit packaged_task(R(*f)())
1614
2804
  {
1615
- typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
1616
- typedef typename Allocator::template rebind<detail::task_object<R,FR> >::other A2;
1617
- A2 a2(a);
1618
- typedef thread_detail::allocator_destructor<A2> D;
1619
-
1620
- task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(boost::forward<F>(f)), D(a2, 1) );
1621
- future_obtained = false;
2805
+ typedef R(*FR)();
2806
+ typedef detail::task_object<FR,R()> task_object_type;
2807
+ task= task_ptr(new task_object_type(f));
2808
+ future_obtained=false;
1622
2809
  }
2810
+ #endif
1623
2811
  #else
1624
- template <class F, class Allocator>
1625
- packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
2812
+ explicit packaged_task(R(*f)())
1626
2813
  {
1627
- typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2;
2814
+ typedef R(*FR)();
2815
+ typedef detail::task_object<FR,R> task_object_type;
2816
+ task= task_ptr(new task_object_type(f));
2817
+ future_obtained=false;
2818
+ }
2819
+ #endif
2820
+ #endif
2821
+ #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2822
+ template <class F>
2823
+ explicit packaged_task(BOOST_THREAD_FWD_REF(F) f
2824
+ , typename disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
2825
+ )
2826
+ {
2827
+ typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
2828
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2829
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2830
+ typedef detail::task_object<FR,R(ArgTypes...)> task_object_type;
2831
+ #else
2832
+ typedef detail::task_object<FR,R()> task_object_type;
2833
+ #endif
2834
+ #else
2835
+ typedef detail::task_object<FR,R> task_object_type;
2836
+ #endif
2837
+ task = task_ptr(new task_object_type(boost::forward<F>(f)));
2838
+ future_obtained = false;
2839
+
2840
+ }
2841
+
2842
+ #else
2843
+ template <class F>
2844
+ explicit packaged_task(F const& f
2845
+ , typename disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
2846
+ )
2847
+ {
2848
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2849
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2850
+ typedef detail::task_object<F,R(ArgTypes...)> task_object_type;
2851
+ #else
2852
+ typedef detail::task_object<F,R()> task_object_type;
2853
+ #endif
2854
+ #else
2855
+ typedef detail::task_object<F,R> task_object_type;
2856
+ #endif
2857
+ task = task_ptr(new task_object_type(f));
2858
+ future_obtained=false;
2859
+ }
2860
+ template <class F>
2861
+ explicit packaged_task(BOOST_THREAD_RV_REF(F) f)
2862
+ {
2863
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2864
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2865
+ typedef detail::task_object<F,R(ArgTypes...)> task_object_type;
2866
+ task = task_ptr(new task_object_type(boost::forward<F>(f)));
2867
+ #else
2868
+ typedef detail::task_object<F,R()> task_object_type;
2869
+ task = task_ptr(new task_object_type(boost::move<F>(f))); // TODO forward
2870
+ #endif
2871
+ #else
2872
+ typedef detail::task_object<F,R> task_object_type;
2873
+ task = task_ptr(new task_object_type(boost::forward<F>(f)));
2874
+ #endif
2875
+ future_obtained=false;
2876
+
2877
+ }
2878
+ #endif
2879
+
2880
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
2881
+ #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
2882
+ template <class Allocator>
2883
+ packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
2884
+ {
2885
+ typedef R(*FR)();
2886
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2887
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2888
+ typedef detail::task_object<FR,R(ArgTypes...)> task_object_type;
2889
+ #else
2890
+ typedef detail::task_object<FR,R()> task_object_type;
2891
+ #endif
2892
+ #else
2893
+ typedef detail::task_object<FR,R> task_object_type;
2894
+ #endif
2895
+ typedef typename Allocator::template rebind<task_object_type>::other A2;
2896
+ A2 a2(a);
2897
+ typedef thread_detail::allocator_destructor<A2> D;
2898
+
2899
+ task = task_ptr(::new(a2.allocate(1)) task_object_type(f), D(a2, 1) );
2900
+ future_obtained = false;
2901
+ }
2902
+ #endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
2903
+
2904
+ #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2905
+ template <class F, class Allocator>
2906
+ packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f)
2907
+ {
2908
+ typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
2909
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2910
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2911
+ typedef detail::task_object<FR,R(ArgTypes...)> task_object_type;
2912
+ #else
2913
+ typedef detail::task_object<FR,R()> task_object_type;
2914
+ #endif
2915
+ #else
2916
+ typedef detail::task_object<FR,R> task_object_type;
2917
+ #endif
2918
+ typedef typename Allocator::template rebind<task_object_type>::other A2;
1628
2919
  A2 a2(a);
1629
2920
  typedef thread_detail::allocator_destructor<A2> D;
1630
2921
 
1631
- task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(f), D(a2, 1) );
2922
+ task = task_ptr(::new(a2.allocate(1)) task_object_type(boost::forward<F>(f)), D(a2, 1) );
2923
+ future_obtained = false;
2924
+ }
2925
+ #else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2926
+ template <class F, class Allocator>
2927
+ packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
2928
+ {
2929
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2930
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2931
+ typedef detail::task_object<F,R(ArgTypes...)> task_object_type;
2932
+ #else
2933
+ typedef detail::task_object<F,R()> task_object_type;
2934
+ #endif
2935
+ #else
2936
+ typedef detail::task_object<F,R> task_object_type;
2937
+ #endif
2938
+ typedef typename Allocator::template rebind<task_object_type>::other A2;
2939
+ A2 a2(a);
2940
+ typedef thread_detail::allocator_destructor<A2> D;
2941
+
2942
+ task = task_ptr(::new(a2.allocate(1)) task_object_type(f), D(a2, 1) );
1632
2943
  future_obtained = false;
1633
2944
  }
1634
2945
  template <class F, class Allocator>
1635
2946
  packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
1636
2947
  {
1637
- typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2;
2948
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
2949
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2950
+ typedef detail::task_object<F,R(ArgTypes...)> task_object_type;
2951
+ #else
2952
+ typedef detail::task_object<F,R()> task_object_type;
2953
+ #endif
2954
+ #else
2955
+ typedef detail::task_object<F,R> task_object_type;
2956
+ #endif
2957
+ typedef typename Allocator::template rebind<task_object_type>::other A2;
1638
2958
  A2 a2(a);
1639
2959
  typedef thread_detail::allocator_destructor<A2> D;
1640
2960
 
1641
- task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(boost::move(f)), D(a2, 1) );
2961
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
2962
+ task = task_ptr(::new(a2.allocate(1)) task_object_type(boost::forward<F>(f)), D(a2, 1) );
2963
+ #else
2964
+ task = task_ptr(::new(a2.allocate(1)) task_object_type(boost::move(f)), D(a2, 1) ); // TODO forward
2965
+ #endif
1642
2966
  future_obtained = false;
1643
2967
  }
2968
+
1644
2969
  #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
1645
2970
  #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
1646
2971
 
@@ -1661,7 +2986,13 @@ namespace boost
1661
2986
  }
1662
2987
  packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
1663
2988
  {
2989
+
2990
+ // todo use forward
2991
+ #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
2992
+ packaged_task temp(boost::move(other));
2993
+ #else
1664
2994
  packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other));
2995
+ #endif
1665
2996
  swap(temp);
1666
2997
  return *this;
1667
2998
  }
@@ -1687,6 +3018,7 @@ namespace boost
1687
3018
  // result retrieval
1688
3019
  BOOST_THREAD_FUTURE<R> get_future()
1689
3020
  {
3021
+
1690
3022
  if(!task)
1691
3023
  {
1692
3024
  boost::throw_exception(task_moved());
@@ -1700,12 +3032,34 @@ namespace boost
1700
3032
  {
1701
3033
  boost::throw_exception(future_already_retrieved());
1702
3034
  }
1703
- return BOOST_THREAD_FUTURE<R>();
3035
+ //return BOOST_THREAD_FUTURE<R>();
1704
3036
 
1705
3037
  }
1706
3038
 
1707
3039
 
1708
3040
  // execution
3041
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3042
+ void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args)
3043
+ {
3044
+ if(!task)
3045
+ {
3046
+ boost::throw_exception(task_moved());
3047
+ }
3048
+ task->run(boost::forward<ArgTypes>(args)...);
3049
+ }
3050
+ void make_ready_at_thread_exit(ArgTypes... args)
3051
+ {
3052
+ if(!task)
3053
+ {
3054
+ boost::throw_exception(task_moved());
3055
+ }
3056
+ if (task->has_value())
3057
+ {
3058
+ boost::throw_exception(promise_already_satisfied());
3059
+ }
3060
+ task->apply(boost::forward<ArgTypes>(args)...);
3061
+ }
3062
+ #else
1709
3063
  void operator()()
1710
3064
  {
1711
3065
  if(!task)
@@ -1714,7 +3068,17 @@ namespace boost
1714
3068
  }
1715
3069
  task->run();
1716
3070
  }
1717
-
3071
+ void make_ready_at_thread_exit()
3072
+ {
3073
+ if(!task)
3074
+ {
3075
+ boost::throw_exception(task_moved());
3076
+ }
3077
+ if (task->has_value())
3078
+ boost::throw_exception(promise_already_satisfied());
3079
+ task->apply();
3080
+ }
3081
+ #endif
1718
3082
  template<typename F>
1719
3083
  void set_wait_callback(F f)
1720
3084
  {
@@ -1734,131 +3098,829 @@ namespace boost
1734
3098
 
1735
3099
  BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
1736
3100
 
3101
+ namespace detail
3102
+ {
3103
+ ////////////////////////////////
3104
+ // make_future_deferred_object
3105
+ ////////////////////////////////
3106
+ template <class Rp, class Fp>
3107
+ BOOST_THREAD_FUTURE<Rp>
3108
+ make_future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f)
3109
+ {
3110
+ shared_ptr<future_deferred_object<Rp, Fp> >
3111
+ h(new future_deferred_object<Rp, Fp>(boost::forward<Fp>(f)));
3112
+ return BOOST_THREAD_FUTURE<Rp>(h);
3113
+ }
3114
+
3115
+ ////////////////////////////////
3116
+ // make_future_async_object
3117
+ ////////////////////////////////
3118
+ template <class Rp, class Fp>
3119
+ BOOST_THREAD_FUTURE<Rp>
3120
+ make_future_async_object(BOOST_THREAD_FWD_REF(Fp) f)
3121
+ {
3122
+ shared_ptr<future_async_object<Rp, Fp> >
3123
+ h(new future_async_object<Rp, Fp>(boost::forward<Fp>(f)));
3124
+ return BOOST_THREAD_FUTURE<Rp>(h);
3125
+ }
3126
+
3127
+ }
3128
+
3129
+ ////////////////////////////////
3130
+ // template <class F, class... ArgTypes>
3131
+ // future<R> async(launch policy, F&&, ArgTypes&&...);
3132
+ ////////////////////////////////
3133
+
3134
+ #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
1737
3135
 
3136
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3137
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3138
+ template <class R, class... ArgTypes>
3139
+ BOOST_THREAD_FUTURE<R>
3140
+ async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
3141
+ {
3142
+ typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
3143
+ typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3144
+ typedef typename BF::result_type Rp;
3145
+ #else
1738
3146
  template <class R>
1739
3147
  BOOST_THREAD_FUTURE<R>
1740
3148
  async(launch policy, R(*f)())
1741
3149
  {
1742
- if (int(policy) & int(launch::async))
1743
- {
1744
- packaged_task<R> pt( f );
3150
+ typedef packaged_task<R()> packaged_task_type;
3151
+ #endif
3152
+ #else
3153
+ template <class R>
3154
+ BOOST_THREAD_FUTURE<R>
3155
+ async(launch policy, R(*f)())
3156
+ {
3157
+ typedef packaged_task<R> packaged_task_type;
3158
+ #endif
3159
+ if (int(policy) & int(launch::async))
3160
+ {
3161
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3162
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_object<Rp>(
3163
+ BF(
3164
+ thread_detail::decay_copy(boost::forward<F>(f))
3165
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3166
+ )
3167
+ ));
3168
+ #else
3169
+ packaged_task_type pt( f );
1745
3170
 
1746
- BOOST_THREAD_FUTURE<R> ret = pt.get_future();
3171
+ BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future());
3172
+ ret.set_async();
1747
3173
  boost::thread( boost::move(pt) ).detach();
1748
3174
  return ::boost::move(ret);
3175
+ #endif
1749
3176
  }
1750
3177
  else if (int(policy) & int(launch::deferred))
1751
3178
  {
1752
- packaged_task<R> pt( f );
3179
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3180
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_object<Rp>(
3181
+ BF(
3182
+ thread_detail::decay_copy(boost::forward<F>(f))
3183
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3184
+ )
3185
+ ));
3186
+ #else
3187
+ std::terminate();
3188
+ BOOST_THREAD_FUTURE<R> ret;
3189
+ return ::boost::move(ret);
1753
3190
 
1754
- BOOST_THREAD_FUTURE<R> ret = pt.get_future();
1755
- return ::boost::move(ret);
3191
+ #endif
1756
3192
  } else {
3193
+ std::terminate();
1757
3194
  BOOST_THREAD_FUTURE<R> ret;
1758
3195
  return ::boost::move(ret);
1759
3196
  }
1760
3197
  }
1761
3198
 
1762
- template <class R>
1763
- BOOST_THREAD_FUTURE<R>
1764
- async(R(*f)())
3199
+ #endif
3200
+
3201
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
3202
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3203
+
3204
+ template <class F, class ...ArgTypes>
3205
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
3206
+ typename decay<ArgTypes>::type...
3207
+ )>::type>
3208
+ async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
1765
3209
  {
1766
- return async(launch::any, f);
1767
- }
1768
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1769
- template <class F>
1770
- BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
1771
- async(launch policy, BOOST_THREAD_FWD_REF(F) f)
1772
- {
1773
- typedef typename boost::result_of<typename decay<F>::type()>::type R;
3210
+
3211
+ typedef typename boost::result_of<typename decay<F>::type(
3212
+ typename decay<ArgTypes>::type...
3213
+ )>::type R;
3214
+
3215
+ typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
3216
+ typedef typename BF::result_type Rp;
3217
+
3218
+ #else
3219
+ template <class F>
3220
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
3221
+ async(launch policy, BOOST_THREAD_FWD_REF(F) f)
3222
+ {
3223
+ typedef typename boost::result_of<typename decay<F>::type()>::type R;
3224
+ typedef packaged_task<R()> packaged_task_type;
3225
+
3226
+ #endif
3227
+ #else
3228
+ template <class F>
3229
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
3230
+ async(launch policy, BOOST_THREAD_FWD_REF(F) f)
3231
+ {
3232
+ typedef typename boost::result_of<typename decay<F>::type()>::type R;
3233
+ typedef packaged_task<R> packaged_task_type;
3234
+
3235
+ #endif
3236
+
1774
3237
  if (int(policy) & int(launch::async))
1775
3238
  {
1776
- packaged_task<R> pt( boost::forward<F>(f) );
3239
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3240
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_object<Rp>(
3241
+ BF(
3242
+ thread_detail::decay_copy(boost::forward<F>(f))
3243
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3244
+ )
3245
+ ));
3246
+ #else
3247
+ packaged_task_type pt( boost::forward<F>(f) );
1777
3248
 
1778
3249
  BOOST_THREAD_FUTURE<R> ret = pt.get_future();
3250
+ ret.set_async();
3251
+ //#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3252
+ // boost::thread( boost::move(pt), boost::forward<ArgTypes>(args)... ).detach(); // todo forward
3253
+ //#else
1779
3254
  boost::thread( boost::move(pt) ).detach();
3255
+ //#endif
1780
3256
  return ::boost::move(ret);
3257
+ #endif
1781
3258
  }
1782
3259
  else if (int(policy) & int(launch::deferred))
1783
3260
  {
1784
- packaged_task<R> pt( boost::forward<F>(f) );
3261
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3262
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_object<Rp>(
3263
+ BF(
3264
+ thread_detail::decay_copy(boost::forward<F>(f))
3265
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
3266
+ )
3267
+ ));
3268
+ #else
3269
+ std::terminate();
3270
+ BOOST_THREAD_FUTURE<R> ret;
3271
+ return ::boost::move(ret);
3272
+ // return boost::detail::make_future_deferred_object<Rp>(
3273
+ // BF(
3274
+ // thread_detail::decay_copy(boost::forward<F>(f))
3275
+ // )
3276
+ // );
3277
+ #endif
1785
3278
 
1786
- BOOST_THREAD_FUTURE<R> ret = pt.get_future();
1787
- return ::boost::move(ret);
1788
3279
  } else {
3280
+ std::terminate();
1789
3281
  BOOST_THREAD_FUTURE<R> ret;
1790
3282
  return ::boost::move(ret);
1791
3283
  }
1792
3284
  }
3285
+
3286
+ ////////////////////////////////
3287
+ // template <class F, class... ArgTypes>
3288
+ // future<R> async(F&&, ArgTypes&&...);
3289
+ ////////////////////////////////
3290
+
3291
+ #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
3292
+
3293
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3294
+ template <class R, class... ArgTypes>
3295
+ BOOST_THREAD_FUTURE<R>
3296
+ async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
3297
+ {
3298
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
3299
+ }
3300
+ #else
3301
+ template <class R>
3302
+ BOOST_THREAD_FUTURE<R>
3303
+ async(R(*f)())
3304
+ {
3305
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
3306
+ }
3307
+ #endif
3308
+ #endif
3309
+
3310
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
3311
+ template <class F, class ...ArgTypes>
3312
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
3313
+ typename decay<ArgTypes>::type...
3314
+ )>::type>
3315
+ async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
3316
+ {
3317
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
3318
+ }
3319
+ #else
1793
3320
  template <class F>
1794
3321
  BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
1795
3322
  async(BOOST_THREAD_RV_REF(F) f)
1796
3323
  {
1797
- return async(launch::any, boost::forward<F>(f));
3324
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
1798
3325
  }
1799
- #else
3326
+ #endif
1800
3327
 
1801
- // template <class F>
1802
- // BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
1803
- // async(launch policy, F const& f)
1804
- // {
1805
- // typedef typename boost::result_of<typename decay<F>::type()>::type R;
1806
- // if (int(policy) & int(launch::async))
1807
- // {
1808
- // packaged_task<R> pt( f );
3328
+
3329
+ ////////////////////////////////
3330
+ // make_future deprecated
3331
+ ////////////////////////////////
3332
+ template <typename T>
3333
+ BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value)
3334
+ {
3335
+ typedef typename decay<T>::type future_type;
3336
+ promise<future_type> p;
3337
+ p.set_value(boost::forward<T>(value));
3338
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3339
+ }
3340
+
3341
+ #if defined BOOST_THREAD_USES_MOVE
3342
+ inline BOOST_THREAD_FUTURE<void> make_future()
3343
+ {
3344
+ promise<void> p;
3345
+ p.set_value();
3346
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3347
+ }
3348
+ #endif
3349
+
3350
+ ////////////////////////////////
3351
+ // make_ready_future
3352
+ ////////////////////////////////
3353
+ template <typename T>
3354
+ BOOST_THREAD_FUTURE<typename decay<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value)
3355
+ {
3356
+ typedef typename decay<T>::type future_type;
3357
+ promise<future_type> p;
3358
+ p.set_value(boost::forward<T>(value));
3359
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3360
+ }
3361
+
3362
+ #if defined BOOST_THREAD_USES_MOVE
3363
+ inline BOOST_THREAD_FUTURE<void> make_ready_future()
3364
+ {
3365
+ promise<void> p;
3366
+ p.set_value();
3367
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3368
+ }
3369
+ #endif
3370
+
3371
+ ////////////////////////////////
3372
+ // make_exceptional_future
3373
+ ////////////////////////////////
3374
+ template <typename T>
3375
+ BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr ex)
3376
+ {
3377
+ promise<T> p;
3378
+ p.set_exception(ex);
3379
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3380
+ }
3381
+
3382
+ #if 0
3383
+ template<typename CLOSURE>
3384
+ make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> {
3385
+ typedef decltype(closure() T;
3386
+ promise<T> p;
3387
+ try
3388
+ {
3389
+ p.set_value(closure());
3390
+ }
3391
+ catch(...)
3392
+ {
3393
+ p.set_exception(std::current_exception());
3394
+ }
3395
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
3396
+ }
3397
+ #endif
3398
+
3399
+ ////////////////////////////////
3400
+ // make_shared_future deprecated
3401
+ ////////////////////////////////
3402
+ template <typename T>
3403
+ shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value)
3404
+ {
3405
+ typedef typename decay<T>::type future_type;
3406
+ promise<future_type> p;
3407
+ p.set_value(boost::forward<T>(value));
3408
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
3409
+ }
3410
+
3411
+
3412
+ inline shared_future<void> make_shared_future()
3413
+ {
3414
+ promise<void> p;
3415
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
3416
+
3417
+ }
3418
+
3419
+ ////////////////////////////////
3420
+ // make_ready_shared_future
3421
+ ////////////////////////////////
3422
+ template <typename T>
3423
+ shared_future<typename decay<T>::type> make_ready_shared_future(BOOST_THREAD_FWD_REF(T) value)
3424
+ {
3425
+ typedef typename decay<T>::type future_type;
3426
+ promise<future_type> p;
3427
+ p.set_value(boost::forward<T>(value));
3428
+ return p.get_future().share();
3429
+ }
3430
+
3431
+
3432
+ inline shared_future<void> make_ready_shared_future()
3433
+ {
3434
+ promise<void> p;
3435
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
3436
+
3437
+ }
3438
+
3439
+ ////////////////////////////////
3440
+ // make_exceptional_shared_future
3441
+ ////////////////////////////////
3442
+ template <typename T>
3443
+ shared_future<T> make_exceptional_shared_future(exception_ptr ex)
3444
+ {
3445
+ promise<T> p;
3446
+ p.set_exception(ex);
3447
+ return p.get_future().share();
3448
+ }
3449
+
3450
+ ////////////////////////////////
3451
+ // detail::future_async_continuation
3452
+ ////////////////////////////////
3453
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
3454
+ namespace detail
3455
+ {
3456
+
3457
+ /////////////////////////
3458
+ /// future_async_continuation
3459
+ /////////////////////////
3460
+
3461
+ template<typename F, typename Rp, typename Fp>
3462
+ struct future_async_continuation: future_object<Rp>
3463
+ {
3464
+ typedef future_object<Rp> base_type;
3465
+ typedef typename base_type::move_dest_type move_dest_type;
3466
+ typedef weak_ptr<future_object_base> parent_ptr_type;
3467
+
3468
+ F parent;
3469
+ Fp continuation;
3470
+ boost::thread thr_;
3471
+
3472
+ public:
3473
+ future_async_continuation(
3474
+ F& f, BOOST_THREAD_FWD_REF(Fp) c
3475
+ ) :
3476
+ parent(f.future_),
3477
+ //continuation(boost::move(c)),
3478
+ continuation(c),
3479
+ thr_()
3480
+ {
3481
+ this->set_async();
3482
+ }
3483
+
3484
+ ~future_async_continuation()
3485
+ {
3486
+ if (thr_.get_id()==thread::id())
3487
+ {
3488
+ //BOOST_THREAD_LOG << "ERRORRRRRRRRR ~future_async_continuation " << this << " " << thr_.get_id() << BOOST_THREAD_END_LOG;
3489
+ return;
3490
+ }
3491
+ if (thr_.joinable()) {
3492
+ thr_.join();
3493
+ }
3494
+ }
3495
+
3496
+ void launch_continuation(boost::unique_lock<boost::mutex>& lock)
3497
+ {
3498
+ lock.unlock();
3499
+ thr_ = thread(&future_async_continuation::run, this);
3500
+ }
3501
+
3502
+ move_dest_type get()
3503
+ {
3504
+ if (thr_.joinable()) thr_.join();
3505
+ // fixme Is the lock needed during the whole scope?
3506
+ //this->wait();
3507
+ boost::unique_lock<boost::mutex> lock(this->mutex);
3508
+ this->wait_internal(lock);
3509
+
3510
+ // fixme use boost::move
3511
+ return static_cast<move_dest_type>(*(this->result));
3512
+ }
3513
+ static void run(future_async_continuation* that)
3514
+ {
3515
+ try
3516
+ {
3517
+ that->mark_finished_with_result(that->continuation(that->parent));
3518
+ }
3519
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
3520
+ catch(thread_interrupted& )
3521
+ {
3522
+ that->mark_interrupted_finish();
3523
+ }
3524
+ #endif
3525
+ catch(...)
3526
+ {
3527
+ that->mark_exceptional_finish();
3528
+ }
3529
+ }
3530
+ };
3531
+
3532
+ template<typename F, typename Fp>
3533
+ struct future_async_continuation<F, void, Fp>: public future_object<void>
3534
+ {
3535
+ typedef future_object<void> base_type;
3536
+ F parent;
3537
+ Fp continuation;
3538
+ boost::thread thr_;
3539
+
3540
+ public:
3541
+ future_async_continuation(
3542
+ F& f, BOOST_THREAD_FWD_REF(Fp) c
3543
+ ) :
3544
+ parent(f.future_),
3545
+ continuation(boost::move(c)),
3546
+ thr_()
3547
+ {
3548
+ this->set_async();
3549
+ }
3550
+
3551
+ ~future_async_continuation()
3552
+ {
3553
+ if (thr_.get_id()==thread::id())
3554
+ {
3555
+ return;
3556
+ }
3557
+ if (thr_.joinable()) thr_.join();
3558
+ }
3559
+
3560
+ void launch_continuation(boost::unique_lock<boost::mutex>& lk)
3561
+ {
3562
+ lk.unlock();
3563
+ thr_ = thread(&future_async_continuation::run, this);
3564
+ }
3565
+
3566
+ static void run(future_async_continuation* that)
3567
+ {
3568
+ try
3569
+ {
3570
+ that->continuation(that->parent);
3571
+ that->mark_finished_with_result();
3572
+ }
3573
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
3574
+ catch(thread_interrupted& )
3575
+ {
3576
+ that->mark_interrupted_finish();
3577
+ }
3578
+ #endif
3579
+ catch(...)
3580
+ {
3581
+ that->mark_exceptional_finish();
3582
+ }
3583
+ }
3584
+ };
3585
+
3586
+
3587
+ //////////////////////////
3588
+ /// future_deferred_continuation
3589
+ //////////////////////////
3590
+ template<typename F, typename Rp, typename Fp>
3591
+ struct future_deferred_continuation: future_object<Rp>
3592
+ {
3593
+ typedef future_object<Rp> base_type;
3594
+ F parent;
3595
+ Fp continuation;
3596
+
3597
+ public:
3598
+ future_deferred_continuation(
3599
+ F& f, BOOST_THREAD_FWD_REF(Fp) c
3600
+ ) :
3601
+ parent(f.future_),
3602
+ //continuation(boost::move(c))
3603
+ continuation(c)
3604
+ {
3605
+ this->set_deferred();
3606
+ }
3607
+
3608
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk)
3609
+ {
3610
+ execute(lk);
3611
+ }
3612
+
3613
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
3614
+ try
3615
+ {
3616
+ this->mark_finished_with_result_internal(continuation(parent), lck);
3617
+ }
3618
+ catch (...)
3619
+ {
3620
+ this->mark_exceptional_finish_internal(current_exception(), lck);
3621
+ }
3622
+ }
3623
+ };
3624
+
3625
+ template<typename F, typename Fp>
3626
+ struct future_deferred_continuation<F,void,Fp>: future_object<void>
3627
+ {
3628
+ typedef future_object<void> base_type;
3629
+ F parent;
3630
+ Fp continuation;
3631
+
3632
+ public:
3633
+ future_deferred_continuation(
3634
+ F& f, BOOST_THREAD_FWD_REF(Fp) c
3635
+ ):
3636
+ parent(f.future_),
3637
+ continuation(boost::move(c))
3638
+ {
3639
+ this->set_deferred();
3640
+ }
3641
+
3642
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk)
3643
+ {
3644
+ execute(lk);
3645
+ }
3646
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
3647
+ try
3648
+ {
3649
+ continuation(parent);
3650
+ this->mark_finished_with_result_internal(lck);
3651
+ }
3652
+ catch (...)
3653
+ {
3654
+ this->mark_exceptional_finish_internal(current_exception(), lck);
3655
+ }
3656
+ }
3657
+ };
3658
+
3659
+ ////////////////////////////////
3660
+ // make_future_deferred_continuation
3661
+ ////////////////////////////////
3662
+ template<typename F, typename Rp, typename Fp>
3663
+ BOOST_THREAD_FUTURE<Rp>
3664
+ make_future_deferred_continuation(
3665
+ boost::unique_lock<boost::mutex> &lock,
3666
+ F& f, BOOST_THREAD_FWD_REF(Fp) c
3667
+ )
3668
+ {
3669
+ shared_ptr<future_deferred_continuation<F, Rp, Fp> >
3670
+ h(new future_deferred_continuation<F, Rp, Fp>(f, boost::forward<Fp>(c)));
3671
+ f.future_->set_continuation_ptr(h, lock);
3672
+ return BOOST_THREAD_FUTURE<Rp>(h);
3673
+ }
3674
+
3675
+ ////////////////////////////////
3676
+ // make_future_async_continuation
3677
+ ////////////////////////////////
3678
+ template<typename F, typename Rp, typename Fp>
3679
+ BOOST_THREAD_FUTURE<Rp>
3680
+ make_future_async_continuation(
3681
+ boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c
3682
+ )
3683
+ {
3684
+ shared_ptr<future_async_continuation<F,Rp, Fp> >
3685
+ h(new future_async_continuation<F,Rp, Fp>(f, boost::forward<Fp>(c)));
3686
+ f.future_->set_continuation_ptr(h, lock);
3687
+
3688
+ return BOOST_THREAD_FUTURE<Rp>(h);
3689
+ }
3690
+
3691
+ // template <typename F, typename R, typename C>
3692
+ // struct future_continuation : future_object<R>
3693
+ // {
3694
+ // F& parent;
3695
+ // C continuation;
3696
+ // launch policy_;
1809
3697
  //
1810
- // BOOST_THREAD_FUTURE<R> ret = pt.get_future();
1811
- // boost::thread( boost::move(pt) ).detach();
1812
- // return ::boost::move(ret);
3698
+ // future_continuation(boost::unique_lock<boost::mutex>& lk, F& f, BOOST_THREAD_FWD_REF(C) c) :
3699
+ // parent(f),
3700
+ // continuation(boost::forward<C>(c)),
3701
+ // policy_(f.launch_policy())
3702
+ // {
3703
+ // init_continuation(lk);
1813
3704
  // }
1814
- // else if (int(policy) & int(launch::deferred))
3705
+ // future_continuation(boost::unique_lock<boost::mutex>& lk, F& f, BOOST_THREAD_FWD_REF(C) c, launch policy) :
3706
+ // parent(f),
3707
+ // continuation(boost::forward<C>(c)),
3708
+ // policy_(policy)
1815
3709
  // {
1816
- // packaged_task<R> pt( f );
3710
+ // init_continuation(lk);
3711
+ // }
3712
+ // ~future_continuation()
3713
+ // {}
1817
3714
  //
1818
- // BOOST_THREAD_FUTURE<R> ret = pt.get_future();
1819
- // return ::boost::move(ret);
1820
- // } else {
1821
- // BOOST_THREAD_FUTURE<R> ret;
1822
- // return ::boost::move(ret);
3715
+ // void init_continuation(boost::unique_lock<boost::mutex>& lk)
3716
+ // {
3717
+ // try
3718
+ // {
3719
+ // lk.unlock();
3720
+ // // fixme what to do depending on inherits_launch_policy_ and policy_?
3721
+ // if (int(policy_) & int(launch::deferred))
3722
+ // {
3723
+ // R val = continuation(parent);
3724
+ // next.set_value(boost::move(val));
3725
+ // }
3726
+ // else
3727
+ // {
3728
+ // BOOST_THREAD_FUTURE<R> f = async(policy_, continuation, boost::ref(parent));
3729
+ // R val = f.get();
3730
+ // next.set_value(boost::move(val));
3731
+ // }
3732
+ // }
3733
+ // catch (...)
3734
+ // {
3735
+ // next.set_exception(boost::current_exception());
3736
+ // }
1823
3737
  // }
1824
- // }
1825
- // template <class F>
1826
- // BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
1827
- // async(F const& f)
1828
- // {
1829
- // return async(launch::any, f);
1830
- // }
3738
+ // private:
3739
+ //
3740
+ // future_continuation(future_continuation const&);
3741
+ // future_continuation& operator=(future_continuation const&);
3742
+ // };
3743
+ //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
3744
+ // template <typename F, typename R, typename CR>
3745
+ // struct future_continuation<F,R,CR(*)(F&)> : future_object<R>
3746
+ // {
3747
+ // F& parent;
3748
+ // CR(*continuation)(F&) ;
3749
+ // launch policy_;
3750
+ //
3751
+ // future_continuation(F& f, CR(*c)(F&)) :
3752
+ // parent(f),
3753
+ // continuation(c),
3754
+ // policy_(f.launch_policy()),
3755
+ // next()
3756
+ // {}
3757
+ // future_continuation(F& f, CR(*c)(F&), launch policy) :
3758
+ // parent(f),
3759
+ // continuation(c),
3760
+ // policy_(policy),
3761
+ // next()
3762
+ // {}
3763
+ // ~future_continuation()
3764
+ // {}
3765
+ //
3766
+ // void start_continuation(boost::unique_lock<boost::mutex>& lk)
3767
+ // {
3768
+ // try
3769
+ // {
3770
+ // lk.unlock();
3771
+ // // fixme what to do depending on inherits_launch_policy_ and policy_?
3772
+ // if (int(policy_) & int(launch::deferred))
3773
+ // {
3774
+ // R val = continuation(parent);
3775
+ // next.set_value(boost::move(val));
3776
+ // }
3777
+ // else
3778
+ // {
3779
+ // BOOST_THREAD_FUTURE<R> f = async(policy_, continuation, boost::ref(parent));
3780
+ // R val = f.get();
3781
+ // next.set_value(boost::move(val));
3782
+ // }
3783
+ // }
3784
+ // catch (...)
3785
+ // {
3786
+ // next.set_exception(boost::current_exception());
3787
+ // }
3788
+ // }
3789
+ // private:
3790
+ //
3791
+ // future_continuation(future_continuation const&);
3792
+ // future_continuation& operator=(future_continuation const&);
3793
+ // };
3794
+ //#endif
3795
+ }
1831
3796
 
1832
- template <class F>
1833
- BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
1834
- async(launch policy, BOOST_THREAD_FWD_REF(F) f)
3797
+ ////////////////////////////////
3798
+ // template<typename F>
3799
+ // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
3800
+ ////////////////////////////////
3801
+
3802
+ template <typename R>
3803
+ template <typename F>
3804
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type>
3805
+ BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func)
3806
+ {
3807
+
3808
+ typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type future_type;
3809
+
3810
+ if (this->future_==0)
3811
+ {
3812
+ // fixme what to do when the future has no associated state?
3813
+ return BOOST_THREAD_FUTURE<future_type>();
3814
+ }
3815
+
3816
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
3817
+ if (int(policy) & int(launch::async))
1835
3818
  {
1836
- typedef typename boost::result_of<typename decay<F>::type()>::type R;
1837
- if (int(policy) & int(launch::async))
3819
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation<BOOST_THREAD_FUTURE<R>, future_type, F>(
3820
+ lock, *this, boost::forward<F>(func)
3821
+ )));
3822
+ }
3823
+ else
3824
+ if (int(policy) & int(launch::deferred))
1838
3825
  {
1839
- packaged_task<R> pt( boost::forward<F>(f) );
1840
-
1841
- BOOST_THREAD_FUTURE<R> ret = pt.get_future();
1842
- boost::thread( boost::move(pt) ).detach();
1843
- return ::boost::move(ret);
3826
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation<BOOST_THREAD_FUTURE<R>, future_type, F>(
3827
+ lock, *this, boost::forward<F>(func)
3828
+ )));
1844
3829
  }
1845
- else if (int(policy) & int(launch::deferred))
1846
- {
1847
- packaged_task<R> pt( boost::forward<F>(f) );
3830
+ else
3831
+ {
3832
+ // fixme what to do when the policy is invalid?
3833
+ return BOOST_THREAD_FUTURE<future_type>();
3834
+ }
1848
3835
 
1849
- BOOST_THREAD_FUTURE<R> ret = pt.get_future();
1850
- return ::boost::move(ret);
1851
- } else {
1852
- BOOST_THREAD_FUTURE<R> ret;
1853
- return ::boost::move(ret);
1854
- }
3836
+ }
3837
+ template <typename R>
3838
+ template <typename F>
3839
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type>
3840
+ BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func)
3841
+ {
3842
+
3843
+ typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type future_type;
3844
+
3845
+ if (this->future_==0)
3846
+ {
3847
+ //BOOST_THREAD_LOG << "ERROR future::then " << this << BOOST_THREAD_END_LOG;
3848
+ // fixme what to do when the future has no associated state?
3849
+ return BOOST_THREAD_FUTURE<future_type>();
1855
3850
  }
1856
- template <class F>
1857
- BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
1858
- async(BOOST_THREAD_FWD_REF(F) f)
3851
+
3852
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
3853
+ if (int(this->launch_policy()) & int(launch::async))
3854
+ {
3855
+ return boost::detail::make_future_async_continuation<BOOST_THREAD_FUTURE<R>, future_type, F>(
3856
+ lock, *this, boost::forward<F>(func)
3857
+ );
3858
+ }
3859
+ else if (int(this->launch_policy()) & int(launch::deferred))
3860
+ {
3861
+ this->future_->wait_internal(lock);
3862
+ return boost::detail::make_future_deferred_continuation<BOOST_THREAD_FUTURE<R>, future_type, F>(
3863
+ lock, *this, boost::forward<F>(func)
3864
+ );
3865
+ }
3866
+ else
1859
3867
  {
1860
- return async(launch::any, boost::forward<F>(f));
3868
+ // fixme what to do when the policy is invalid?
3869
+ return BOOST_THREAD_FUTURE<future_type>();
1861
3870
  }
3871
+ }
3872
+ //#if 0 && defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
3873
+ // template <typename R>
3874
+ // template<typename RF>
3875
+ // BOOST_THREAD_FUTURE<RF>
3876
+ // BOOST_THREAD_FUTURE<R>::then(RF(*func)(BOOST_THREAD_FUTURE<R>&))
3877
+ // {
3878
+ //
3879
+ // typedef RF future_type;
3880
+ //
3881
+ // if (this->future_)
3882
+ // {
3883
+ // boost::unique_lock<boost::mutex> lock(this->future_->mutex);
3884
+ // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr =
3885
+ // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func);
3886
+ // if (ptr==0)
3887
+ // {
3888
+ // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
3889
+ // }
3890
+ // this->future_->set_continuation_ptr(ptr, lock);
3891
+ // return ptr->get_future();
3892
+ // } else {
3893
+ // // fixme what to do when the future has no associated state?
3894
+ // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
3895
+ // }
3896
+ //
3897
+ // }
3898
+ // template <typename R>
3899
+ // template<typename RF>
3900
+ // BOOST_THREAD_FUTURE<RF>
3901
+ // BOOST_THREAD_FUTURE<R>::then(launch policy, RF(*func)(BOOST_THREAD_FUTURE<R>&))
3902
+ // {
3903
+ //
3904
+ // typedef RF future_type;
3905
+ //
3906
+ // if (this->future_)
3907
+ // {
3908
+ // boost::unique_lock<boost::mutex> lock(this->future_->mutex);
3909
+ // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr =
3910
+ // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func, policy);
3911
+ // if (ptr==0)
3912
+ // {
3913
+ // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
3914
+ // }
3915
+ // this->future_->set_continuation_ptr(ptr, lock);
3916
+ // return ptr->get_future();
3917
+ // } else {
3918
+ // // fixme what to do when the future has no associated state?
3919
+ // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
3920
+ // }
3921
+ //
3922
+ // }
3923
+ //#endif
1862
3924
 
1863
3925
  #endif
1864
3926