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.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/.gitignore +1 -0
- data/.travis.yml +1 -1
- data/NEWS +15 -0
- data/README.md +5 -3
- data/Rakefile +1 -0
- data/bin/passenger-config +1 -5
- data/bin/passenger-install-apache2-module +53 -5
- data/bin/passenger-install-nginx-module +19 -6
- data/bin/passenger-memory-stats +3 -3
- data/build/agents.rb +11 -8
- data/build/apache2.rb +9 -5
- data/build/basics.rb +15 -21
- data/build/common_library.rb +16 -6
- data/build/cplusplus_support.rb +5 -5
- data/build/cxx_tests.rb +3 -3
- data/build/documentation.rb +1 -1
- data/build/misc.rb +4 -37
- data/build/node_tests.rb +29 -0
- data/build/oxt_tests.rb +1 -1
- data/build/packaging.rb +29 -10
- data/build/preprocessor.rb +2 -1
- data/build/test_basics.rb +15 -6
- data/debian.template/locations.ini.template +1 -0
- data/debian.template/passenger.install.template +1 -0
- data/dev/copy_boost_headers.rb +7 -3
- data/dev/run_travis.sh +32 -16
- data/doc/Users guide Apache.idmap.txt +22 -34
- data/doc/Users guide Apache.txt +20 -234
- data/doc/Users guide Nginx.idmap.txt +84 -66
- data/doc/Users guide Nginx.txt +50 -1
- data/doc/Users guide Standalone.idmap.txt +74 -0
- data/doc/Users guide Standalone.txt +22 -9
- data/doc/Users guide.txt +51 -0
- data/doc/users_guide_snippets/environment_variables.txt +0 -3
- data/doc/users_guide_snippets/installation.txt +337 -380
- data/doc/users_guide_snippets/installation/run_installer.txt +58 -0
- data/doc/users_guide_snippets/installation/verify_running_epilogue.txt +6 -0
- data/doc/users_guide_snippets/support_information.txt +2 -9
- data/doc/users_guide_snippets/troubleshooting/default.txt +112 -0
- data/doc/users_guide_snippets/troubleshooting/rails.txt +56 -0
- data/doc/users_guide_snippets/where_to_get_support.txt +9 -0
- data/ext/apache2/Bucket.h +1 -1
- data/ext/apache2/Configuration.hpp +0 -44
- data/ext/apache2/CreateDirConfig.cpp +1 -1
- data/ext/apache2/CreateDirConfig.cpp.erb +1 -1
- data/ext/apache2/Hooks.cpp +28 -21
- data/ext/apache2/MergeDirConfig.cpp +1 -0
- data/ext/apache2/MergeDirConfig.cpp.erb +1 -1
- data/ext/apache2/SetHeaders.cpp +73 -0
- data/ext/apache2/SetHeaders.cpp.erb +88 -0
- data/ext/boost/algorithm/string/detail/find_format.hpp +5 -5
- data/ext/boost/algorithm/string/detail/find_format_all.hpp +5 -5
- data/ext/boost/algorithm/string/detail/finder.hpp +1 -1
- data/ext/boost/algorithm/string/formatter.hpp +2 -2
- data/ext/boost/assert.hpp +6 -1
- data/ext/boost/atomic.hpp +18 -0
- data/ext/boost/atomic/atomic.hpp +241 -0
- data/ext/boost/atomic/detail/base.hpp +585 -0
- data/ext/boost/atomic/detail/cas32strong.hpp +885 -0
- data/ext/boost/atomic/detail/cas32weak.hpp +947 -0
- data/ext/boost/atomic/detail/cas64strong.hpp +443 -0
- data/ext/boost/atomic/detail/config.hpp +54 -0
- data/ext/boost/atomic/detail/gcc-alpha.hpp +368 -0
- data/ext/boost/atomic/detail/gcc-armv6plus.hpp +252 -0
- data/ext/boost/atomic/detail/gcc-cas.hpp +157 -0
- data/ext/boost/atomic/detail/gcc-ppc.hpp +2850 -0
- data/ext/boost/atomic/detail/gcc-sparcv9.hpp +1259 -0
- data/ext/boost/atomic/detail/gcc-x86.hpp +1766 -0
- data/ext/boost/atomic/detail/generic-cas.hpp +206 -0
- data/ext/boost/atomic/detail/interlocked.hpp +200 -0
- data/ext/boost/atomic/detail/linux-arm.hpp +189 -0
- data/ext/boost/atomic/detail/lockpool.hpp +97 -0
- data/ext/boost/atomic/detail/platform.hpp +62 -0
- data/ext/boost/atomic/detail/type-classification.hpp +45 -0
- data/ext/boost/chrono/config.hpp +8 -3
- data/ext/boost/chrono/duration.hpp +9 -10
- data/ext/boost/chrono/system_clocks.hpp +1 -1
- data/ext/boost/chrono/time_point.hpp +4 -3
- data/ext/boost/config/auto_link.hpp +53 -52
- data/ext/boost/config/compiler/borland.hpp +1 -0
- data/ext/boost/config/compiler/clang.hpp +24 -1
- data/ext/boost/config/compiler/codegear.hpp +1 -0
- data/ext/boost/config/compiler/common_edg.hpp +1 -0
- data/ext/boost/config/compiler/cray.hpp +1 -0
- data/ext/boost/config/compiler/digitalmars.hpp +1 -0
- data/ext/boost/config/compiler/gcc.hpp +29 -3
- data/ext/boost/config/compiler/gcc_xml.hpp +2 -1
- data/ext/boost/config/compiler/hp_acc.hpp +1 -0
- data/ext/boost/config/compiler/intel.hpp +1 -1
- data/ext/boost/config/compiler/metrowerks.hpp +1 -0
- data/ext/boost/config/compiler/mpw.hpp +1 -0
- data/ext/boost/config/compiler/pathscale.hpp +1 -0
- data/ext/boost/config/compiler/pgi.hpp +1 -0
- data/ext/boost/config/compiler/sunpro_cc.hpp +1 -0
- data/ext/boost/config/compiler/vacpp.hpp +3 -2
- data/ext/boost/config/compiler/visualc.hpp +25 -11
- data/ext/boost/config/platform/vxworks.hpp +353 -15
- data/ext/boost/config/select_compiler_config.hpp +4 -4
- data/ext/boost/config/stdlib/dinkumware.hpp +10 -3
- data/ext/boost/config/stdlib/libstdcpp3.hpp +2 -1
- data/ext/boost/config/suffix.hpp +45 -19
- data/ext/boost/date_time/format_date_parser.hpp +1 -11
- data/ext/boost/date_time/strings_from_facet.hpp +5 -3
- data/ext/boost/detail/atomic_redef_macros.hpp +19 -0
- data/ext/boost/detail/atomic_undef_macros.hpp +39 -0
- data/ext/boost/detail/endian.hpp +52 -4
- data/ext/boost/detail/scoped_enum_emulation.hpp +10 -10
- data/ext/boost/detail/select_type.hpp +36 -0
- data/ext/boost/exception/current_exception_cast.hpp +1 -1
- data/ext/boost/exception/detail/error_info_impl.hpp +3 -5
- data/ext/boost/exception/detail/exception_ptr.hpp +3 -3
- data/ext/boost/exception/detail/is_output_streamable.hpp +1 -1
- data/ext/boost/exception/detail/object_hex_dump.hpp +1 -1
- data/ext/boost/exception/detail/type_info.hpp +1 -1
- data/ext/boost/exception/diagnostic_information.hpp +15 -14
- data/ext/boost/exception/exception.hpp +1 -1
- data/ext/boost/exception/get_error_info.hpp +1 -1
- data/ext/boost/exception/info.hpp +12 -13
- data/ext/boost/exception/to_string.hpp +6 -1
- data/ext/boost/exception/to_string_stub.hpp +9 -1
- data/ext/boost/foreach.hpp +5 -5
- data/ext/boost/function/function_template.hpp +6 -6
- data/ext/boost/functional/hash/detail/float_functions.hpp +90 -0
- data/ext/boost/functional/hash/detail/hash_float.hpp +11 -2
- data/ext/boost/functional/hash/extensions.hpp +14 -2
- data/ext/boost/functional/hash/hash.hpp +26 -5
- data/ext/boost/get_pointer.hpp +17 -2
- data/ext/boost/integer_traits.hpp +1 -1
- data/ext/boost/lexical_cast.hpp +615 -395
- data/ext/boost/libs/atomic/lockpool.cpp +24 -0
- data/ext/boost/libs/system/src/error_code.cpp +25 -18
- data/ext/boost/libs/thread/src/future.cpp +7 -5
- data/ext/boost/libs/thread/src/pthread/once.cpp +9 -3
- data/ext/boost/libs/thread/src/pthread/once_atomic.cpp +90 -0
- data/ext/boost/libs/thread/src/pthread/thread.cpp +129 -95
- data/ext/boost/libs/thread/src/pthread/timeconv.inl +20 -1
- data/ext/boost/limits.hpp +1 -1
- data/ext/boost/math/policies/policy.hpp +10 -0
- data/ext/boost/math/special_functions/detail/round_fwd.hpp +17 -4
- data/ext/boost/math/special_functions/fpclassify.hpp +114 -45
- data/ext/boost/math/special_functions/math_fwd.hpp +195 -83
- data/ext/boost/math/special_functions/sign.hpp +13 -8
- data/ext/boost/math/tools/config.hpp +38 -16
- data/ext/boost/move/algorithm.hpp +275 -0
- data/ext/boost/move/core.hpp +332 -0
- data/ext/boost/move/detail/config_begin.hpp +23 -0
- data/ext/boost/move/detail/config_end.hpp +20 -0
- data/ext/boost/move/detail/meta_utils.hpp +158 -0
- data/ext/boost/move/iterator.hpp +298 -0
- data/ext/boost/move/move.hpp +10 -1256
- data/ext/boost/move/traits.hpp +142 -0
- data/ext/boost/move/utility.hpp +194 -0
- data/ext/boost/mpl/assert.hpp +72 -4
- data/ext/boost/noncopyable.hpp +15 -3
- data/ext/boost/pointer_to_other.hpp +55 -0
- data/ext/boost/range/concepts.hpp +4 -4
- data/ext/boost/range/detail/extract_optional_type.hpp +1 -1
- data/ext/boost/range/empty.hpp +1 -1
- data/ext/boost/range/iterator_range_core.hpp +4 -1
- data/ext/boost/range/iterator_range_io.hpp +2 -2
- data/ext/boost/ratio/config.hpp +6 -0
- data/ext/boost/ratio/detail/overflow_helpers.hpp +2 -2
- data/ext/boost/smart_ptr/allocate_shared_array.hpp +250 -0
- data/ext/boost/smart_ptr/detail/allocate_array_helper.hpp +169 -0
- data/ext/boost/smart_ptr/detail/array_deleter.hpp +124 -0
- data/ext/boost/smart_ptr/detail/array_traits.hpp +53 -0
- data/ext/boost/smart_ptr/detail/array_utility.hpp +178 -0
- data/ext/boost/smart_ptr/detail/make_array_helper.hpp +157 -0
- data/ext/boost/smart_ptr/detail/operator_bool.hpp +16 -9
- data/ext/boost/smart_ptr/detail/shared_count.hpp +78 -7
- data/ext/boost/smart_ptr/detail/sp_convertible.hpp +15 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base.hpp +12 -6
- data/ext/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_aix.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_nt.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_pt.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp +162 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_solaris.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_spin.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_sync.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp +1 -0
- data/ext/boost/smart_ptr/detail/sp_counted_impl.hpp +15 -0
- data/ext/boost/smart_ptr/detail/sp_forward.hpp +39 -0
- data/ext/boost/smart_ptr/detail/sp_has_sync.hpp +19 -3
- data/ext/boost/smart_ptr/detail/sp_if_array.hpp +31 -0
- data/ext/boost/smart_ptr/detail/sp_nullptr_t.hpp +45 -0
- data/ext/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +5 -12
- data/ext/boost/smart_ptr/enable_shared_from_this.hpp +4 -4
- data/ext/boost/smart_ptr/make_shared.hpp +5 -1060
- data/ext/boost/smart_ptr/make_shared_array.hpp +247 -0
- data/ext/boost/smart_ptr/make_shared_object.hpp +1128 -0
- data/ext/boost/smart_ptr/scoped_array.hpp +32 -7
- data/ext/boost/smart_ptr/scoped_ptr.hpp +31 -5
- data/ext/boost/smart_ptr/shared_array.hpp +135 -20
- data/ext/boost/smart_ptr/shared_ptr.hpp +444 -126
- data/ext/boost/smart_ptr/weak_ptr.hpp +39 -28
- data/ext/boost/static_assert.hpp +74 -17
- data/ext/boost/system/error_code.hpp +76 -68
- data/ext/boost/system/system_error.hpp +5 -1
- data/ext/boost/thread/barrier.hpp +6 -2
- data/ext/boost/thread/completion_latch.hpp +233 -0
- data/ext/boost/thread/condition.hpp +6 -1
- data/ext/boost/thread/detail/async_func.hpp +571 -0
- data/ext/boost/thread/detail/config.hpp +248 -40
- data/ext/boost/thread/detail/counter.hpp +93 -0
- data/ext/boost/thread/detail/delete.hpp +12 -0
- data/ext/boost/thread/detail/invoke.hpp +1351 -0
- data/ext/boost/thread/detail/is_convertible.hpp +48 -0
- data/ext/boost/thread/detail/lockable_wrapper.hpp +45 -0
- data/ext/boost/thread/detail/log.hpp +83 -0
- data/ext/boost/thread/detail/make_tuple_indices.hpp +224 -0
- data/ext/boost/thread/detail/move.hpp +32 -16
- data/ext/boost/thread/detail/thread.hpp +236 -41
- data/ext/boost/thread/detail/thread_group.hpp +55 -9
- data/ext/boost/thread/detail/thread_interruption.hpp +4 -1
- data/ext/boost/thread/exceptions.hpp +2 -0
- data/ext/boost/thread/externally_locked.hpp +351 -0
- data/ext/boost/thread/externally_locked_stream.hpp +170 -0
- data/ext/boost/thread/future.hpp +2517 -455
- data/ext/boost/thread/future_error_code.hpp +61 -0
- data/ext/boost/thread/is_locked_by_this_thread.hpp +39 -0
- data/ext/boost/thread/latch.hpp +142 -0
- data/ext/boost/thread/lock_algorithms.hpp +468 -0
- data/ext/boost/thread/lock_concepts.hpp +197 -0
- data/ext/boost/thread/lock_factories.hpp +78 -0
- data/ext/boost/thread/lock_guard.hpp +88 -0
- data/ext/boost/thread/lock_options.hpp +31 -0
- data/ext/boost/thread/lock_traits.hpp +45 -0
- data/ext/boost/thread/lock_types.hpp +1226 -0
- data/ext/boost/thread/lockable_adapter.hpp +226 -0
- data/ext/boost/thread/lockable_concepts.hpp +157 -0
- data/ext/boost/thread/lockable_traits.hpp +207 -0
- data/ext/boost/thread/locks.hpp +5 -1816
- data/ext/boost/thread/mutex.hpp +33 -1
- data/ext/boost/thread/null_mutex.hpp +243 -0
- data/ext/boost/thread/once.hpp +10 -1
- data/ext/boost/thread/poly_lockable.hpp +68 -0
- data/ext/boost/thread/poly_lockable_adapter.hpp +89 -0
- data/ext/boost/thread/poly_shared_lockable.hpp +135 -0
- data/ext/boost/thread/poly_shared_lockable_adapter.hpp +170 -0
- data/ext/boost/thread/pthread/condition_variable.hpp +74 -26
- data/ext/boost/thread/pthread/condition_variable_fwd.hpp +54 -27
- data/ext/boost/thread/pthread/mutex.hpp +101 -38
- data/ext/boost/thread/pthread/once.hpp +459 -44
- data/ext/boost/thread/pthread/once_atomic.hpp +313 -0
- data/ext/boost/thread/pthread/recursive_mutex.hpp +19 -10
- data/ext/boost/thread/pthread/shared_mutex.hpp +226 -61
- data/ext/boost/thread/pthread/shared_mutex_assert.hpp +724 -0
- data/ext/boost/thread/pthread/thread_data.hpp +53 -50
- data/ext/boost/thread/pthread/timespec.hpp +96 -12
- data/ext/boost/thread/recursive_mutex.hpp +44 -1
- data/ext/boost/thread/reverse_lock.hpp +3 -2
- data/ext/boost/thread/scoped_thread.hpp +285 -0
- data/ext/boost/thread/shared_lock_guard.hpp +2 -1
- data/ext/boost/thread/shared_mutex.hpp +23 -0
- data/ext/boost/thread/strict_lock.hpp +235 -0
- data/ext/boost/thread/sync_bounded_queue.hpp +594 -0
- data/ext/boost/thread/sync_queue.hpp +516 -0
- data/ext/boost/thread/synchronized_value.hpp +1001 -0
- data/ext/boost/thread/testable_mutex.hpp +148 -0
- data/ext/boost/thread/thread.hpp +1 -13
- data/ext/boost/thread/thread_functors.hpp +57 -0
- data/ext/boost/thread/thread_guard.hpp +46 -0
- data/ext/boost/thread/thread_only.hpp +29 -0
- data/ext/boost/thread/v2/shared_mutex.hpp +1062 -0
- data/ext/boost/thread/v2/thread.hpp +37 -10
- data/ext/boost/thread/xtime.hpp +2 -1
- data/ext/boost/token_functions.hpp +16 -16
- data/ext/boost/type_traits/add_lvalue_reference.hpp +26 -0
- data/ext/boost/type_traits/add_reference.hpp +1 -1
- data/ext/boost/type_traits/add_rvalue_reference.hpp +4 -4
- data/ext/boost/type_traits/aligned_storage.hpp +13 -0
- data/ext/boost/type_traits/common_type.hpp +11 -12
- data/ext/boost/type_traits/config.hpp +1 -1
- data/ext/boost/type_traits/detail/common_type_imp.hpp +1 -1
- data/ext/boost/type_traits/detail/has_binary_operator.hpp +1 -1
- data/ext/boost/type_traits/detail/is_function_ptr_tester.hpp +1 -1
- data/ext/boost/type_traits/has_left_shift.hpp +49 -0
- data/ext/boost/type_traits/has_right_shift.hpp +49 -0
- data/ext/boost/type_traits/has_trivial_move_assign.hpp +57 -0
- data/ext/boost/type_traits/has_trivial_move_constructor.hpp +57 -0
- data/ext/boost/type_traits/intrinsics.hpp +18 -2
- data/ext/boost/type_traits/is_abstract.hpp +1 -1
- data/ext/boost/type_traits/is_array.hpp +1 -1
- data/ext/boost/type_traits/is_const.hpp +1 -1
- data/ext/boost/type_traits/is_convertible.hpp +78 -17
- data/ext/boost/type_traits/is_function.hpp +6 -1
- data/ext/boost/type_traits/is_integral.hpp +6 -1
- data/ext/boost/type_traits/is_nothrow_move_assignable.hpp +84 -0
- data/ext/boost/type_traits/is_nothrow_move_constructible.hpp +84 -0
- data/ext/boost/type_traits/is_pod.hpp +3 -1
- data/ext/boost/type_traits/is_rvalue_reference.hpp +1 -1
- data/ext/boost/type_traits/is_volatile.hpp +1 -1
- data/ext/boost/type_traits/make_signed.hpp +153 -0
- data/ext/boost/type_traits/make_unsigned.hpp +16 -0
- data/ext/boost/type_traits/remove_const.hpp +1 -1
- data/ext/boost/type_traits/remove_cv.hpp +1 -1
- data/ext/boost/type_traits/remove_reference.hpp +1 -1
- data/ext/boost/type_traits/remove_volatile.hpp +1 -1
- data/ext/boost/unordered/detail/allocate.hpp +1120 -0
- data/ext/boost/unordered/detail/buckets.hpp +876 -0
- data/ext/boost/unordered/detail/equivalent.hpp +680 -0
- data/ext/boost/unordered/detail/extract_key.hpp +183 -0
- data/ext/boost/unordered/detail/fwd.hpp +23 -0
- data/ext/boost/unordered/detail/table.hpp +861 -0
- data/ext/boost/unordered/detail/unique.hpp +622 -0
- data/ext/boost/unordered/detail/util.hpp +260 -0
- data/ext/boost/unordered/unordered_map.hpp +1652 -0
- data/ext/boost/unordered/unordered_map_fwd.hpp +65 -0
- data/ext/boost/unordered/unordered_set.hpp +1549 -0
- data/ext/boost/unordered/unordered_set_fwd.hpp +63 -0
- data/ext/boost/unordered_map.hpp +18 -0
- data/ext/boost/unordered_set.hpp +18 -0
- data/ext/boost/utility/addressof.hpp +2 -2
- data/ext/boost/utility/result_of.hpp +8 -1
- data/ext/boost/version.hpp +2 -2
- data/ext/common/Account.h +1 -1
- data/ext/common/AccountsDatabase.h +1 -1
- data/ext/common/AgentsStarter.cpp +3 -1
- data/ext/common/AgentsStarter.h +2 -2
- data/ext/common/ApplicationPool2/AppTypes.cpp +24 -6
- data/ext/common/ApplicationPool2/AppTypes.h +17 -8
- data/ext/common/ApplicationPool2/Common.h +12 -12
- data/ext/common/ApplicationPool2/DirectSpawner.h +2 -2
- data/ext/common/ApplicationPool2/DummySpawner.h +3 -3
- data/ext/common/ApplicationPool2/Group.h +6 -6
- data/ext/common/ApplicationPool2/Implementation.cpp +19 -19
- data/ext/common/ApplicationPool2/PipeWatcher.h +5 -5
- data/ext/common/ApplicationPool2/Pool.h +21 -21
- data/ext/common/ApplicationPool2/Process.h +6 -6
- data/ext/common/ApplicationPool2/Session.h +1 -1
- data/ext/common/ApplicationPool2/SmartSpawner.h +24 -12
- data/ext/common/ApplicationPool2/Socket.h +2 -2
- data/ext/common/ApplicationPool2/Spawner.h +64 -14
- data/ext/common/ApplicationPool2/SpawnerFactory.h +7 -7
- data/ext/common/ApplicationPool2/SuperGroup.h +5 -5
- data/ext/common/BackgroundEventLoop.cpp +4 -4
- data/ext/common/BackgroundEventLoop.h +1 -1
- data/ext/common/Constants.h +13 -1
- data/ext/common/EventedBufferedInput.h +8 -8
- data/ext/common/Exceptions.cpp +71 -0
- data/ext/common/Exceptions.h +60 -7
- data/ext/common/FileDescriptor.h +4 -4
- data/ext/common/MessageClient.h +1 -1
- data/ext/common/MessageServer.h +5 -5
- data/ext/common/MultiLibeio.cpp +3 -3
- data/ext/common/MultiLibeio.h +2 -2
- data/ext/common/RandomGenerator.h +11 -11
- data/ext/common/ResourceLocator.h +8 -1
- data/ext/common/SafeLibev.h +12 -12
- data/ext/common/ServerInstanceDir.h +11 -3
- data/ext/common/UnionStation.h +10 -10
- data/ext/common/Utils.cpp +11 -13
- data/ext/common/Utils.h +9 -9
- data/ext/common/Utils/BlockingQueue.h +10 -10
- data/ext/common/Utils/BufferedIO.h +1 -1
- data/ext/common/Utils/CachedFileStat.hpp +2 -2
- data/ext/common/Utils/FileChangeChecker.h +1 -1
- data/ext/common/Utils/HashMap.h +13 -4
- data/ext/common/Utils/IOUtils.cpp +33 -10
- data/ext/common/Utils/IniFile.h +3 -3
- data/ext/common/Utils/Lock.h +2 -2
- data/ext/common/Utils/MessagePassing.h +10 -10
- data/ext/common/Utils/ProcessMetricsCollector.h +24 -6
- data/ext/common/Utils/ScopeGuard.h +5 -5
- data/ext/common/Utils/jsoncpp.cpp +2 -0
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +26 -26
- data/ext/common/agents/HelperAgent/Main.cpp +18 -18
- data/ext/common/agents/HelperAgent/RequestHandler.cpp +4 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +30 -21
- data/ext/common/agents/LoggingAgent/AdminController.h +1 -1
- data/ext/common/agents/LoggingAgent/FilterSupport.h +13 -11
- data/ext/common/agents/LoggingAgent/LoggingServer.h +11 -11
- data/ext/common/agents/LoggingAgent/Main.cpp +9 -9
- data/ext/common/agents/LoggingAgent/RemoteSender.h +3 -3
- data/ext/common/agents/SpawnPreparer.cpp +1 -0
- data/ext/common/agents/Watchdog/AgentWatcher.cpp +8 -7
- data/ext/common/agents/Watchdog/Main.cpp +81 -73
- data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +1 -1
- data/ext/libev/Changes +57 -0
- data/ext/libev/LICENSE +2 -1
- data/ext/libev/Makefile.in +110 -50
- data/ext/libev/README +8 -8
- data/ext/libev/aclocal.m4 +1503 -861
- data/ext/libev/config.guess +290 -304
- data/ext/libev/config.sub +77 -198
- data/ext/libev/configure +1735 -890
- data/ext/libev/configure.ac +3 -2
- data/ext/libev/ev++.h +6 -6
- data/ext/libev/ev.c +541 -214
- data/ext/libev/ev.h +106 -100
- data/ext/libev/ev_epoll.c +1 -1
- data/ext/libev/ev_kqueue.c +20 -4
- data/ext/libev/ev_vars.h +15 -16
- data/ext/libev/ev_win32.c +12 -2
- data/ext/libev/ev_wrap.h +162 -160
- data/ext/libev/event.c +29 -6
- data/ext/libev/event.h +9 -2
- data/ext/libev/ltmain.sh +2632 -1384
- data/ext/nginx/ConfigurationCommands.c +1 -1
- data/ext/nginx/ConfigurationCommands.c.erb +3 -1
- data/ext/nginx/ContentHandler.c +25 -2
- data/ext/nginx/CreateLocationConfig.c +1 -0
- data/ext/nginx/CreateLocationConfig.c.erb +1 -1
- data/ext/nginx/MergeLocationConfig.c +1 -0
- data/ext/nginx/MergeLocationConfig.c.erb +1 -1
- data/ext/nginx/config +12 -0
- data/ext/oxt/dynamic_thread_group.hpp +7 -4
- data/ext/oxt/system_calls.cpp +5 -1
- data/ext/oxt/system_calls.hpp +3 -0
- data/helper-scripts/node-loader.js +117 -249
- data/lib/phusion_passenger.rb +27 -5
- data/lib/phusion_passenger/abstract_installer.rb +104 -9
- data/lib/phusion_passenger/admin_tools/memory_stats.rb +10 -9
- data/lib/phusion_passenger/apache2/config_options.rb +6 -3
- data/lib/phusion_passenger/common_library.rb +7 -1
- data/lib/phusion_passenger/constants.rb +6 -0
- data/lib/phusion_passenger/loader_shared_helpers.rb +7 -4
- data/lib/phusion_passenger/nginx/config_options.rb +2 -1
- data/lib/phusion_passenger/packaging.rb +3 -0
- data/lib/phusion_passenger/platform_info/apache.rb +43 -6
- data/lib/phusion_passenger/platform_info/apache_detector.rb +15 -5
- data/lib/phusion_passenger/platform_info/compiler.rb +167 -32
- data/lib/phusion_passenger/platform_info/cxx_portability.rb +133 -77
- data/lib/phusion_passenger/platform_info/depcheck.rb +17 -7
- data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +3 -3
- data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
- data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +5 -6
- data/lib/phusion_passenger/platform_info/linux.rb +2 -1
- data/lib/phusion_passenger/platform_info/operating_system.rb +1 -1
- data/lib/phusion_passenger/platform_info/ruby.rb +18 -3
- data/lib/phusion_passenger/standalone/runtime_installer.rb +6 -2
- data/lib/phusion_passenger/standalone/start_command.rb +8 -2
- data/lib/phusion_passenger/utils/ansi_colors.rb +9 -0
- data/lib/phusion_passenger/utils/hosts_file_parser.rb +4 -2
- data/node_lib/phusion_passenger/httplib_emulation.js +141 -0
- data/node_lib/phusion_passenger/line_reader.js +154 -0
- data/node_lib/phusion_passenger/request_handler.js +65 -0
- data/node_lib/phusion_passenger/session_protocol_parser.js +113 -0
- data/resources/templates/apache2/deployment_example.txt.erb +2 -1
- data/resources/templates/apache2/installing_against_a_different_apache.txt.erb +14 -0
- data/resources/templates/apache2/multiple_apache_installations_detected.txt.erb +15 -0
- data/resources/templates/apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb +4 -5
- data/resources/templates/general_error_with_html.html.template +1 -1
- data/resources/templates/installer_common/gem_install_permission_problems.txt.erb +17 -0
- data/resources/templates/installer_common/low_amount_of_memory_warning.txt.erb +6 -4
- data/resources/templates/installer_common/world_inaccessible_directories.txt.erb +16 -0
- data/resources/templates/nginx/deployment_example.txt.erb +2 -1
- data/resources/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +4 -5
- data/resources/templates/standalone/config.erb +1 -0
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +3 -3
- data/test/cxx/ApplicationPool2/PoolTest.cpp +4 -4
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +5 -5
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +5 -5
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +1 -1
- data/test/cxx/EventedBufferedInputTest.cpp +6 -6
- data/test/cxx/FileBackedPipeTest.cpp +1 -1
- data/test/cxx/MessagePassingTest.cpp +1 -1
- data/test/cxx/MessageServerTest.cpp +4 -4
- data/test/cxx/RequestHandlerTest.cpp +7 -7
- data/test/cxx/UnionStationTest.cpp +2 -2
- data/test/node/line_reader_spec.js +338 -0
- data/test/node/spec_helper.js +27 -0
- data/test/ruby/standalone/runtime_installer_spec.rb +2 -1
- metadata +131 -22
- metadata.gz.asc +7 -7
- data/ext/boost/functional/hash/detail/container_fwd_0x.hpp +0 -29
- data/ext/boost/lambda/core.hpp +0 -79
- data/ext/boost/lambda/detail/actions.hpp +0 -174
- data/ext/boost/lambda/detail/arity_code.hpp +0 -110
- data/ext/boost/lambda/detail/function_adaptors.hpp +0 -789
- data/ext/boost/lambda/detail/is_instance_of.hpp +0 -104
- data/ext/boost/lambda/detail/lambda_config.hpp +0 -48
- data/ext/boost/lambda/detail/lambda_functor_base.hpp +0 -615
- data/ext/boost/lambda/detail/lambda_functors.hpp +0 -324
- data/ext/boost/lambda/detail/lambda_fwd.hpp +0 -74
- data/ext/boost/lambda/detail/lambda_traits.hpp +0 -578
- data/ext/boost/lambda/detail/member_ptr.hpp +0 -737
- data/ext/boost/lambda/detail/operator_actions.hpp +0 -139
- data/ext/boost/lambda/detail/operator_lambda_func_base.hpp +0 -271
- data/ext/boost/lambda/detail/operator_return_type_traits.hpp +0 -917
- data/ext/boost/lambda/detail/operators.hpp +0 -370
- data/ext/boost/lambda/detail/ret.hpp +0 -325
- data/ext/boost/lambda/detail/return_type_traits.hpp +0 -282
- data/ext/boost/lambda/detail/select_functions.hpp +0 -74
- 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
|
data/ext/boost/thread/future.hpp
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
// (C) Copyright 2008-10 Anthony Williams
|
2
|
-
// (C) Copyright 2011-
|
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/
|
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
|
-
|
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/
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
258
|
-
|
259
|
-
|
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
|
334
|
+
void wait_internal(boost::unique_lock<boost::mutex> &lock, bool rethrow=true)
|
284
335
|
{
|
285
|
-
|
286
|
-
|
287
|
-
|
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
|
-
|
341
|
+
is_deferred_=false;
|
342
|
+
execute(lock);
|
343
|
+
//lock.unlock();
|
294
344
|
}
|
295
|
-
|
345
|
+
else
|
296
346
|
{
|
297
|
-
|
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::
|
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::
|
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
|
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
|
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
|
-
|
508
|
+
typedef boost::scoped_ptr<T> storage_type;
|
509
|
+
struct dummy;
|
377
510
|
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
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
|
-
|
384
|
-
|
385
|
-
|
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
|
-
|
388
|
-
|
389
|
-
|
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
|
-
|
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
|
-
|
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::
|
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::
|
487
|
-
|
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
|
-
|
644
|
+
|
645
|
+
virtual move_dest_type get()
|
491
646
|
{
|
492
647
|
wait();
|
493
|
-
return
|
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
|
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::
|
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
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
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
|
-
|
579
|
-
|
866
|
+
typedef future_object<Rp> base_type;
|
867
|
+
typedef typename base_type::move_dest_type move_dest_type;
|
580
868
|
|
581
|
-
|
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
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
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
|
-
|
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
|
-
|
598
|
-
|
599
|
-
#
|
600
|
-
|
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
|
-
|
603
|
-
|
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
|
-
|
809
|
-
class BOOST_THREAD_FUTURE
|
1322
|
+
namespace detail
|
810
1323
|
{
|
811
|
-
|
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
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
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
|
-
|
829
|
-
BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
|
1347
|
+
public:
|
830
1348
|
typedef future_state::state state;
|
831
1349
|
|
832
|
-
|
833
|
-
{}
|
834
|
-
|
835
|
-
~BOOST_THREAD_FUTURE()
|
836
|
-
{}
|
1350
|
+
BOOST_THREAD_MOVABLE(basic_future)
|
1351
|
+
basic_future(): future_() {}
|
1352
|
+
~basic_future() {}
|
837
1353
|
|
838
|
-
|
839
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
990
|
-
|
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
|
-
|
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=(
|
1661
|
+
shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT
|
1001
1662
|
{
|
1002
|
-
|
1003
|
-
|
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
|
-
|
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
|
-
|
1024
|
-
|
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
|
-
|
1710
|
+
#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
1711
|
+
#include <boost/detail/atomic_undef_macros.hpp>
|
1712
|
+
if(!atomic_load(&future_))
|
1027
1713
|
{
|
1028
|
-
|
1714
|
+
future_ptr blank;
|
1715
|
+
atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R>));
|
1029
1716
|
}
|
1030
|
-
|
1717
|
+
#include <boost/detail/atomic_redef_macros.hpp>
|
1718
|
+
#endif
|
1031
1719
|
}
|
1032
1720
|
|
1033
|
-
|
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
|
-
|
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
|
-
|
1744
|
+
~promise()
|
1039
1745
|
{
|
1040
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1773
|
+
void swap(promise& other)
|
1049
1774
|
{
|
1050
|
-
|
1775
|
+
future_.swap(other.future_);
|
1776
|
+
std::swap(future_obtained,other.future_obtained);
|
1051
1777
|
}
|
1052
1778
|
|
1053
|
-
|
1779
|
+
// Result retrieval
|
1780
|
+
BOOST_THREAD_FUTURE<R> get_future()
|
1054
1781
|
{
|
1055
|
-
|
1782
|
+
lazy_init();
|
1783
|
+
if (future_.get()==0)
|
1056
1784
|
{
|
1057
|
-
boost::throw_exception(
|
1785
|
+
boost::throw_exception(promise_moved());
|
1058
1786
|
}
|
1059
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1806
|
+
// void set_value(R && r);
|
1807
|
+
void set_value(typename detail::future_traits<R>::rvalue_source_type r)
|
1069
1808
|
{
|
1070
|
-
|
1809
|
+
lazy_init();
|
1810
|
+
boost::unique_lock<boost::mutex> lock(future_->mutex);
|
1811
|
+
if(future_->done)
|
1071
1812
|
{
|
1072
|
-
boost::throw_exception(
|
1813
|
+
boost::throw_exception(promise_already_satisfied());
|
1073
1814
|
}
|
1074
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1086
|
-
|
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(
|
1845
|
+
if (future_.get()==0)
|
1090
1846
|
{
|
1091
|
-
boost::throw_exception(
|
1847
|
+
boost::throw_exception(promise_moved());
|
1092
1848
|
}
|
1093
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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::
|
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
|
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
|
1961
|
+
return BOOST_THREAD_FUTURE<R&>(future_);
|
1191
1962
|
}
|
1192
1963
|
|
1193
|
-
void set_value(
|
1964
|
+
void set_value(R& r)
|
1194
1965
|
{
|
1195
1966
|
lazy_init();
|
1196
|
-
boost::
|
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
|
-
|
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::
|
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_->
|
1983
|
+
future_->mark_exceptional_finish_internal(p, lock);
|
1214
1984
|
}
|
1215
1985
|
|
1216
|
-
|
1986
|
+
// setting the result with deferred notification
|
1987
|
+
void set_value_at_thread_exit(R& r)
|
1217
1988
|
{
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
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
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
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
|
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
|
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::
|
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::
|
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::
|
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
|
-
|
1383
|
-
|
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::
|
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
|
-
|
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::
|
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
|
-
|
1443
|
-
|
1444
|
-
|
2294
|
+
void do_apply()
|
2295
|
+
{
|
2296
|
+
try
|
2297
|
+
{
|
2298
|
+
this->set_value_at_thread_exit(f());
|
2299
|
+
}
|
1445
2300
|
#endif
|
1446
|
-
|
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
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
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
|
-
|
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
|
1493
|
-
|
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
|
1532
|
-
|
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
|
-
|
1565
|
-
|
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
|
-
|
1579
|
-
|
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
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
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
|
-
#
|
1612
|
-
|
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
|
-
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
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
|
-
|
1625
|
-
packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
|
2812
|
+
explicit packaged_task(R(*f)())
|
1626
2813
|
{
|
1627
|
-
|
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))
|
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
|
-
|
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
|
-
|
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
|
-
|
1743
|
-
|
1744
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1763
|
-
|
1764
|
-
|
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
|
-
|
1767
|
-
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
3326
|
+
#endif
|
1800
3327
|
|
1801
|
-
|
1802
|
-
|
1803
|
-
//
|
1804
|
-
|
1805
|
-
|
1806
|
-
|
1807
|
-
|
1808
|
-
|
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
|
-
//
|
1811
|
-
//
|
1812
|
-
//
|
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
|
-
//
|
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
|
-
//
|
3710
|
+
// init_continuation(lk);
|
3711
|
+
// }
|
3712
|
+
// ~future_continuation()
|
3713
|
+
// {}
|
1817
3714
|
//
|
1818
|
-
//
|
1819
|
-
//
|
1820
|
-
//
|
1821
|
-
//
|
1822
|
-
//
|
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
|
-
//
|
1826
|
-
//
|
1827
|
-
//
|
1828
|
-
//
|
1829
|
-
|
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
|
-
|
1833
|
-
|
1834
|
-
|
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
|
-
|
1837
|
-
|
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
|
-
|
1840
|
-
|
1841
|
-
|
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
|
-
|
1846
|
-
|
1847
|
-
|
3830
|
+
else
|
3831
|
+
{
|
3832
|
+
// fixme what to do when the policy is invalid?
|
3833
|
+
return BOOST_THREAD_FUTURE<future_type>();
|
3834
|
+
}
|
1848
3835
|
|
1849
|
-
|
1850
|
-
|
1851
|
-
|
1852
|
-
|
1853
|
-
|
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
|
-
|
1857
|
-
|
1858
|
-
|
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
|
-
|
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
|
|