diff options
Diffstat (limited to 'src/boost/libs/thread/test')
433 files changed, 46108 insertions, 0 deletions
diff --git a/src/boost/libs/thread/test/Carbon.r b/src/boost/libs/thread/test/Carbon.r new file mode 100644 index 000000000..e0ac5b449 --- /dev/null +++ b/src/boost/libs/thread/test/Carbon.r @@ -0,0 +1,18 @@ +/* + * Permit this Carbon application to launch on OS X + * + * © 1997-2000 Metrowerks Corp. + * + * Questions and comments to: + * <mailto:support@metrowerks.com> + * <http://www.metrowerks.com/> + */ + + +/*----------------------------carb ¥ Carbon on OS X launch information --------------------------*/ +type 'carb' { +}; + + +resource 'carb'(0) { +}; diff --git a/src/boost/libs/thread/test/Jamfile.v2 b/src/boost/libs/thread/test/Jamfile.v2 new file mode 100644 index 000000000..5788c83d8 --- /dev/null +++ b/src/boost/libs/thread/test/Jamfile.v2 @@ -0,0 +1,1098 @@ +# (C) Copyright William E. Kempf 2001. +# (C) Copyright 2007 Anthony Williams. +# (C) Copyright 2011-2012 Vicente J.Botet Escriba. +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Boost.Threads test Jamfile +# +# Additional configuration variables used: +# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32 +# library should be used instead of "native" threads. This feature is +# mostly used for testing and it's generally recommended you use the +# native threading libraries instead. PTW32 should be set to be a list +# of two strings, the first specifying the installation path of the +# pthreads-win32 library and the second specifying which library +# variant to link against (see the pthreads-win32 documentation). +# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib" + +# bring in rules for testing +import testing ; +import regex ; +import path ; +import os ; + +project + : requirements + <threading>multi + + <define>BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED + + <warnings>all + <toolset>gcc:<cxxflags>-Wextra + <toolset>gcc:<cxxflags>-pedantic + <toolset>gcc:<cxxflags>-Wno-long-long + #<toolset>gcc:<cxxflags>-ansi + #<toolset>gcc:<cxxflags>-fpermissive + <toolset>gcc-4:<cxxflags>-Wno-variadic-macros + <toolset>gcc-5:<cxxflags>-Wno-variadic-macros + #<toolset>gcc:<cxxflags>-Wunused-local-typedefs + <toolset>gcc:<cxxflags>-Wunused-function + <toolset>gcc:<cxxflags>-Wno-unused-parameter + + <toolset>darwin:<cxxflags>-Wextra + <toolset>darwin:<cxxflags>-pedantic + <toolset>darwin:<cxxflags>-Wno-long-long + #<toolset>darwin:<cxxflags>-ansi # doesn't work for 4.1.2 + <toolset>darwin:<cxxflags>-fpermissive + <toolset>darwin:<cxxflags>-Wno-variadic-macros + #<toolset>darwin:<cxxflags>-Wunused-local-typedefs + <toolset>darwin:<cxxflags>-Wunused-function + <toolset>darwin:<cxxflags>-Wno-unused-parameter + + #<toolset>pathscale:<cxxflags>-Wextra + <toolset>pathscale:<cxxflags>-Wno-long-long + <toolset>pathscale:<cxxflags>-pedantic + + <toolset>clang:<warnings>on + <toolset>clang:<cxxflags>-Wextra + #<toolset>clang:<cxxflags>-pedantic + <toolset>clang:<cxxflags>-Wno-long-long + #<toolset>clang:<cxxflags>-ansi + #<toolset>clang:<cxxflags>-fpermissive # doesn't work + <toolset>clang:<cxxflags>-Wunused-function + <toolset>clang:<cxxflags>-Wno-unused-parameter + + #<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.6.3:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.7.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.8.0:<cxxflags>-fdiagnostics-show-option + + <toolset>darwin-4.6.2:<cxxflags>-ansi + #<toolset>darwin-4.6.2:<cxxflags>-Wno-delete-non-virtual-dtor # doesn't work + <toolset>darwin-4.7.0:<cxxflags>-ansi + <toolset>darwin-4.7.0:<cxxflags>-Wno-delete-non-virtual-dtor + #<toolset>darwin-4.6.2:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.7.1:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.7.2:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.8.0:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.6.2x:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.7.1x:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.7.2x:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.8.0x:<cxxflags>-Wno-unused-local-typedefs + + #<toolset>clang-2.8:<cxxflags>-Wno-delete-non-virtual-dtor + #<toolset>clang-2.8:<cxxflags>-Wno-unused-function + #<toolset>clang-2.9:<cxxflags>-Wno-delete-non-virtual-dtor + #<toolset>clang-2.9:<cxxflags>-Wno-unused-function + <toolset>clang-3.0:<cxxflags>-Wno-delete-non-virtual-dtor + #<toolset>clang-3.0:<cxxflags>-Wno-unused-function + #<toolset>clang-3.0:<cxxflags>-Wno-unused-variable + #<toolset>clang-3.1:<cxxflags>-Wno-bind-to-temporary-copy + #<toolset>clang-3.2:<cxxflags>-Wno-bind-to-temporary-copy + +# Note: Some of the remarks from the Intel compiler are disabled +# remark #193: zero used for undefined preprocessing identifier "XXX" +# remark #304: access control not specified ("public" by default) +# remark #593: variable "XXX" was set but never used +# remark #1418: external function definition with no prior declaration +# remark #2415: variable "XXX" of static storage duration was declared but never referenced + + <toolset>intel:<cxxflags>-wd193,304,383,444 + <toolset>intel:<cxxflags>-wd593,981 + <toolset>intel:<cxxflags>-wd1418 + <toolset>intel:<cxxflags>-wd2415 + + <toolset>msvc:<cxxflags>/wd4100 + <toolset>msvc:<cxxflags>/wd4512 + <toolset>msvc:<cxxflags>/wd6246 + ; + +rule thread-run ( sources ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../build//boost_thread ] + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : : $(sources[1]:B)_lib ] + ; +} + + +rule thread-test ( sources ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../build//boost_thread : : : + <library>/boost/test//boost_unit_test_framework + ] + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : + <library>/boost/test//boost_unit_test_framework/<link>static + : $(sources[1]:B)_lib + ] + ; +} + +rule thread-run2 ( sources : name ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../build//boost_thread : : : + : $(name) ] + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : + : $(name)_lib ] + ; +} + +rule thread-run2-noit ( sources : name : reqs * ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../build//boost_thread : : : $(reqs) + : $(name) ] + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : $(reqs) + : $(name)_lib ] + #[ run $(sources) ../build//boost_thread : : : + # <define>BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS + # : $(name)_noit ] + ; +} + +rule thread-run2-noit-pthread ( sources : name ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../build//boost_thread : : : <threadapi>win32:<build>no + : $(name) ] + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : <threadapi>win32:<build>no + : $(name)_lib ] + #[ run $(sources) ../build//boost_thread : : : + # <define>BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS + # : $(name)_noit ] + ; +} + +rule thread-run2-h ( sources : name ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) : : : + <define>BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS + <define>BOOST_THREAD_VERSION=3 + : $(name)_h ] + ; +} + + +rule thread-run-lib2 ( sources : name ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : + : $(name)_lib ] + ; +} + + +rule thread-compile-fail ( sources : reqs * : name ) +{ + return + [ compile-fail $(sources) + : $(reqs) + : $(name) ] + ; +} + +rule clang-thread-safety ( properties * ) +{ + if <toolset>clang in $(properties) + { + return <cxxflags>-Werror=thread-safety <define>BOOST_THREAD_ENABLE_THREAD_SAFETY_ANALYSIS ; + } + else + { + return <build>no ; + } +} + +rule thread-safety-compile ( sources : reqs * : name ) +{ + return + [ compile $(sources) + : $(reqs) <conditional>@clang-thread-safety + : $(name) ] + ; +} + +rule thread-safety-compile-fail ( sources : reqs * : name ) +{ + return + [ compile-fail $(sources) + : $(reqs) <conditional>@clang-thread-safety + : $(name) ] + ; +} + +rule thread-compile ( sources : reqs * : name ) +{ + return + [ compile $(sources) + : $(reqs) + : $(name) ] + ; +} + +rule windows-cygwin-specific ( properties * ) +{ + if <target-os>windows in $(properties) || <target-os>cygwin in $(properties) + { + return <build>yes ; + } + else + { + return <build>no ; + } +} + +rule generate_self_contained_header_tests +{ + local all_rules ; + local file ; + + if ! [ os.environ BOOST_THREAD_TEST_WITHOUT_SELF_CONTAINED_HEADER_TESTS ] + { + local headers_path = [ path.make $(BOOST_ROOT)/libs/thread/include/boost/thread ] ; + for file in [ path.glob-tree $(headers_path) : *.hpp : detail pthread win32 ] + { + local rel_file = [ path.relative-to $(headers_path) $(file) ] ; + # Note: The test name starts with '~' in order to group these tests in the test report table, preferably at the end. + # All '/' are replaced with '-' because apparently test scripts have a problem with test names containing slashes. + local test_name = [ regex.replace ~hdr/$(rel_file) "/" "-" ] ; + #ECHO $(rel_file) ; + all_rules += [ compile self_contained_header.cpp : <define>"BOOST_THREAD_TEST_HEADER=$(rel_file)" <dependency>$(file) : $(test_name) ] ; + all_rules += [ compile self_contained_header.cpp : <define>"BOOST_THREAD_TEST_HEADER=$(rel_file)" <define>"BOOST_THREAD_TEST_POST_WINDOWS_H" <dependency>$(file) <conditional>@windows-cygwin-specific : $(test_name)-post_winh ] ; + } + } + + #ECHO All rules: $(all_rules) ; + return $(all_rules) ; +} + +{ + test-suite t_threads + : + [ thread-test test_thread.cpp ] + [ thread-test test_thread_id.cpp ] + [ thread-test test_hardware_concurrency.cpp ] + [ thread-test test_physical_concurrency.cpp ] + [ thread-test test_thread_move.cpp ] + [ thread-test test_thread_return_local.cpp ] + [ thread-test test_thread_move_return.cpp ] + [ thread-test test_thread_launching.cpp ] + [ thread-test test_thread_mf.cpp ] + [ thread-test test_thread_exit.cpp ] + [ thread-test test_move_function.cpp ] + [ compile-fail no_implicit_move_from_lvalue_thread.cpp ] + [ compile-fail no_implicit_assign_from_lvalue_thread.cpp ] + [ thread-test test_tss.cpp ] + [ thread-test test_xtime.cpp ] + ; + + test-suite t_sync + : + [ thread-test test_mutex.cpp ] + [ thread-test test_condition_notify_one.cpp ] + [ thread-test test_condition_timed_wait_times_out.cpp ] + [ thread-test test_condition_notify_all.cpp ] + [ thread-test test_condition.cpp ] + [ thread-test test_once.cpp ] + [ thread-run test_barrier.cpp ] + [ thread-run test_barrier_void_fct.cpp ] + [ thread-run test_barrier_size_fct.cpp ] + [ thread-test test_lock_concept.cpp ] + [ thread-test test_generic_locks.cpp ] + [ thread-run test_latch.cpp ] + [ thread-run test_completion_latch.cpp ] + ; + + test-suite t_shared + : + [ thread-test test_shared_mutex.cpp ] + [ thread-test test_shared_mutex_part_2.cpp ] + [ thread-test test_shared_mutex_timed_locks.cpp ] + [ thread-test test_shared_mutex_timed_locks_chrono.cpp ] + #uncomment the following once these works on windows + #[ thread-test test_vhh_shared_mutex.cpp ] + #[ thread-test test_vhh_shared_mutex_part_2.cpp ] + #[ thread-test test_vhh_shared_mutex_timed_locks.cpp ] + ; + + explicit t_futures_too_long ; + test-suite t_futures_too_long + : + [ thread-test test_futures.cpp ] + ; + + + #explicit tickets ; + test-suite tickets + : + [ thread-test test_2309.cpp ] + [ thread-run test_2501.cpp ] + [ thread-test test_2741.cpp ] + [ thread-run test_3628.cpp ] + [ thread-run test_4521.cpp ] + [ thread-run test_4648.cpp ] + [ thread-run test_4882.cpp ] + [ thread-run test_5542_1.cpp ] + [ thread-run test_5542_2.cpp ] + [ thread-run test_5542_3.cpp ] + [ thread-run test_5891.cpp ] + #[ thread-run test_6130.cpp ] + #[ thread-run test_6170.cpp ] + [ thread-run test_6174.cpp ] + #[ thread-run test_7160.cpp ] + [ thread-run test_7328.cpp ] + [ thread-run test_7571.cpp ] + [ thread-run test_9319.cpp ] + #[ thread-run test_9711.cpp ] This is an invalid use of ::then deferred. + [ thread-run test_9856.cpp ] + [ thread-compile test_10963.cpp : : test_10963_c ] + [ thread-run test_10964.cpp ] + [ thread-test test_11053.cpp ] + [ thread-run test_11266.cpp ] + ; + + + explicit oth_tickets ; + test-suite oth_tickets + : + [ thread-run test_5351.cpp ] + [ thread-run test_5502.cpp ] + ; + + + + #explicit ts_conditions ; + test-suite ts_conditions + : + [ thread-compile-fail ./sync/conditions/condition_variable/assign_fail.cpp : : condition_variable__assign_f ] + [ thread-compile-fail ./sync/conditions/condition_variable/copy_fail.cpp : : condition_variable__copy_f ] + [ thread-run2-noit ./sync/conditions/condition_variable/default_pass.cpp : condition_variable__default_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/dtor_pass.cpp : condition_variable__dtor_p ] + [ thread-run2-noit-pthread ./sync/conditions/condition_variable/native_handle_pass.cpp : condition_variable__native_handle_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/wait_pass.cpp : condition_variable__wait_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/wait_for_pass.cpp : condition_variable__wait_for_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/wait_for_pred_pass.cpp : condition_variable__wait_for_pred_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/wait_until_pass.cpp : condition_variable__wait_until_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/wait_until_pred_pass.cpp : condition_variable__wait_until_pred_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/lost_notif_pass.cpp : condition_variable__lost_notif_p ] + + [ thread-compile-fail ./sync/conditions/condition_variable_any/assign_fail.cpp : : condition_variable_any__assign_f ] + [ thread-compile-fail ./sync/conditions/condition_variable_any/copy_fail.cpp : : condition_variable_any__copy_f ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/default_pass.cpp : condition_variable_any__default_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/dtor_pass.cpp : condition_variable_any__dtor_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/wait_for_pass.cpp : condition_variable_any__wait_for_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/wait_for_pred_pass.cpp : condition_variable_any__wait_for_pred_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/wait_until_pass.cpp : condition_variable_any__wait_until_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/wait_until_pred_pass.cpp : condition_variable_any__wait_until_pred_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/lost_notif_pass.cpp : condition_variable_any__lost_notif_p ] + [ thread-run2-noit ./sync/conditions/cv_status/cv_status_pass.cpp : cv_status__cv_status_p ] + [ thread-run2-noit ./sync/conditions/notify_all_at_thread_exit_pass.cpp : notify_all_at_thread_exit_p ] + ; + + #explicit ts_async ; + test-suite ts_async + : + [ thread-run2-noit ./sync/futures/async/async_pass.cpp : async__async_p ] + [ thread-run2-noit ./sync/futures/async/async_executor_pass.cpp : async__async_executor_p ] + ; + + #explicit ts_promise ; + test-suite ts_promise + : + [ thread-compile-fail ./sync/futures/promise/copy_assign_fail.cpp : : promise__copy_assign_f ] + [ thread-compile-fail ./sync/futures/promise/copy_ctor_fail.cpp : : promise__copy_ctor_f ] + [ thread-run2-noit ./sync/futures/promise/alloc_ctor_pass.cpp : promise__alloc_ctor_p ] + [ thread-run2-noit ./sync/futures/promise/default_pass.cpp : promise__default_p ] + [ thread-run2-noit ./sync/futures/promise/dtor_pass.cpp : promise__dtor_p ] + [ thread-run2-noit ./sync/futures/promise/get_future_pass.cpp : promise__get_future_p ] + [ thread-run2-noit ./sync/futures/promise/move_ctor_pass.cpp : promise__move_ctor_p ] + [ thread-run2-noit ./sync/futures/promise/move_assign_pass.cpp : promise__move_asign_p ] + [ thread-run2-noit ./sync/futures/promise/set_exception_pass.cpp : promise__set_exception_p ] + [ thread-run2-noit ./sync/futures/promise/set_lvalue_pass.cpp : promise__set_lvalue_p ] + [ thread-run2-noit ./sync/futures/promise/set_rvalue_pass.cpp : promise__set_rvalue_p ] + [ thread-run2-noit ./sync/futures/promise/set_value_const_pass.cpp : promise__set_value_const_p ] + [ thread-run2-noit ./sync/futures/promise/set_value_void_pass.cpp : promise__set_value_void_p ] + [ thread-run2-noit ./sync/futures/promise/emplace_pass.cpp : promise__emplace_p ] + [ thread-run2-noit ./sync/futures/promise/use_allocator_pass.cpp : promise__use_allocator_p ] + [ thread-run2-noit ./sync/futures/promise/set_exception_at_thread_exit_pass.cpp : promise__set_exception_at_thread_exit_p ] + [ thread-run2-noit ./sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp : promise__set_lvalue_at_thread_exit_p ] + [ thread-run2-noit ./sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp : promise__set_rvalue_at_thread_exit_p ] + [ thread-run2-noit ./sync/futures/promise/set_value_at_thread_exit_const_pass.cpp : promise__set_value_at_thread_exit_const_p ] + [ thread-run2-noit ./sync/futures/promise/set_value_at_thread_exit_void_pass.cpp : promise__set_value_at_thread_exit_void_p ] + ; + + #explicit ts_make_ready_future ; + test-suite ts_make_ready_future + : + [ thread-run2-noit ./sync/futures/make_ready_future_pass.cpp : make_ready_future_p ] + ; + + #explicit ts_future ; + test-suite ts_future + : + [ thread-compile-fail ./sync/futures/future/copy_assign_fail.cpp : : future__copy_assign_f ] + [ thread-compile-fail ./sync/futures/future/copy_ctor_fail.cpp : : future__copy_ctor_f ] + [ thread-run2-noit ./sync/futures/future/default_pass.cpp : future__default_p ] + [ thread-run2-noit ./sync/futures/future/dtor_pass.cpp : future__dtor_p ] + [ thread-run2-noit ./sync/futures/future/get_pass.cpp : future__get_p ] + [ thread-run2-noit ./sync/futures/future/get_or_pass.cpp : future__get_or_p ] + [ thread-run2-noit ./sync/futures/future/move_ctor_pass.cpp : future__move_ctor_p ] + [ thread-run2-noit ./sync/futures/future/move_assign_pass.cpp : future__move_asign_p ] + [ thread-run2-noit ./sync/futures/future/share_pass.cpp : future__share_p ] + [ thread-run2-noit ./sync/futures/future/wait_pass.cpp : future__wait_p ] + [ thread-run2-noit ./sync/futures/future/wait_for_pass.cpp : future__wait_for_p ] + [ thread-run2-noit ./sync/futures/future/wait_until_pass.cpp : future__wait_until_p ] + [ thread-run2-noit ./sync/futures/future/then_pass.cpp : future__then_p ] + [ thread-run2-noit ./sync/futures/future/then_executor_pass.cpp : future__then_executor_p ] + [ thread-run2-noit ./sync/futures/future/async_deferred_then_pass.cpp : future__async_def_then_p ] + [ thread-run2-noit ./sync/futures/future/then_deferred_pass.cpp : future__then_def_p ] + ; + + #explicit ts_shared_future ; + test-suite ts_shared_future + : + [ thread-run2-noit ./sync/futures/shared_future/copy_assign_pass.cpp : shared_future__copy_assign_p ] + [ thread-run2-noit ./sync/futures/shared_future/copy_ctor_pass.cpp : shared_future__copy_ctor_p ] + [ thread-run2-noit ./sync/futures/shared_future/default_pass.cpp : shared_future__default_p ] + [ thread-run2-noit ./sync/futures/shared_future/dtor_pass.cpp : shared_future__dtor_p ] + [ thread-run2-noit ./sync/futures/shared_future/get_pass.cpp : shared_future__get_p ] + [ thread-run2-noit ./sync/futures/shared_future/move_ctor_pass.cpp : shared_future__move_ctor_p ] + [ thread-run2-noit ./sync/futures/shared_future/move_assign_pass.cpp : shared_future__move_asign_p ] + [ thread-run2-noit ./sync/futures/shared_future/wait_pass.cpp : shared_future__wait_p ] + [ thread-run2-noit ./sync/futures/shared_future/wait_for_pass.cpp : shared_future__wait_for_p ] + [ thread-run2-noit ./sync/futures/shared_future/wait_until_pass.cpp : shared_future__wait_until_p ] + [ thread-run2-noit ./sync/futures/shared_future/then_pass.cpp : shared_future__then_p ] + [ thread-run2-noit ./sync/futures/shared_future/then_executor_pass.cpp : shared_future__then_executor_p ] + ; + + #explicit ts_packaged_task ; + test-suite ts_packaged_task + : + [ thread-run2-noit ./sync/futures/packaged_task/alloc_ctor_pass.cpp : packaged_task__alloc_ctor_p ] + [ thread-compile-fail ./sync/futures/packaged_task/copy_assign_fail.cpp : : packaged_task__copy_assign_f ] + [ thread-compile-fail ./sync/futures/packaged_task/copy_ctor_fail.cpp : : packaged_task__copy_ctor_f ] + [ thread-run2-noit ./sync/futures/packaged_task/default_ctor_pass.cpp : packaged_task__default_ctor_p ] + [ thread-run2-noit ./sync/futures/packaged_task/func_ctor_pass.cpp : packaged_task__func_ctor_p ] + [ thread-run2-noit ./sync/futures/packaged_task/dtor_pass.cpp : packaged_task__dtor_p ] + [ thread-run2-noit ./sync/futures/packaged_task/get_future_pass.cpp : packaged_task__get_future_p ] + [ thread-run2-noit ./sync/futures/packaged_task/move_ctor_pass.cpp : packaged_task__move_ctor_p ] + [ thread-run2-noit ./sync/futures/packaged_task/move_assign_pass.cpp : packaged_task__move_asign_p ] + [ thread-run2-noit ./sync/futures/packaged_task/operator_pass.cpp : packaged_task__operator_p ] + [ thread-run2-noit ./sync/futures/packaged_task/reset_pass.cpp : packaged_task__reset_p ] + [ thread-run2-noit ./sync/futures/packaged_task/use_allocator_pass.cpp : packaged_task__use_allocator_p ] + [ thread-run2-noit ./sync/futures/packaged_task/types_pass.cpp : packaged_task__types_p ] + [ thread-run2-noit ./sync/futures/packaged_task/member_swap_pass.cpp : packaged_task__member_swap_p ] + [ thread-run2-noit ./sync/futures/packaged_task/non_member_swap_pass.cpp : packaged_task__non_member_swap_p ] + [ thread-run2-noit ./sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp : packaged_task__make_ready_at_thread_exit_p ] + ; + + + #explicit ts_when_all ; + test-suite ts_when_all + : + [ thread-run2-noit ./sync/futures/when_all/none_pass.cpp : when_all__none_p ] + [ thread-run2-noit ./sync/futures/when_all/one_pass.cpp : when_all__one_p ] + [ thread-run2-noit ./sync/futures/when_all/iterators_pass.cpp : when_all__iterators_p ] + [ thread-run2-noit ./sync/futures/when_all/variadic_pass.cpp : when_all__variadic_p ] + ; + + #explicit ts_when_any ; + test-suite ts_when_any + : + [ thread-run2-noit ./sync/futures/when_any/none_pass.cpp : when_any__none_p ] + [ thread-run2-noit ./sync/futures/when_any/one_pass.cpp : when_any__one_p ] + [ thread-run2-noit ./sync/futures/when_any/iterators_pass.cpp : when_any__iterators_p ] + [ thread-run2-noit ./sync/futures/when_any/variadic_pass.cpp : when_any__variadic_p ] + ; + + #explicit ts_lock_guard ; + test-suite ts_lock_guard + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/lock_guard/copy_assign_fail.cpp : : lock_guard__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/lock_guard/copy_ctor_fail.cpp : : lock_guard__cons__copy_ctor_f ] + [ thread-safety-compile ./sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_pass.cpp : : lock_guard__lock_compile_p ] + [ thread-safety-compile-fail ./sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_fail.cpp : : lock_guard__lock_compile_f ] + [ thread-safety-compile ./sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_pass.cpp : : lock_guard__adopt_lock_compile_p ] + [ thread-safety-compile-fail ./sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_fail.cpp : : lock_guard__adopt_lock_compile_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/adopt_lock_pass.cpp : lock_guard__cons__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/default_pass.cpp : lock_guard__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/types_pass.cpp : lock_guard__types_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/make_lock_guard_pass.cpp : make_lock_guard_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/make_lock_guard_adopt_lock_pass.cpp : make_lock_guard__adopt_lock_p ] + ; + + #explicit ts_unique_lock ; + test-suite ts_unique_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/cons/copy_assign_fail.cpp : : unique_lock__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/cons/copy_ctor_fail.cpp : : unique_lock__cons__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/adopt_lock_pass.cpp : unique_lock__cons__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/default_pass.cpp : unique_lock__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/defer_lock_pass.cpp : unique_lock__cons__defer_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp : unique_lock__cons__duration_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp : unique_lock__cons__move_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp : unique_lock__cons__move_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp : uq_lk_cons_mv_c_upg_lk_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp : uq_lk_cons_mv_c_upg_lk_t_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp : uq_lk_cons_mv_c_upg_lk_f_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp : uq_lk_cons_mv_c_upg_lk_u_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp : unique_lock__cons__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp : unique_lock__cons__time_point_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp : unique_lock__cons__try_to_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/locking/lock_pass.cpp : unique_lock__lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_for_pass.cpp : unique_lock__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_pass.cpp : unique_lock__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_until_pass.cpp : unique_lock__try_lock_until_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/locking/unlock_pass.cpp : unique_lock__unlock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/mod/member_swap_pass.cpp : unique_lock__member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/mod/non_member_swap_pass.cpp : unique_lock__non_member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/mod/release_pass.cpp : unique_lock__release_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/obs/mutex_pass.cpp : unique_lock__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/obs/op_bool_pass.cpp : unique_lock__op_bool_p ] + #[ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/obs/op_int_fail.cpp : : unique_lock__op_int_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/obs/owns_lock_pass.cpp : unique_lock__owns_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/types_pass.cpp : unique_lock__types_p ] + + + ; + + #explicit ts_make_unique_lock ; + test-suite ts_make_unique_lock + : + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_mutex_pass.cpp : make_unique_lock__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_adopt_lock_pass.cpp : make_unique_lock__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_defer_lock_pass.cpp : make_unique_lock__defer_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_try_to_lock_pass.cpp : make_unique_lock__try_to_lock_p ] + + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/make_unique_locks_mutex_pass.cpp : make_unique_locks__mutex_p ] + + ; + + #explicit ts_shared_lock ; + test-suite ts_shared_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock/cons/copy_assign_fail.cpp : : shared_lock__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock/cons/copy_ctor_fail.cpp : : shared_lock__cons__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/adopt_lock_pass.cpp : shared_lock__cons__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp : shared_lock__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp : shared_lock__cons__defer_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp : shared_lock__cons__duration_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp : shared_lock__cons__move_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp : shared_lock__cons__move_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp : sh_lock_cons_move_ctor_unq_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp : sh_lock_cons_move_ctor_upg_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp : shared_lock__cons__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp : shared_lock__cons__time_point_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp : shared_lock__cons__try_to_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/locking/lock_pass.cpp : shared_lock__lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_for_pass.cpp : shared_lock__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_pass.cpp : shared_lock__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_until_pass.cpp : shared_lock__try_lock_until_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/locking/unlock_pass.cpp : shared_lock__unlock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/mod/member_swap_pass.cpp : shared_lock__member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/mod/non_member_swap_pass.cpp : shared_lock__non_member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/mod/release_pass.cpp : shared_lock__release_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/obs/mutex_pass.cpp : shared_lock__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/obs/op_bool_pass.cpp : shared_lock__op_bool_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/obs/owns_lock_pass.cpp : shared_lock__owns_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/types_pass.cpp : shared_lock__types_p ] + + #[ thread-run2-h ./sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp : shared_lock__cons__default_p ] + #[ thread-run2-h ./sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp : shared_lock__cons__defer_lock_p ] + + ; + + #explicit ts_upgrade_lock ; + test-suite ts_upgrade_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/upgrade_lock/cons/copy_assign_fail.cpp : : upgrade_lock__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/upgrade_lock/cons/copy_ctor_fail.cpp : : upgrade_lock__cons__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/adopt_lock_pass.cpp : upgrade_lock__cons__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/default_pass.cpp : upgrade_lock__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/defer_lock_pass.cpp : upgrade_lock__cons__defer_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp : upgrade_lock__cons__duration_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp : upgrade_lock__cons__move_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp : upgrade_lock__cons__move_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp : upg_lock_cons_mv_ctor_uq_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp : upgrade_lock__cons__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp : upgrade_lock__cons__time_point_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp : upgrade_lock__cons__try_to_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/locking/lock_pass.cpp : upgrade_lock__lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_for_pass.cpp : upgrade_lock__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_pass.cpp : upgrade_lock__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_until_pass.cpp : upgrade_lock__try_lock_until_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/locking/unlock_pass.cpp : upgrade_lock__unlock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/mod/member_swap_pass.cpp : upgrade_lock__member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/mod/non_member_swap_pass.cpp : upgrade_lock__non_member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/mod/release_pass.cpp : upgrade_lock__release_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/obs/mutex_pass.cpp : upgrade_lock__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/obs/op_bool_pass.cpp : upgrade_lock__op_bool_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/obs/owns_lock_pass.cpp : upgrade_lock__owns_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/types_pass.cpp : upgrade_lock__types_p ] + ; + + #explicit ts_strict_lock ; + test-suite ts_strict_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/strict_lock/copy_assign_fail.cpp : : strict_lock__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/strict_lock/copy_ctor_fail.cpp : : strict_lock__cons__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/default_pass.cpp : strict_lock__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/owns_lock_pass.cpp : strict_lock__owns_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/types_pass.cpp : strict_lock__types_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp : make_strict_lock_p ] + ; + + #explicit ts_nested_strict_lock ; + test-suite ts_nested_strict_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp : : nested_strict_lock_cons_copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp : : nested_strict_lock_cons_copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/default_pass.cpp : nested_strict_lock__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/owns_lock_pass.cpp : nested_strict_lock__owns_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/types_pass.cpp : nested_strict_lock__types_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp : make_nested_strict_lock_p ] + ; + + + #explicit ts_once ; + test-suite ts_once + : + #[ thread-compile-fail ./sync/mutual_exclusion/once/once_flag/assign_fail.cpp : : once_flag__assign_f ] + #[ thread-compile-fail ./sync/mutual_exclusion/once/once_flag/copy_fail.cpp : : once_flag__copy_f ] + #[ thread-run2-noit ./sync/mutual_exclusion/once/once_flag/default_pass.cpp : once_flag__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/once/call_once/call_once_pass.cpp : call_once_p ] + ; + + #explicit ts_mutex ; + test-suite ts_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/mutex/assign_fail.cpp : : mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/mutex/copy_fail.cpp : : mutex__copy_f ] + [ thread-safety-compile ./sync/mutual_exclusion/mutex/lock_compile_pass.cpp : : mutex__lock_compile_p ] + [ thread-safety-compile-fail ./sync/mutual_exclusion/mutex/lock_compile_fail.cpp : : mutex__lock_compile_f ] + # https://bugs.llvm.org/show_bug.cgi?id=32954 + # http://clang-developers.42468.n3.nabble.com/thread-safety-warnings-specifically-try-acquire-capability-td4059337.html + #[ thread-safety-compile ./sync/mutual_exclusion/mutex/try_lock_compile_pass.cpp : : mutex__try_lock_compile_p ] + [ thread-safety-compile-fail ./sync/mutual_exclusion/mutex/try_lock_compile_fail.cpp : : mutex__try_lock_compile_f ] + [ thread-run2-noit ./sync/mutual_exclusion/mutex/default_pass.cpp : mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/mutex/lock_pass.cpp : mutex__lock_p ] + [ thread-run2-noit-pthread ./sync/mutual_exclusion/mutex/native_handle_pass.cpp : mutex__native_handle_p ] + [ thread-run2-noit ./sync/mutual_exclusion/mutex/try_lock_pass.cpp : mutex__try_lock_p ] + ; + + #explicit ts_recursive_mutex ; + test-suite ts_recursive_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/recursive_mutex/assign_fail.cpp : : recursive_mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/recursive_mutex/copy_fail.cpp : : recursive_mutex__copy_f ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_mutex/default_pass.cpp : recursive_mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_mutex/lock_pass.cpp : recursive_mutex__lock_p ] + [ thread-run2-noit-pthread ./sync/mutual_exclusion/recursive_mutex/native_handle_pass.cpp : recursive_mutex__native_handle_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_mutex/try_lock_pass.cpp : recursive_mutex__try_lock_p ] + ; + + #explicit ts_recursive_timed_mutex ; + test-suite ts_recursive_timed_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/recursive_timed_mutex/assign_fail.cpp : : recursive_timed_mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp : : recursive_timed_mutex__copy_f ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp : recursive_timed_mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp : recursive_timed_mutex__lock_p ] + [ thread-run2-noit-pthread ./sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp : rec_timed_mutex_native_handle_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp : rec_timed_mutex_try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp : recursive_timed_mutex__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp : rec_timed_mutex_try_lock_until_p ] + ; + + #explicit ts_timed_mutex ; + test-suite ts_timed_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/timed_mutex/assign_fail.cpp : : timed_mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/timed_mutex/copy_fail.cpp : : timed_mutex__copy_f ] + [ thread-run2-noit ./sync/mutual_exclusion/timed_mutex/default_pass.cpp : timed_mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/timed_mutex/lock_pass.cpp : timed_mutex__lock_p ] + [ thread-run2-noit-pthread ./sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp : timed_mutex__native_handle_p ] + [ thread-run2-noit ./sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp : timed_mutex__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp : timed_mutex__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp : timed_mutex__try_lock_until_p ] + ; + + #explicit ts_shared_mutex ; + test-suite ts_shared_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/shared_mutex/assign_fail.cpp : : shared_mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/shared_mutex/copy_fail.cpp : : shared_mutex__copy_f ] + [ thread-run2-noit ./sync/mutual_exclusion/shared_mutex/default_pass.cpp : shared_mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/shared_mutex/lock_pass.cpp : shared_mutex__lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp : shared_mutex__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp : shared_mutex__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp : shared_mutex__try_lock_until_p ] + + #[ thread-run2-h ./sync/mutual_exclusion/shared_mutex/default_pass.cpp : shared_mutex__default_p ] + ; + + #explicit ts_null_mutex ; + test-suite ts_null_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/null_mutex/assign_fail.cpp : : null_mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/null_mutex/copy_fail.cpp : : null_mutex__copy_f ] + [ thread-run2-noit ./sync/mutual_exclusion/null_mutex/default_pass.cpp : null_mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/null_mutex/lock_pass.cpp : null_mutex__lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/null_mutex/try_lock_for_pass.cpp : null_mutex__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/null_mutex/try_lock_pass.cpp : null_mutex__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/null_mutex/try_lock_until_pass.cpp : null_mutex__try_lock_until_p ] + ; + + test-suite ts_sync_queue + : + [ thread-run2-noit ./sync/mutual_exclusion/sync_queue/single_thread_pass.cpp : sync_queue__single_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp : sync_queue__multi_thread_p ] + ; + + test-suite ts_sync_deque + : + [ thread-run2-noit ./sync/mutual_exclusion/sync_deque/single_thread_pass.cpp : sync_deque__single_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp : sync_deque__multi_thread_p ] + ; + + test-suite ts_sync_bounded_queue + : + [ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp : sync_bounded_q_single_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp : sync_bounded_q_multi_thread_p ] + ; + + test-suite ts_sync_pq + : + [ thread-run2-noit ./sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp : sync_pq_single_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp : sync_pq_multi_thread_p ] + ; + + test-suite ts_sync_tq + : + [ thread-run2-noit ./sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp : sync_tq_single_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_pq/tq_multi_thread_pass.cpp : sync_tq_multi_thread_p ] + ; + + test-suite ts_scheduler + : + [ thread-run2-noit ./test_scheduled_tp.cpp : test_scheduled_tp_p ] + [ thread-run2-noit ./test_scheduling_adaptor.cpp : test_scheduling_adaptor_p ] + [ thread-run2-noit ./test_scheduler.cpp : test_scheduler_p ] + ; + + test-suite ts_queue_views + : + [ thread-run2-noit ./sync/mutual_exclusion/queue_views/single_thread_pass.cpp : queue_views__single_thread_p ] + #[ thread-run2-noit ./sync/mutual_exclusion/queue_views/multi_thread_pass.cpp : queue_views__multi_thread_p ] + ; + + test-suite ts_deque_views + : + [ thread-run2-noit ./sync/mutual_exclusion/deque_views/single_thread_pass.cpp : deque_views__single_thread_p ] + #[ thread-run2-noit ./sync/mutual_exclusion/deque_views/multi_thread_pass.cpp : deque_views__multi_thread_p ] + ; + + #explicit ts_this_thread ; + test-suite ts_this_thread + : + [ thread-run2-noit ./threads/this_thread/get_id/get_id_pass.cpp : this_thread__get_id_p ] + [ thread-run2-noit ./threads/this_thread/sleep_for/sleep_for_pass.cpp : this_thread__sleep_for_p ] + [ thread-run2-noit ./threads/this_thread/sleep_until/sleep_until_pass.cpp : this_thread__sleep_until_p ] + ; + + #explicit ts_thread ; + test-suite ts_thread + : + [ thread-compile-fail ./threads/thread/assign/copy_fail.cpp : : thread__assign__copy_f ] + [ thread-run2-noit ./threads/thread/assign/move_pass.cpp : thread__assign__move_p ] + [ thread-compile-fail ./threads/thread/constr/copy_fail.cpp : : thread__constr__copy_f ] + [ thread-run2-noit ./threads/thread/constr/default_pass.cpp : thread__constr__default_p ] + [ thread-run-lib2 ./threads/thread/constr/lambda_pass.cpp : thread__constr__lambda_p ] + [ thread-run-lib2 ./threads/thread/constr/F_pass.cpp : thread__constr__F_p ] + [ thread-run-lib2 ./threads/thread/constr/FArgs_pass.cpp : thread__constr__FArgs_p ] + [ thread-run2-noit ./threads/thread/constr/Frvalue_pass.cpp : thread__constr__Frvalue_p ] + [ thread-run2-noit ./threads/thread/constr/FrvalueArgs_pass.cpp : thread__constr__FrvalueArgs_p ] + [ thread-run2-noit ./threads/thread/constr/move_pass.cpp : thread__constr__move_p ] + [ thread-run2-noit ./threads/thread/destr/dtor_pass.cpp : thread__destr__dtor_p ] + [ thread-run2-noit ./threads/thread/id/hash_pass.cpp : thread__id__hash_p ] + [ thread-run2-noit ./threads/thread/members/detach_pass.cpp : thread__detach_p ] + [ thread-run2-noit ./threads/thread/members/get_id_pass.cpp : thread__get_id_p ] + [ thread-run2-noit ./threads/thread/members/join_pass.cpp : thread__join_p ] + [ thread-run2-noit ./threads/thread/members/try_join_until_pass.cpp : thread__join_until_p ] + [ thread-run2-noit ./threads/thread/members/try_join_for_pass.cpp : thread__join_for_p ] + [ thread-run2-noit ./threads/thread/members/joinable_pass.cpp : thread__joinable_p ] + [ thread-run2-noit ./threads/thread/members/native_handle_pass.cpp : thread__native_handle_p ] + [ thread-run2-noit ./threads/thread/members/swap_pass.cpp : thread__swap_p ] + [ thread-run2-noit ./threads/thread/non_members/swap_pass.cpp : swap_threads_p ] + [ thread-run2-noit ./threads/thread/static/hardware_concurrency_pass.cpp : thread__hardware_concurrency_p ] + ; + + #explicit ts_container ; + test-suite ts_container + : + [ thread-run2-noit ./threads/container/thread_vector_pass.cpp : container__thread_vector_p ] + [ thread-run2-noit ./threads/container/thread_ptr_list_pass.cpp : container__thread_ptr_list_p ] + ; + + explicit ts_examples_too_long ; + test-suite ts_examples_too_long + : + [ thread-run2 ../example/shared_mutex.cpp : ex_shared_mutex ] + ; + + #explicit ts_examples ; + test-suite ts_examples + : + [ thread-run2-noit ../example/monitor.cpp : ex_monitor ] + [ thread-compile ../example/starvephil.cpp : : ex_starvephil ] + [ thread-run2 ../example/tennis.cpp : ex_tennis ] + [ thread-compile ../example/condition.cpp : : ex_condition ] + [ thread-run2-noit ../example/mutex.cpp : ex_mutex ] + [ thread-run2-noit ../example/once.cpp : ex_once ] + [ thread-run2-noit ../example/recursive_mutex.cpp : ex_recursive_mutex ] + [ thread-run2-noit ../example/thread.cpp : ex_thread ] + [ thread-run2-noit ../example/thread_group.cpp : ex_thread_group ] + [ thread-run2-noit ../example/tss.cpp : ex_tss ] + [ thread-run2 ../example/xtime.cpp : ex_xtime ] + [ thread-run2 ../example/shared_monitor.cpp : ex_shared_monitor ] + #[ thread-run ../example/vhh_shared_monitor.cpp ] + #[ thread-run ../example/vhh_shared_mutex.cpp ] + [ thread-run2 ../example/make_future.cpp : ex_make_future ] + [ thread-run2 ../example/future_then.cpp : ex_future_then ] + [ thread-run2 ../example/future_fallback_to.cpp : ex_future_fallback_to ] + [ thread-run2 ../example/future_unwrap.cpp : ex_future_unwrap ] + [ thread-run2-noit ../example/synchronized_value.cpp : ex_synchronized_value ] + [ thread-run2-noit ../example/synchronized_person.cpp : ex_synchronized_person ] + [ thread-run2-noit ../example/thread_guard.cpp : ex_thread_guard ] + [ thread-run2-noit ../example/std_thread_guard.cpp : ex_std_thread_guard : <toolset>gcc-4.8:<build>no ] + [ thread-run2-noit ../example/scoped_thread.cpp : ex_scoped_thread ] + [ thread-run2-noit ../example/std_scoped_thread.cpp : ex_std_scoped_thread : <toolset>gcc-4.8:<build>no ] + [ thread-run2-noit ../example/strict_lock.cpp : ex_strict_lock ] + [ thread-run2-noit ../example/ba_externallly_locked.cpp : ex_ba_externallly_locked ] + [ thread-run2 ../example/producer_consumer_bounded.cpp : ex_producer_consumer_bounded ] + [ thread-run2 ../example/producer_consumer.cpp : ex_producer_consumer ] + [ thread-run2 ../example/producer_consumer2.cpp : ex_producer_consumer2 ] + [ thread-run2 ../example/not_interleaved.cpp : ex_not_interleaved ] + [ thread-run2 ../example/lambda_future.cpp : ex_lambda_future ] + [ thread-run2 ../example/not_interleaved2.cpp : ex_not_interleaved2 ] + [ thread-run2 ../example/thread_pool.cpp : ex_thread_pool ] + [ thread-run2 ../example/user_scheduler.cpp : ex_user_scheduler ] + [ thread-run2 ../example/executor.cpp : ex_executor ] + [ thread-run2 ../example/generic_executor_ref.cpp : ex_generic_executor_ref ] + [ thread-run2 ../example/serial_executor.cpp : ex_serial_executor ] + #[ thread-run2 ../example/serial_executor_cont.cpp : ex_serial_executor_cont ] + [ thread-run2 ../example/future_when_all.cpp : ex_future_when_all ] + [ thread-run2 ../example/parallel_accumulate.cpp : ex_parallel_accumulate ] + [ thread-run2 ../example/parallel_quick_sort.cpp : ex_parallel_quick_sort ] + [ thread-run2 ../example/with_lock_guard.cpp : ex_with_lock_guard ] + [ thread-run2 ../example/fib_task_region.cpp : ex_fib_task_region ] + ; + + #explicit ts_shared_upwards ; + test-suite ts_shared_upwards + : + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_try_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_until_p ] + + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp : upg_lock_cons_move_ctor_sh_lock_try_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp : upg_lock_cons_move_ctor_sh_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp : upg_lock_cons_move_ctor_sh_lock_untl_p ] + ; + + + #explicit ts_shared_lock_guard ; + test-suite ts_shared_lock_guard + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock_guard/copy_assign_fail.cpp : : shared_lock_guard__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock_guard/copy_ctor_fail.cpp : : shared_lock_guard__cons__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock_guard/adopt_lock_pass.cpp : shared_lock_guard__cons__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock_guard/default_pass.cpp : shared_lock_guard__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock_guard/types_pass.cpp : shared_lock_guard__types_p ] + ; + + #explicit ts_reverse_lock ; + test-suite ts_reverse_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/reverse_lock/copy_assign_fail.cpp : : reverse_lock__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/reverse_lock/copy_ctor_fail.cpp : : reverse_lock__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/reverse_lock/unique_lock_ctor_pass.cpp : reverse_lock__unique_lock_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp : reverse_lock__types_p ] + ; + + + #explicit ts_synchronized_value ; + test-suite ts_synchronized_value + : + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/copy_assign_pass.cpp : synchronized_value__copy_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/copy_ctor_pass.cpp : synchronized_value__copy_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/copy_T_assign_pass.cpp : synchronized_value__copy_T_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/copy_T_ctor_pass.cpp : synchronized_value__copy_T_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/default_ctor_pass.cpp : synchronized_value__default_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/indirect_pass.cpp : synchronized_value__indirect_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/move_assign_pass.cpp : synchronized_value__move_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/move_ctor_pass.cpp : synchronized_value__move_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/move_T_assign_pass.cpp : synchronized_value__move_T_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/move_T_ctor_pass.cpp : synchronized_value__move_T_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/swap_pass.cpp : synchronized_value__swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/swap_T_pass.cpp : synchronized_value__swap_T_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/synchronize_pass.cpp : synchronized_value__synchronize_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/call_pass.cpp : synchronized_value__call_p ] + + ; + + + test-suite ts_with_lock_guard + : + [ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_simple.cpp : with_lock_guard_simple_p ] + [ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp : with_lock_guard_bind_p ] + [ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_move.cpp : with_lock_guard_move_p ] + [ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_lambda.cpp : with_lock_guard_lambda_p ] + ; + + explicit ts_invoke ; + test-suite ts_invoke + : + [ thread-run2-noit ./functional/invoke/invoke_int_0_pass.cpp : invoke_int_0_p ] + [ thread-run2-noit ./functional/invoke/invoke_lvalue_pass.cpp : invoke_lvalue_p ] + [ thread-run2-noit ./functional/invoke/invoke_rvalue_pass.cpp : invoke_rvalue_p ] + ; + + explicit ts_invoker ; + test-suite ts_invoker + : + [ thread-run2-noit ./functional/invoker/invoker_int_0_pass.cpp : invoker_int_0_p ] + [ thread-run2-noit ./functional/invoker/invoker_lvalue_pass.cpp : invoker_lvalue_p ] + [ thread-run2-noit ./functional/invoker/invoker_rvalue_pass.cpp : invoker_rvalue_p ] + ; + + + + explicit ts_more ; + test-suite ts_more + : + [ thread-run test_7666.cpp ] + [ thread-run test_7720.cpp ] + [ thread-run test_7755.cpp ] + [ thread-run test_8455.cpp ] + [ thread-run test_8508.cpp ] + #[ thread-run test_8557.cpp ] + [ thread-run test_8586.cpp ] + [ thread-run test_8943.cpp ] + [ thread-run test_8960.cpp ] + [ thread-run test_9079_a.cpp ] + [ thread-run test_9079_b.cpp ] + [ thread-run test_9192.cpp ] + #[ thread-run test_9303.cpp ] + #[ thread-run test_9720.cpp ] + #[ thread-run test_10125.cpp ] + #[ thread-run test_10128.cpp ] + #[ thread-run test_10340.cpp ] + ; + + explicit ts_more_cpp11 ; + test-suite ts_more_cpp11 + : + [ thread-run test_8596.cpp ] + [ thread-run test_8600.cpp ] + ; + + explicit perf ; + test-suite perf + : + #[ thread-run ../example/perf_condition_variable.cpp ] + #[ thread-run ../example/perf_shared_mutex.cpp ] + ; + + + #explicit ts_exception_list ; + test-suite ts_exception_list + : + [ thread-run2-noit ./experimental/parallel/v1/exception_list_pass.cpp : exception_list_p ] + ; + + #explicit ts_task_region ; + test-suite ts_task_region + : + [ thread-run2-noit ./experimental/parallel/v2/task_region_pass.cpp : task_region_p ] + ; + + explicit ts_other ; + test-suite ts_other + : + [ thread-run2 ../example/this_executor.cpp : ex_this_executor ] + [ thread-run2 ../example/default_executor.cpp : ex_default_executor ] + ; + + explicit ts_ ; + test-suite ts_ + : + #[ thread-run test_11256.cpp ] + #[ thread-run test_11256.cpp ] + #[ thread-run test_11499.cpp ] + #[ thread-run test_11611.cpp ] + #[ thread-run test_11818.cpp ] + #[ thread-run test_11796.cpp ] + #[ thread-run test_12293.cpp ] + #[ thread-run test_12949.cpp ] + #[ thread-run test_13480b.cpp ] + [ thread-run test_13561.cpp ] + + ; + + explicit test_time_jumps_1_obj ; + obj test_time_jumps_1_obj : test_time_jumps.cpp : + # BOOST_THREAD_USES_MOVE is required to prevent ambiguity between the two definitions + # of boost::move when using sync_priority_queue/sync_timed_queue with POD data types. + <define>BOOST_THREAD_USES_MOVE + <define>BOOST_THREAD_PROVIDES_FUTURE + ; + + explicit test_time_jumps_2_obj ; + obj test_time_jumps_2_obj : test_time_jumps.cpp : + # BOOST_THREAD_USES_MOVE is required to prevent ambiguity between the two definitions + # of boost::move when using sync_priority_queue/sync_timed_queue with POD data types. + <define>BOOST_THREAD_USES_MOVE + <define>BOOST_THREAD_PROVIDES_FUTURE + <define>BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + ; + + explicit test_time_jumps_3_obj ; + obj test_time_jumps_3_obj : test_time_jumps.cpp : + # BOOST_THREAD_USES_MOVE is required to prevent ambiguity between the two definitions + # of boost::move when using sync_priority_queue/sync_timed_queue with POD data types. + <define>BOOST_THREAD_USES_MOVE + <define>BOOST_THREAD_PROVIDES_FUTURE + <define>BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + <define>BOOST_THREAD_V2_SHARED_MUTEX + ; + + explicit test_time_jumps ; + test-suite test_time_jumps + : + [ exe test_time_jumps_1 : test_time_jumps_1_obj ../build//boost_thread ] + [ exe test_time_jumps_2 : test_time_jumps_2_obj ../build//boost_thread ] + [ exe test_time_jumps_3 : test_time_jumps_3_obj ../build//boost_thread ] + ; + + test-suite test_self_contained_headers : [ generate_self_contained_header_tests ] ; +} diff --git a/src/boost/libs/thread/test/condition_test_common.hpp b/src/boost/libs/thread/test/condition_test_common.hpp new file mode 100644 index 000000000..4aa114e05 --- /dev/null +++ b/src/boost/libs/thread/test/condition_test_common.hpp @@ -0,0 +1,97 @@ +#ifndef CONDITION_TEST_COMMON_HPP +#define CONDITION_TEST_COMMON_HPP +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread_time.hpp> + +unsigned const timeout_seconds=5; + +struct wait_for_flag +{ + boost::mutex mutex; + boost::condition_variable cond_var; + bool flag; + unsigned woken; + + wait_for_flag(): + flag(false),woken(0) + {} + + struct check_flag + { + bool const& flag; + + check_flag(bool const& flag_): + flag(flag_) + {} + + bool operator()() const + { + return flag; + } + private: + void operator=(check_flag&); + }; + + + void wait_without_predicate() + { + boost::unique_lock<boost::mutex> lock(mutex); + while(!flag) + { + cond_var.wait(lock); + } + ++woken; + } + + void wait_with_predicate() + { + boost::unique_lock<boost::mutex> lock(mutex); + cond_var.wait(lock,check_flag(flag)); + if(flag) + { + ++woken; + } + } + + void timed_wait_without_predicate() + { + boost::system_time const timeout=boost::get_system_time()+boost::posix_time::seconds(timeout_seconds); + + boost::unique_lock<boost::mutex> lock(mutex); + while(!flag) + { + if(!cond_var.timed_wait(lock,timeout)) + { + return; + } + } + ++woken; + } + + void timed_wait_with_predicate() + { + boost::system_time const timeout=boost::get_system_time()+boost::posix_time::seconds(timeout_seconds); + boost::unique_lock<boost::mutex> lock(mutex); + if(cond_var.timed_wait(lock,timeout,check_flag(flag)) && flag) + { + ++woken; + } + } + void relative_timed_wait_with_predicate() + { + boost::unique_lock<boost::mutex> lock(mutex); + if(cond_var.timed_wait(lock,boost::posix_time::seconds(timeout_seconds),check_flag(flag)) && flag) + { + ++woken; + } + } +}; + + +#endif diff --git a/src/boost/libs/thread/test/experimental/parallel/v1/exception_list_pass.cpp b/src/boost/libs/thread/test/experimental/parallel/v1/exception_list_pass.cpp new file mode 100644 index 000000000..de79412ae --- /dev/null +++ b/src/boost/libs/thread/test/experimental/parallel/v1/exception_list_pass.cpp @@ -0,0 +1,23 @@ +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/experimental/parallel/v1/exception_list.hpp> + + +#define BOOST_THREAD_VERSION 4 +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include <boost/thread/experimental/parallel/v1/exception_list.hpp> + +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/experimental/parallel/v2/task_region_pass.cpp b/src/boost/libs/thread/test/experimental/parallel/v2/task_region_pass.cpp new file mode 100644 index 000000000..814ef28e5 --- /dev/null +++ b/src/boost/libs/thread/test/experimental/parallel/v2/task_region_pass.cpp @@ -0,0 +1,295 @@ +// Copyright (C) 2014-2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/experimental/parallel/v1/exception_list.hpp> + + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include <boost/thread/experimental/parallel/v2/task_region.hpp> +#include <string> + +#include <boost/detail/lightweight_test.hpp> + +#if ! defined BOOST_NO_CXX11_LAMBDAS && defined(BOOST_THREAD_PROVIDES_INVOKE) +using boost::experimental::parallel::v2::task_region; +using boost::experimental::parallel::v2::task_region_handle; +using boost::experimental::parallel::v1::exception_list; + +void run_no_exception() +{ + std::string s("test"); + bool parent_flag = false; + bool task1_flag = false; + bool task2_flag = false; + bool task21_flag = false; + bool task3_flag = false; + task_region([&](task_region_handle& trh) + { + parent_flag = true; + trh.run([&]() + { + task1_flag = true; + std::cout << "task1: " << s << std::endl; + }); + trh.run([&]() + { + task2_flag = true; + std::cout << "task2" << std::endl; + task_region([&](task_region_handle& trh) + { + trh.run([&]() + { + task21_flag = true; + std::cout << "task2.1" << std::endl; + }); + }); + }); + int i = 0, j = 10, k = 20; + trh.run([=, &task3_flag]() + { + task3_flag = true; + std::cout << "task3: " << i << " " << j << " " << k << std::endl; + }); + std::cout << "parent" << std::endl; + }); + BOOST_TEST(parent_flag); + BOOST_TEST(task1_flag); + BOOST_TEST(task2_flag); + BOOST_TEST(task21_flag); + BOOST_TEST(task3_flag); +} + +void run_no_exception_wait() +{ + std::string s("test"); + bool parent_flag = false; + bool wait_flag = false; + bool task1_flag = false; + bool task2_flag = false; + bool task21_flag = false; + bool task3_flag = false; + task_region([&](task_region_handle& trh) + { + parent_flag = true; + trh.run([&]() + { + task1_flag = true; + std::cout << "task1: " << s << std::endl; + }); + trh.run([&]() + { + task2_flag = true; + std::cout << "task2" << std::endl; + task_region([&](task_region_handle& trh) + { + trh.run([&]() + { + task21_flag = true; + std::cout << "task2.1" << std::endl; + }); + }); + }); + int i = 0, j = 10, k = 20; + trh.run([=, &task3_flag]() + { + task3_flag = true; + std::cout << "task3: " << i << " " << j << " " << k << std::endl; + }); + std::cout << "before" << std::endl; + trh.wait(); + wait_flag = true; + std::cout << "parent" << std::endl; + }); + BOOST_TEST(parent_flag); + BOOST_TEST(wait_flag); + BOOST_TEST(task1_flag); + BOOST_TEST(task2_flag); + BOOST_TEST(task21_flag); + BOOST_TEST(task3_flag); +} + +void run_exception_1() +{ + try + { + task_region([](task_region_handle& trh) + { + trh.run([]() + { + std::cout << "task1" << std::endl; + throw 1; + }); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + trh.run([]() + { + std::cout << "task3" << std::endl; + }); +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + BOOST_TEST(false); +#endif + }); + BOOST_TEST(false); + } + catch (exception_list const& e) + { + BOOST_TEST_EQ(e.size(), 1u); + } + catch (...) + { + BOOST_TEST(false); + } +} + +void run_exception() +{ + try + { + task_region([](task_region_handle& trh) + { + trh.run([]() + { + std::cout << "task1" << std::endl; + throw 1; + }); + trh.run([]() + { + std::cout << "task2" << std::endl; + throw 2; + }); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + trh.run([]() + { + std::cout << "task3" << std::endl; + throw 3; + }); + std::cout << "parent" << std::endl; + throw 100; + }); + BOOST_TEST(false); + } + catch (exception_list const& el) + { + BOOST_TEST(el.size() >= 1u); + for (boost::exception_ptr const& e: el) + { + try { + boost::rethrow_exception(e); + } + catch (boost::exception&) + { + BOOST_TEST(true); + } + catch (int i) // this doesn't works yet + { + BOOST_TEST((i == 1) || (i == 2) || (i == 3)); + } + catch (...) + { + BOOST_TEST(false); + } + } + } + catch (...) + { + BOOST_TEST(false); + } +} + + +void run_nested_exception() +{ + std::string s("test"); + bool parent_flag = false; + bool task1_flag = false; + bool task2_flag = false; + bool task21_flag = false; + bool task3_flag = false; + try + { + task_region([&](task_region_handle& trh) + { + parent_flag = true; + trh.run([&]() + { + task1_flag = true; + std::cout << "task1: " << s << std::endl; + }); + trh.run([&]() + { + task2_flag = true; + std::cout << "task2" << std::endl; + task_region([&](task_region_handle& trh) + { + trh.run([&]() + { + task21_flag = true; + std::cout << "task2.1" << std::endl; + throw 21; + }); + }); + }); + int i = 0, j = 10, k = 20; + trh.run([=, &task3_flag]() + { + task3_flag = true; + std::cout << "task3: " << i << " " << j << " " << k << std::endl; + }); + std::cout << "parent" << std::endl; + }); + } + catch (exception_list const& el) + { + BOOST_TEST(el.size() == 1u); + for (boost::exception_ptr const& e: el) + { + try { + boost::rethrow_exception(e); + } + catch (int i) // this doesn't works yet + { + BOOST_TEST_EQ(i, 21); + } + catch (boost::exception&) + { + BOOST_TEST(true); + } + catch (...) + { + BOOST_TEST(false); + } + } + } + catch (...) + { + BOOST_TEST(false); + } + BOOST_TEST(parent_flag); + BOOST_TEST(task1_flag); + BOOST_TEST(task2_flag); + BOOST_TEST(task21_flag); +} + + +int main() +{ + run_no_exception(); + run_no_exception_wait(); + run_exception(); + run_exception_1(); + run_nested_exception(); + return boost::report_errors(); +} +#else +int main() +{ + return boost::report_errors(); +} +#endif diff --git a/src/boost/libs/thread/test/functional/invoke/invoke_int_0_pass.cpp b/src/boost/libs/thread/test/functional/invoke/invoke_int_0_pass.cpp new file mode 100644 index 000000000..fa1f67543 --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoke/invoke_int_0_pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/detail/invoke.hpp> + +#include <boost/thread/detail/invoke.hpp> +#include <boost/detail/lightweight_test.hpp> + +int f() +{ + return 1; +} + +struct A_int_0 +{ + A_int_0() + { + } + int operator()() + { + return 4; + } + int operator()() const + { + return 5; + } +}; + + +int main() +{ + const A_int_0 ca; + A_int_0 a; + +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST_EQ(boost::detail::invoke(f), 1); + BOOST_TEST_EQ(boost::detail::invoke(&f), 1); + BOOST_TEST_EQ(boost::detail::invoke(A_int_0()), 4); + BOOST_TEST_EQ(boost::detail::invoke(a), 4); + BOOST_TEST_EQ(boost::detail::invoke(ca), 5); +#endif + + BOOST_TEST_EQ(boost::detail::invoke<int>(f), 1); + BOOST_TEST_EQ(boost::detail::invoke<int>(&f), 1); + BOOST_TEST_EQ(A_int_0()(), 4); +#if defined BOOST_THREAD_PROVIDES_INVOKE || ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + BOOST_TEST_EQ(boost::detail::invoke<int>(A_int_0()), 4); +#else + //BOOST_TEST_EQ(boost::detail::invoke<int>(A_int_0()), 5); +#endif + BOOST_TEST_EQ(a(), 4); + BOOST_TEST_EQ(boost::detail::invoke<int>(a), 4); + BOOST_TEST_EQ(ca(), 5); + BOOST_TEST_EQ(boost::detail::invoke<int>(ca), 5); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/functional/invoke/invoke_lvalue_pass.cpp b/src/boost/libs/thread/test/functional/invoke/invoke_lvalue_pass.cpp new file mode 100644 index 000000000..154953d89 --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoke/invoke_lvalue_pass.cpp @@ -0,0 +1,336 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +// <boost/thread/detail/invoke.hpp> + +#include <boost/thread/detail/invoke.hpp> +#include <boost/detail/lightweight_test.hpp> + +int count = 0; + +// 1 arg, return void + +void f_void_1(int i) +{ + count += i; +} + +struct A_void_1 +{ + void operator()(int i) + { + count += i; + } + + void mem1() {++count;} + void mem2() const {count += 2;} +}; + +void +test_void_1() +{ + int save_count = count; + // function +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + int i = 2; + boost::detail::invoke(f_void_1, i); + BOOST_TEST(count == save_count + 2); + save_count = count; + } +#endif + { + int i = 2; + boost::detail::invoke<void>(f_void_1, i); + BOOST_TEST(count == save_count + 2); + save_count = count; + } + // function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoke(fp, i); + BOOST_TEST(count == save_count+3); + save_count = count; + } +#endif + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoke<void>(fp, i); + BOOST_TEST(count == save_count+3); + save_count = count; + } +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoke(fp, i); + BOOST_TEST(count == save_count+3); + save_count = count; + } +#endif + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoke<void>(fp, i); + BOOST_TEST(count == save_count+3); + save_count = count; + } + // functor +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + A_void_1 a0; + int i = 4; + boost::detail::invoke(a0, i); + BOOST_TEST(count == save_count+4); + save_count = count; + } +#endif + { + A_void_1 a0; + int i = 4; + boost::detail::invoke<void>(a0, i); + BOOST_TEST(count == save_count+4); + save_count = count; + } + // member function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (A_void_1::*fp)() = &A_void_1::mem1; + A_void_1 a; + boost::detail::invoke(fp, a); + BOOST_TEST(count == save_count+1); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoke(fp, ap); + BOOST_TEST(count == save_count+1); + save_count = count; + } +#endif + { + void (A_void_1::*fp)() = &A_void_1::mem1; + A_void_1 a; + boost::detail::invoke<void>(fp, a); + BOOST_TEST(count == save_count+1); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoke<void>(fp, ap); + BOOST_TEST(count == save_count+1); + save_count = count; + } + // const member function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (A_void_1::*fp)() const = &A_void_1::mem2; + A_void_1 a; + boost::detail::invoke(fp, a); + BOOST_TEST(count == save_count+2); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoke(fp, ap); + BOOST_TEST(count == save_count+2); + save_count = count; + } +#endif + { + void (A_void_1::*fp)() const = &A_void_1::mem2; + A_void_1 a; + boost::detail::invoke<void>(fp, a); + BOOST_TEST(count == save_count+2); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoke<void>(fp, ap); + BOOST_TEST(count == save_count+2); + save_count = count; + } +} + +// 1 arg, return int + +int f_int_1(int i) +{ + return i + 1; +} + +struct A_int_1 +{ + A_int_1() : data_(5) {} + int operator()(int i) + { + return i - 1; + } + + int mem1() {return 3;} + int mem2() const {return 4;} + int data_; +}; + +void +test_int_1() +{ + // function + { + int i = 2; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(f_int_1, i) == 3); +#endif + BOOST_TEST(boost::detail::invoke<int>(f_int_1, i) == 3); + } + // function pointer + { + int (*fp)(int) = f_int_1; + int i = 3; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(fp, i) == 4); +#endif + BOOST_TEST(boost::detail::invoke<int>(fp, i) == 4); + } + // functor + { + int i = 4; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(A_int_1(), i) == 3); +#endif + const A_int_1 ca; + A_int_1 a; + BOOST_TEST(boost::detail::invoke<int>(a, i) == 3); + //BOOST_TEST(boost::detail::invoke<int>(ca, i) == 3); +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke<int>(A_int_1(), i) == 3); +#endif + } + // member function pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::mem1, a) == 3); +#endif + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, a) == 3); + A_int_1* ap = &a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::mem1, ap) == 3); +#endif + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, ap) == 3); + } + // const member function pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::mem2, A_int_1()) == 4); +#endif + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem2, A_int_1()) == 4); + A_int_1* ap = &a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::mem2, ap) == 4); +#endif + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem2, ap) == 4); + } + // member data pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, a) == 5); + + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, a) == 5); + +#endif +#if defined BOOST_THREAD_PROVIDES_INVOKE + A_int_1* ap = &a; + + boost::detail::invoke(&A_int_1::data_, a) = 6; + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, a) == 6); + + boost::detail::invoke<int>(&A_int_1::data_, a) = 6; + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, a) == 6); + +#endif + +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, ap) == 6); + boost::detail::invoke(&A_int_1::data_, ap) = 7; + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, ap) == 7); + + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, ap) == 7); + boost::detail::invoke<int>(&A_int_1::data_, ap) = 8; + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, ap) == 8); +#endif + + } +} + +// 2 arg, return void + +void f_void_2(int i, int j) +{ + count += i+j; +} + +struct A_void_2 +{ + void operator()(int i, int j) + { + count += i+j; + } + + void mem1(int i) {count += i;} + void mem2(int i) const {count += i;} +}; + +void +test_void_2() +{ + int save_count = count; + // function + { + int i = 2; + int j = 3; +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoke(f_void_2, i, j); + BOOST_TEST(count == save_count+5); + save_count = count; +#endif + boost::detail::invoke<void>(f_void_2, i, j); + BOOST_TEST(count == save_count+5); + save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + int j = 3; + boost::detail::invoke(&A_void_2::mem1, A_void_2(), j); + BOOST_TEST(count == save_count+3); + save_count = count; + + boost::detail::invoke<void>(&A_void_2::mem1, A_void_2(), j); + BOOST_TEST(count == save_count+3); + save_count = count; +#endif +// A_void_2 a2; +// boost::detail::invoke<void>(&A_void_2::mem1, a2, j); +// BOOST_TEST(count == save_count+3); +// save_count = count; + } +} + +int main() +{ + test_void_1(); + test_int_1(); + test_void_2(); + return boost::report_errors(); + +} diff --git a/src/boost/libs/thread/test/functional/invoke/invoke_rvalue_pass.cpp b/src/boost/libs/thread/test/functional/invoke/invoke_rvalue_pass.cpp new file mode 100644 index 000000000..82ea09432 --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoke/invoke_rvalue_pass.cpp @@ -0,0 +1,227 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/detail/invoke.hpp> + +#include <boost/thread/detail/invoke.hpp> +#include <boost/detail/lightweight_test.hpp> + +int count = 0; + +// 1 arg, return void + +void f_void_1(int i) +{ + count += i; +} + +struct A_void_1 +{ + void operator()(int i) + { + count += i; + } + + void mem1() {++count;} + void mem2() const {count += 2;} +}; + +void +test_void_1() +{ + int save_count = count; + // function + { + boost::detail::invoke(f_void_1, 2); + BOOST_TEST(count == save_count + 2); + save_count = count; + } + // function pointer + { + void (*fp)(int) = f_void_1; + boost::detail::invoke(fp, 3); + BOOST_TEST(count == save_count+3); + save_count = count; + } + // functor + { + A_void_1 a0; +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoke(a0, 4); + BOOST_TEST(count == save_count+4); + save_count = count; +#endif + boost::detail::invoke<void>(a0, 4); + BOOST_TEST(count == save_count+4); + save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + void (A_void_1::*fp)() = &A_void_1::mem1; + boost::detail::invoke(fp, A_void_1()); + BOOST_TEST(count == save_count+1); + save_count = count; + //BUG + boost::detail::invoke<void>(fp, A_void_1()); + BOOST_TEST(count == save_count+1); + save_count = count; + +#endif +#if defined BOOST_THREAD_PROVIDES_INVOKE + A_void_1 a; + boost::detail::invoke(fp, &a); + BOOST_TEST(count == save_count+1); + save_count = count; + //BUG + boost::detail::invoke<int>(fp, &a); + BOOST_TEST(count == save_count+1); + save_count = count; + +#endif + } + // const member function pointer + { + void (A_void_1::*fp)() const = &A_void_1::mem2; + boost::detail::invoke(fp, A_void_1()); + BOOST_TEST(count == save_count+2); + save_count = count; + A_void_1 a; + boost::detail::invoke(fp, &a); + BOOST_TEST(count == save_count+2); + save_count = count; + } +} + +// 1 arg, return int + +int f_int_1(int i) +{ + return i + 1; +} + +struct A_int_1 +{ + A_int_1() : data_(5) {} + int operator()(int i) + { + return i - 1; + } + + int mem1() {return 3;} + int mem2() const {return 4;} + int data_; +}; + +void +test_int_1() +{ + // function + { + BOOST_TEST(boost::detail::invoke(f_int_1, 2) == 3); + } + // function pointer + { + int (*fp)(int) = f_int_1; + BOOST_TEST(boost::detail::invoke(fp, 3) == 4); + } + // functor + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(A_int_1(), 4) == 3); + BOOST_TEST(boost::detail::invoke<int>(A_int_1(), 4) == 3); +#endif + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::mem1, A_int_1()) == 3); + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, A_int_1()) == 3); +#endif + + A_int_1 a; + BOOST_TEST(boost::detail::invoke(&A_int_1::mem1, &a) == 3); + } + // const member function pointer + { + BOOST_TEST(boost::detail::invoke(&A_int_1::mem2, A_int_1()) == 4); + A_int_1 a; + BOOST_TEST(boost::detail::invoke(&A_int_1::mem2, &a) == 4); + } + // member data pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, A_int_1()) == 5); + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, A_int_1()) == 5); + A_int_1 a; + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, a) == 5); + boost::detail::invoke(&A_int_1::data_, a) = 6; + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, a) == 6); + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, &a) == 6); + boost::detail::invoke(&A_int_1::data_, &a) = 7; + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, &a) == 7); +#endif + } +} + +// 2 arg, return void + +void f_void_2(int i, int j) +{ + count += i+j; +} + +struct A_void_2 +{ + void operator()(int i, int j) + { + count += i+j; + } + + void mem1(int i) {count += i;} + void mem2(int i) const {count += i;} +}; + +void +test_void_2() +{ + int save_count = count; + // function + { + boost::detail::invoke(f_void_2, 2, 3); + BOOST_TEST(count == save_count+5); + save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoke(&A_void_2::mem1, A_void_2(), 3); + BOOST_TEST(count == save_count+3); + save_count = count; + + boost::detail::invoke<void>(&A_void_2::mem1, A_void_2(), 3); + BOOST_TEST(count == save_count+3); + save_count = count; +#endif + + } +} + +int main() +{ + test_void_1(); + test_int_1(); + test_void_2(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/functional/invoker/invoker_int_0_pass.cpp b/src/boost/libs/thread/test/functional/invoker/invoker_int_0_pass.cpp new file mode 100644 index 000000000..123bde2e6 --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoker/invoker_int_0_pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/detail/invoker.hpp> + +#include <boost/thread/detail/invoker.hpp> +#include <boost/detail/lightweight_test.hpp> + +int f() +{ + return 1; +} + +struct A_int_0 +{ + A_int_0() + { + } + int operator()() + { + return 4; + } + int operator()() const + { + return 5; + } +}; + + +int main() +{ + const A_int_0 ca; + A_int_0 a; + +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST_EQ(boost::detail::invoker<int(*)()>(f)(), 1); + BOOST_TEST_EQ(boost::detail::invoker<int(*)()>(&f)(), 1); + BOOST_TEST_EQ(boost::detail::invoker<A_int_0>(A_int_0())(), 4); + BOOST_TEST_EQ(boost::detail::invoker<A_int_0>(a)(), 4); + BOOST_TEST_EQ(boost::detail::invoker<const A_int_0>(ca)(), 5); +#endif + + //BOOST_TEST_EQ(boost::detail::invoker<int>(f), 1); + //BOOST_TEST_EQ(boost::detail::invoker<int>(&f), 1); + BOOST_TEST_EQ(A_int_0()(), 4); +#if defined BOOST_THREAD_PROVIDES_INVOKE || ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + //BOOST_TEST_EQ(boost::detail::invoker<int>(A_int_0()), 4); +#else + //BOOST_TEST_EQ(boost::detail::invoke<int>(A_int_0()), 5); +#endif + //BOOST_TEST_EQ(a(), 4); + //BOOST_TEST_EQ(boost::detail::invoke<int>(a), 4); + //BOOST_TEST_EQ(ca(), 5); + //BOOST_TEST_EQ(boost::detail::invoke<int>(ca), 5); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/functional/invoker/invoker_lvalue_pass.cpp b/src/boost/libs/thread/test/functional/invoker/invoker_lvalue_pass.cpp new file mode 100644 index 000000000..42a98d45a --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoker/invoker_lvalue_pass.cpp @@ -0,0 +1,342 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/detail/invoker.hpp> + +#include <boost/thread/detail/invoker.hpp> +#include <boost/detail/lightweight_test.hpp> + +int count = 0; + +// 1 arg, return void + +void f_void_1(int i) +{ + count += i; +} + +struct A_void_1 +{ + typedef void result_type; + void operator()(int i) + { + count += i; + } + + void mem1() { + std::cout << "mem1 " << count << std::endl; + ++count; + std::cout << "mem1 " << count << std::endl; + } + void mem2() const {count += 2;} +}; + +void +test_void_1() +{ + int save_count = count; + // function +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + int i = 2; + boost::detail::invoker<void(*)(int), int>(f_void_1, i)(); + BOOST_TEST(count == save_count + 2); + save_count = count; + } +#endif +// { +// int i = 2; +// boost::detail::invoke<void>(f_void_1, i); +// BOOST_TEST(count == save_count + 2); +// save_count = count; +// } + // function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoker<void(*)(int), int>(fp, i)(); + BOOST_TEST(count == save_count+3); + save_count = count; + } +#endif +// { +// void (*fp)(int) = f_void_1; +// int i = 3; +// boost::detail::invoke<void>(fp, i); +// BOOST_TEST(count == save_count+3); +// save_count = count; +// } +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoker<void(*)(int), int>(fp, i)(); + BOOST_TEST(count == save_count+3); + save_count = count; + } +#endif +// { +// void (*fp)(int) = f_void_1; +// int i = 3; +// boost::detail::invoke<void>(fp, i); +// BOOST_TEST(count == save_count+3); +// save_count = count; +// } + // functor +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + A_void_1 a0; + int i = 4; + boost::detail::invoker<A_void_1, int>(a0, i)(); + BOOST_TEST(count == save_count+4); + save_count = count; + } +#endif +// { +// A_void_1 a0; +// int i = 4; +// boost::detail::invoke<void>(a0, i); +// BOOST_TEST(count == save_count+4); +// save_count = count; +// } + // member function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (A_void_1::*fp)() = &A_void_1::mem1; + A_void_1 a; + //BUG + boost::detail::invoker<void (A_void_1::*)(), A_void_1>(fp, a)(); + BOOST_TEST_EQ(count, save_count+1); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoker<void (A_void_1::*)(), A_void_1*>(fp, ap)(); + BOOST_TEST_EQ(count, save_count+1); + save_count = count; + } +#endif +// { +// void (A_void_1::*fp)() = &A_void_1::mem1; +// A_void_1 a; +// boost::detail::invoke<void>(fp, a); +// BOOST_TEST(count == save_count+1); +// save_count = count; +// A_void_1* ap = &a; +// boost::detail::invoke<void>(fp, ap); +// BOOST_TEST(count == save_count+1); +// save_count = count; +// } + // const member function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (A_void_1::*fp)() const = &A_void_1::mem2; + A_void_1 a; + boost::detail::invoker<void (A_void_1::*)() const, A_void_1>(fp, a)(); + BOOST_TEST(count == save_count+2); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoker<void (A_void_1::*)() const, A_void_1*>(fp, ap)(); + BOOST_TEST_EQ(count, save_count+2); + save_count = count; + } +#endif +// { +// void (A_void_1::*fp)() const = &A_void_1::mem2; +// A_void_1 a; +// boost::detail::invoke<void>(fp, a); +// BOOST_TEST(count == save_count+2); +// save_count = count; +// A_void_1* ap = &a; +// boost::detail::invoke<void>(fp, ap); +// BOOST_TEST(count == save_count+2); +// save_count = count; +// } +} + +// 1 arg, return int + +int f_int_1(int i) +{ + return i + 1; +} + +struct A_int_1 +{ + A_int_1() : data_(5) {} + int operator()(int i) + { + return i - 1; + } + + int mem1() {return 3;} + int mem2() const {return 4;} + int data_; +}; + +void +test_int_1() +{ + // function + { + int i = 2; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int(*)(int), int>(f_int_1, i)() == 3)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(f_int_1, i) == 3); + } + // function pointer + { + int (*fp)(int) = f_int_1; + int i = 3; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (*)(int), int>(fp, i)() == 4)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(fp, i) == 4); + } + // functor + { + int i = 4; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<A_int_1, int>(A_int_1(), i)() == 3)); +#endif +// const A_int_1 ca; +// A_int_1 a; +// BOOST_TEST(boost::detail::invoke<int>(a, i) == 3); +// //BOOST_TEST(boost::detail::invoke<int>(ca, i) == 3); +//#if defined BOOST_THREAD_PROVIDES_INVOKE +// BOOST_TEST(boost::detail::invoke<int>(A_int_1(), i) == 3); +//#endif + } + // member function pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)(), A_int_1>(&A_int_1::mem1, a)() == 3)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, a) == 3); + A_int_1* ap = &a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)(), A_int_1*>(&A_int_1::mem1, ap)() == 3)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, ap) == 3); + } + // const member function pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)() const, A_int_1>(&A_int_1::mem2, A_int_1())() == 4)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem2, A_int_1()) == 4); + A_int_1* ap = &a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)() const, A_int_1*>(&A_int_1::mem2, ap)() == 4)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem2, ap) == 4); + } + // member data pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + // BUG + //BOOST_TEST(boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a) == 5); + +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, a) == 5); + +#endif +//#if defined BOOST_THREAD_PROVIDES_INVOKE +// A_int_1* ap = &a; +// +// boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a) = 6; +// BOOST_TEST(boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a) == 6); +// +//// boost::detail::invoke<int>(&A_int_1::data_, a) = 6; +//// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, a) == 6); +// +//#endif +// +//#if defined BOOST_THREAD_PROVIDES_INVOKE +// BOOST_TEST(boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, ap) == 6); +// boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, ap) = 7; +// BOOST_TEST(boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, ap) == 7); +// +//// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, ap) == 7); +//// boost::detail::invoke<int>(&A_int_1::data_, ap) = 8; +//// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, ap) == 8); +//#endif + + } +} + +// 2 arg, return void + +void f_void_2(int i, int j) +{ + count += i+j; +} + +struct A_void_2 +{ + void operator()(int i, int j) + { + count += i+j; + } + + void mem1(int i) {count += i;} + void mem2(int i) const {count += i;} +}; + +void +test_void_2() +{ + int save_count = count; + // function + { + int i = 2; + int j = 3; +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoke(f_void_2, i, j); + BOOST_TEST(count == save_count+5); + save_count = count; +#endif +// boost::detail::invoke<void>(f_void_2, i, j); +// BOOST_TEST(count == save_count+5); +// save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + int j = 3; + boost::detail::invoke(&A_void_2::mem1, A_void_2(), j); + BOOST_TEST(count == save_count+3); + save_count = count; + +// boost::detail::invoke<void>(&A_void_2::mem1, A_void_2(), j); +// BOOST_TEST(count == save_count+3); +// save_count = count; +#endif +// A_void_2 a2; +// boost::detail::invoke<void>(&A_void_2::mem1, a2, j); +// BOOST_TEST(count == save_count+3); +// save_count = count; + } +} + +int main() +{ + test_void_1(); + test_int_1(); + test_void_2(); + return boost::report_errors(); + +} diff --git a/src/boost/libs/thread/test/functional/invoker/invoker_rvalue_pass.cpp b/src/boost/libs/thread/test/functional/invoker/invoker_rvalue_pass.cpp new file mode 100644 index 000000000..ae06e16b6 --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoker/invoker_rvalue_pass.cpp @@ -0,0 +1,230 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/detail/invoker.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +//#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include <boost/thread/detail/invoker.hpp> +#include <boost/detail/lightweight_test.hpp> + +int count = 0; + +// 1 arg, return void + +void f_void_1(int i) +{ + count += i; +} + +struct A_void_1 +{ + typedef void result_type; + void operator()(int i) + { + count += i; + } + + void mem1() {++count;} + void mem2() const {count += 2;} +}; + +void +test_void_1() +{ + int save_count = count; + // function + { + boost::detail::invoker<void(*)(int), int>(f_void_1, 2)(); + BOOST_TEST(count == save_count + 2); + save_count = count; + } + // function pointer + { + void (*fp)(int) = f_void_1; + boost::detail::invoker<void(*)(int), int>(fp, 3)(); + BOOST_TEST(count == save_count+3); + save_count = count; + } + // functor + { + A_void_1 a0; +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoker<A_void_1, int>(a0, 4)(); + BOOST_TEST(count == save_count+4); + save_count = count; +#endif +// boost::detail::invoke<void>(a0, 4); +// BOOST_TEST(count == save_count+4); +// save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + void (A_void_1::*fp)() = &A_void_1::mem1; + boost::detail::invoker<void (A_void_1::*)(), A_void_1>(fp, A_void_1())(); + BOOST_TEST(count == save_count+1); + save_count = count; + +#endif + // boost::detail::invoke<void>(fp, A_void_1()); + // BOOST_TEST(count == save_count+1); + // save_count = count; +#if defined BOOST_THREAD_PROVIDES_INVOKE + A_void_1 a; + boost::detail::invoker<void (A_void_1::*)(), A_void_1*>(fp, &a)(); + BOOST_TEST(count == save_count+1); + save_count = count; + +#endif + // boost::detail::invoke<int>(fp, &a); + // BOOST_TEST(count == save_count+1); + // save_count = count; + } + // const member function pointer + { + void (A_void_1::*fp)() const = &A_void_1::mem2; + boost::detail::invoker<void (A_void_1::*)() const, A_void_1>(fp, A_void_1())(); + BOOST_TEST(count == save_count+2); + save_count = count; + A_void_1 a; + boost::detail::invoker<void (A_void_1::*)() const, A_void_1*>(fp, &a)(); + BOOST_TEST(count == save_count+2); + save_count = count; + } +} + +// 1 arg, return int + +int f_int_1(int i) +{ + return i + 1; +} + +struct A_int_1 +{ + A_int_1() : data_(5) {} + int operator()(int i) + { + return i - 1; + } + + int mem1() {return 3;} + int mem2() const {return 4;} + int data_; +}; + +void +test_int_1() +{ + // function + { + BOOST_TEST((boost::detail::invoker<int (*)(int), int>(f_int_1, 2)() == 3)); + } + // function pointer + { + int (*fp)(int) = f_int_1; + BOOST_TEST((boost::detail::invoker<int (*)(int), int>(fp, 3)() == 4)); + } + // functor + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<A_int_1, int>(A_int_1(), 4)() == 3)); +// BOOST_TEST(boost::detail::invoke<int>(A_int_1(), 4) == 3); +#endif + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)(),A_int_1>(&A_int_1::mem1, A_int_1())() == 3)); +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, A_int_1()) == 3); +#endif + + A_int_1 a; + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)(), A_int_1*>(&A_int_1::mem1, &a)() == 3)); + } + // const member function pointer + { + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)() const, A_int_1>(&A_int_1::mem2, A_int_1())() == 4)); + A_int_1 a; + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)() const, A_int_1*>(&A_int_1::mem2, &a)() == 4)); + } + // member data pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE +// BOOST_TEST((boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, A_int_1())() == 5)); +//// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, A_int_1()) == 5); +// A_int_1 a; +// BOOST_TEST((boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a)() == 5)); +// boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a)() = 6; +// BOOST_TEST((boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a)() == 6)); +// BOOST_TEST((boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, &a)() == 6)); +// boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, &a)() = 7; +// BOOST_TEST((boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, &a)() == 7)); +#endif + } +} + +// 2 arg, return void + +void f_void_2(int i, int j) +{ + count += i+j; +} + +struct A_void_2 +{ + void operator()(int i, int j) + { + count += i+j; + } + + void mem1(int i) {count += i;} + void mem2(int i) const {count += i;} +}; + +void +test_void_2() +{ + int save_count = count; + // function + { + boost::detail::invoke(f_void_2, 2, 3); + BOOST_TEST(count == save_count+5); + save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoke(&A_void_2::mem1, A_void_2(), 3); + BOOST_TEST(count == save_count+3); + save_count = count; + + boost::detail::invoke<void>(&A_void_2::mem1, A_void_2(), 3); + BOOST_TEST(count == save_count+3); + save_count = count; +#endif + + } +} + +int main() +{ + test_void_1(); + test_int_1(); + test_void_2(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/no_implicit_assign_from_lvalue_thread.cpp b/src/boost/libs/thread/test/no_implicit_assign_from_lvalue_thread.cpp new file mode 100644 index 000000000..1922bb7dc --- /dev/null +++ b/src/boost/libs/thread/test/no_implicit_assign_from_lvalue_thread.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#include <boost/thread/thread.hpp> + +void do_nothing() +{} + +void test() +{ + boost::thread t1(do_nothing); + boost::thread t2; + t2=t1; +} + +#include "./remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/no_implicit_move_from_lvalue_thread.cpp b/src/boost/libs/thread/test/no_implicit_move_from_lvalue_thread.cpp new file mode 100644 index 000000000..63522f0f0 --- /dev/null +++ b/src/boost/libs/thread/test/no_implicit_move_from_lvalue_thread.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#include <boost/thread/thread.hpp> + +void do_nothing() +{} + +void test() +{ + boost::thread t1(do_nothing); + boost::thread t2(t1); +} + +#include "./remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/remove_error_code_unused_warning.hpp b/src/boost/libs/thread/test/remove_error_code_unused_warning.hpp new file mode 100644 index 000000000..1f43f2a2e --- /dev/null +++ b/src/boost/libs/thread/test/remove_error_code_unused_warning.hpp @@ -0,0 +1,17 @@ +// Copyright (C) 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#include <boost/thread/thread.hpp> + +void remove_unused_warning() +{ + //../../../boost/system/error_code.hpp:214:36: warning: 'boost::system::posix_category' defined but not used [-Wunused-variable] + //../../../boost/system/error_code.hpp:215:36: warning: 'boost::system::errno_ecat' defined but not used [-Wunused-variable] + //../../../boost/system/error_code.hpp:216:36: warning: 'boost::system::native_ecat' defined but not used [-Wunused-variable] + + //(void)boost::system::posix_category; + //(void)boost::system::errno_ecat; + //(void)boost::system::native_ecat; + +} diff --git a/src/boost/libs/thread/test/self_contained_header.cpp b/src/boost/libs/thread/test/self_contained_header.cpp new file mode 100644 index 000000000..ef4117a13 --- /dev/null +++ b/src/boost/libs/thread/test/self_contained_header.cpp @@ -0,0 +1,26 @@ +/* + * Copyright Andrey Semashev 2019. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +/*! + * \file self_contained_header.cpp + * \author Andrey Semashev + * \date 2019-01-19 + * + * \brief This file contains a test boilerplate for checking that every public header is self-contained and does not have any missing #includes. + */ + +#if defined(BOOST_THREAD_TEST_POST_WINDOWS_H) +#include <windows.h> +#endif + +#define BOOST_THREAD_TEST_INCLUDE_HEADER() <boost/thread/BOOST_THREAD_TEST_HEADER> + +#include BOOST_THREAD_TEST_INCLUDE_HEADER() + +int main(int, char*[]) +{ + return 0; +} diff --git a/src/boost/libs/thread/test/shared_mutex_locking_thread.hpp b/src/boost/libs/thread/test/shared_mutex_locking_thread.hpp new file mode 100644 index 000000000..4d9a31ca5 --- /dev/null +++ b/src/boost/libs/thread/test/shared_mutex_locking_thread.hpp @@ -0,0 +1,145 @@ +#ifndef SHARED_MUTEX_LOCKING_THREAD_HPP +#define SHARED_MUTEX_LOCKING_THREAD_HPP + +// (C) Copyright 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/config.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/shared_mutex.hpp> + +template<typename lock_type> +class locking_thread +{ + boost::shared_mutex& rw_mutex; + unsigned& unblocked_count; + boost::condition_variable& unblocked_condition; + unsigned& simultaneous_running_count; + unsigned& max_simultaneous_running; + boost::mutex& unblocked_count_mutex; + boost::mutex& finish_mutex; +public: + locking_thread(boost::shared_mutex& rw_mutex_, + unsigned& unblocked_count_, + boost::mutex& unblocked_count_mutex_, + boost::condition_variable& unblocked_condition_, + boost::mutex& finish_mutex_, + unsigned& simultaneous_running_count_, + unsigned& max_simultaneous_running_): + rw_mutex(rw_mutex_), + unblocked_count(unblocked_count_), + unblocked_condition(unblocked_condition_), + simultaneous_running_count(simultaneous_running_count_), + max_simultaneous_running(max_simultaneous_running_), + unblocked_count_mutex(unblocked_count_mutex_), + finish_mutex(finish_mutex_) + {} + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + locking_thread(locking_thread const&) = default; +#endif + + void operator()() + { + // acquire lock + lock_type lock(rw_mutex); + + // increment count to show we're unblocked + { + boost::unique_lock<boost::mutex> ublock(unblocked_count_mutex); + ++unblocked_count; + unblocked_condition.notify_one(); + ++simultaneous_running_count; + if(simultaneous_running_count>max_simultaneous_running) + { + max_simultaneous_running=simultaneous_running_count; + } + } + + // wait to finish + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + { + boost::unique_lock<boost::mutex> ublock(unblocked_count_mutex); + --simultaneous_running_count; + } + } +private: + void operator=(locking_thread&); +}; + +class simple_writing_thread +{ + boost::shared_mutex& rwm; + boost::mutex& finish_mutex; + boost::mutex& unblocked_mutex; + unsigned& unblocked_count; + + void operator=(simple_writing_thread&); + +public: + simple_writing_thread(boost::shared_mutex& rwm_, + boost::mutex& finish_mutex_, + boost::mutex& unblocked_mutex_, + unsigned& unblocked_count_): + rwm(rwm_),finish_mutex(finish_mutex_), + unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_) + {} + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + simple_writing_thread(simple_writing_thread const&) = default; +#endif + + void operator()() + { + boost::unique_lock<boost::shared_mutex> lk(rwm); + + { + boost::unique_lock<boost::mutex> ulk(unblocked_mutex); + ++unblocked_count; + } + + boost::unique_lock<boost::mutex> flk(finish_mutex); + } +}; + +class simple_reading_thread +{ + boost::shared_mutex& rwm; + boost::mutex& finish_mutex; + boost::mutex& unblocked_mutex; + unsigned& unblocked_count; + + void operator=(simple_reading_thread&); + +public: + simple_reading_thread(boost::shared_mutex& rwm_, + boost::mutex& finish_mutex_, + boost::mutex& unblocked_mutex_, + unsigned& unblocked_count_): + rwm(rwm_),finish_mutex(finish_mutex_), + unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_) + {} + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + simple_reading_thread(simple_reading_thread const&) = default; +#endif + + void operator()() + { + boost::shared_lock<boost::shared_mutex> lk(rwm); + + { + boost::unique_lock<boost::mutex> ulk(unblocked_mutex); + ++unblocked_count; + } + + boost::unique_lock<boost::mutex> flk(finish_mutex); + } +}; + + +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/assign_fail.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/assign_fail.cpp new file mode 100644 index 000000000..703616ff1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/assign_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable& operator=(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> + +void fail() +{ + boost::condition_variable cv0; + boost::condition_variable cv1; + cv1 = cv0; + +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/copy_fail.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/copy_fail.cpp new file mode 100644 index 000000000..374ce3165 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/copy_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/detail/lightweight_test.hpp> + +void fail() +{ + boost::condition_variable cv0; + boost::condition_variable cv1(cv0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/default_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/default_pass.cpp new file mode 100644 index 000000000..465a12de8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/default_pass.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::condition_variable cv0; + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/dtor_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/dtor_pass.cpp new file mode 100644 index 000000000..533898ed4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/dtor_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/locks.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::condition_variable* cv; +boost::mutex m; +typedef boost::unique_lock<boost::mutex> Lock; + +bool f_ready = false; +bool g_ready = false; + +void f() +{ + Lock lk(m); + f_ready = true; + cv->notify_one(); + cv->wait(lk); + delete cv; +} + +void g() +{ + Lock lk(m); + g_ready = true; + cv->notify_one(); + while (!f_ready) + { + cv->wait(lk); + } + cv->notify_one(); +} + +int main() +{ + cv = new boost::condition_variable; + boost::thread th2(g); + Lock lk(m); + while (!g_ready) + { + cv->wait(lk); + } + lk.unlock(); + boost::thread th1(f); + th1.join(); + th2.join(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/lost_notif_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/lost_notif_pass.cpp new file mode 100644 index 000000000..79dbcd295 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/lost_notif_pass.cpp @@ -0,0 +1,241 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2017 Austin J. Beer +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <iostream> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> + +// Summary of each test: +// 1. Start the test thread and wait for it to start up. +// The test thread waits for the flag to be set using a large timeout. +// 2. The main thread takes the lock and then sleeps for a long time while holding +// the lock before setting the flag and calling notify_one(). If the wait +// function being tested is polling pthread_cond_timedwait() internally, any +// notifications sent after pthread_cond_timedwait() times out but before it can +// reacquire the lock may be "lost". pthread_cond_timedwait() will report that +// it timed out and the wait function may incorrectly assume that no +// notification was received. This test ensures that that doesn't happen. +// 3. Measure how it takes the test thread to return. If it received the +// notification, it will return fairly quickly. If it missed the notification, +// the test thread won't return until the wait function being tested times out. + +//------------------------------------------------------------------------------ + +boost::condition_variable cv; +boost::mutex mut; + +bool flag; +bool waiting; + +bool flagIsSet() +{ + return flag; +} + +bool threadIsWaiting() +{ + return waiting; +} + +//------------------------------------------------------------------------------ + +#ifdef BOOST_THREAD_USES_DATETIME + +boost::posix_time::milliseconds posix_wait_time(1000); + +template <typename F> +void test_posix_wait_function(F f) +{ + flag = false; + waiting = false; + boost::thread t(f); + while (!threadIsWaiting()) + { + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } + + boost::unique_lock<boost::mutex> lk(mut); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::posix_time::ptime t0 = boost::posix_time::microsec_clock::universal_time(); + flag = true; + cv.notify_one(); + lk.unlock(); + t.join(); + boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::universal_time(); + + BOOST_TEST(t1 - t0 < boost::posix_time::milliseconds(250)); +} + +//------------------------------------------------------------------------------ + +void timed_wait_absolute_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time); + } +} + +void timed_wait_absolute_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void timed_wait_relative_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.timed_wait(lk, posix_wait_time); + } +} + +void timed_wait_relative_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.timed_wait(lk, posix_wait_time, flagIsSet); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_DATETIME not defined for this platform as not supported" +#endif + +//------------------------------------------------------------------------------ + +#ifdef BOOST_THREAD_USES_CHRONO + +boost::chrono::milliseconds chrono_wait_time(1000); + +template <typename F> +void test_chrono_wait_function(F f) +{ + flag = false; + waiting = false; + boost::thread t(f); + while (!threadIsWaiting()) + { + boost::this_thread::sleep_for(boost::chrono::milliseconds(1)); + } + + boost::unique_lock<boost::mutex> lk(mut); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + boost::chrono::steady_clock::time_point t0 = boost::chrono::steady_clock::now(); + flag = true; + cv.notify_one(); + lk.unlock(); + t.join(); + boost::chrono::steady_clock::time_point t1 = boost::chrono::steady_clock::now(); + + BOOST_TEST(t1 - t0 < boost::chrono::milliseconds(250)); +} + +//------------------------------------------------------------------------------ + +void wait_until_system_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time); + } +} + +void wait_until_system_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void wait_until_steady_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time); + } +} + +void wait_until_steady_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void wait_for_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_for(lk, chrono_wait_time); + } +} + +void wait_for_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_for(lk, chrono_wait_time, flagIsSet); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + +//------------------------------------------------------------------------------ + +int main() +{ +#ifdef BOOST_THREAD_USES_DATETIME + test_posix_wait_function(timed_wait_absolute_without_pred); + test_posix_wait_function(timed_wait_absolute_with_pred); + test_posix_wait_function(timed_wait_relative_without_pred); + test_posix_wait_function(timed_wait_relative_with_pred); +#endif + +#ifdef BOOST_THREAD_USES_CHRONO + test_chrono_wait_function(wait_until_system_without_pred); + test_chrono_wait_function(wait_until_system_with_pred); + test_chrono_wait_function(wait_until_steady_without_pred); + test_chrono_wait_function(wait_until_steady_with_pred); + test_chrono_wait_function(wait_for_without_pred); + test_chrono_wait_function(wait_for_with_pred); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/native_handle_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/native_handle_pass.cpp new file mode 100644 index 000000000..9835f5920 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/native_handle_pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> + +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE + //BOOST_STATIC_ASSERT((boost::is_same<boost::condition_variable::native_handle_type, pthread_cond_t*>::value)); + boost::condition_variable cv; + boost::condition_variable::native_handle_type h = cv.native_handle(); + BOOST_TEST(h != 0); +#else +#error "Test not applicable: BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE not defined for this platform as not supported" +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pass.cpp new file mode 100644 index 000000000..4c6a0af3e --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <iostream> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::condition_variable cv; +boost::mutex mut; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +typedef boost::chrono::steady_clock Clock; +typedef boost::chrono::milliseconds milliseconds; +typedef boost::chrono::nanoseconds nanoseconds; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + try { + boost::unique_lock<boost::mutex> lk(mut); + assert(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + milliseconds(250); + while (test2 == 0 && cv.wait_for(lk, t - Clock::now()) == boost::cv_status::no_timeout) {} + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + assert(t1 - t0 < max_diff); + assert(test2 != 0); + } + else + { + nanoseconds d = t1 - t0 - milliseconds(250); + std::cout << "diff= " << d.count() << std::endl; + std::cout << "max_diff= " << max_diff.count() << std::endl; + assert( d < max_diff); + assert(test2 == 0); + } + ++runs; + } catch(...) { + std::cout << "ERROR exception" << __LINE__ << std::endl; + assert(false); + } +} + +int main() +{ + try + { + boost::unique_lock<boost::mutex> lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } catch(...) { + std::cout << "ERROR exception" << __LINE__ << std::endl; + BOOST_TEST(false); + } + test1 = 0; + test2 = 0; + try + { + boost::unique_lock<boost::mutex> lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + return boost::report_errors(); +} +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pred_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pred_pass.cpp new file mode 100644 index 000000000..92ba82f1e --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pred_pass.cpp @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> +#include <iostream> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +class Pred +{ + int& i_; +public: + explicit Pred(int& i) : + i_(i) + { + } + + bool operator()() + { + return i_ != 0; + } +}; + +boost::condition_variable cv; +boost::mutex mut; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +typedef boost::chrono::system_clock Clock; +typedef boost::chrono::milliseconds milliseconds; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + try { + boost::unique_lock < boost::mutex > lk(mut); + assert(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + cv.wait_for(lk, milliseconds(250), Pred(test2)); + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + assert(t1 - t0 < max_diff); + assert(test2 != 0); + } + else + { + assert(t1 - t0 - milliseconds(250) < max_diff); + assert(test2 == 0); + } + ++runs; + } catch(...) { + std::cout << "ERROR exception" << __LINE__ << std::endl; + assert(false); + } +} + +int main() +{ + try + { + boost::unique_lock < boost::mutex > lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + test1 = 0; + test2 = 0; + try + { + boost::unique_lock < boost::mutex > lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_pass.cpp new file mode 100644 index 000000000..612724b85 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_pass.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// void wait(unique_lock<mutex>& lock); + + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> +#include <iostream> + +#if defined BOOST_THREAD_USES_CHRONO + +boost::condition_variable cv; +boost::mutex mut; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +void f() +{ + try { + boost::unique_lock<boost::mutex> lk(mut); + assert(test2 == 0); + test1 = 1; + cv.notify_one(); + while (test2 == 0) { + cv.wait(lk); + } + assert(test2 != 0); + } catch(...) { + std::cout << "ERROR exception" << __LINE__ << std::endl; + assert(false); + } +} + +int main() +{ + try { + boost::unique_lock<boost::mutex>lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + { + cv.wait(lk); + } + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + return boost::report_errors(); +} +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pass.cpp new file mode 100644 index 000000000..34ef32268 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pass.cpp @@ -0,0 +1,128 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include <cassert> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +struct Clock +{ + typedef boost::chrono::milliseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef boost::chrono::time_point<Clock> time_point; + static const bool is_steady = true; + + static time_point now() + { + using namespace boost::chrono; + return time_point(duration_cast<duration> (steady_clock::now().time_since_epoch())); + } +}; + +boost::condition_variable cv; +boost::mutex mut; + + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + try { + boost::unique_lock < boost::mutex > lk(mut); + assert(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + Clock::duration(250); + while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout) {} + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + assert(test2 != 0); + } + else + { + ns d = t1 - t0 - Clock::duration(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + assert(test2 == 0); + } + ++runs; + } catch(...) { + assert(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } +} + +int main() +{ + try + { + boost::unique_lock < boost::mutex > lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + + test1 = 0; + test2 = 0; + try + { + boost::unique_lock < boost::mutex > lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pred_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pred_pass.cpp new file mode 100644 index 000000000..120e49853 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pred_pass.cpp @@ -0,0 +1,146 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> +#include <iostream> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::milliseconds milliseconds; +typedef boost::chrono::nanoseconds nanoseconds; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +struct Clock +{ + typedef boost::chrono::milliseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef boost::chrono::time_point<Clock> time_point; + static const bool is_steady = true; + + static time_point now() + { + using namespace boost::chrono; + return time_point(duration_cast<duration> (steady_clock::now().time_since_epoch())); + } +}; + +class Pred +{ + int& i_; +public: + explicit Pred(int& i) : + i_(i) + { + } + + bool operator()() + { + return i_ != 0; + } +}; + +boost::condition_variable cv; +boost::mutex mut; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + try { + boost::unique_lock<boost::mutex> lk(mut); + assert(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + Clock::duration(250); + bool r = cv.wait_until(lk, t, Pred(test2)); + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + assert(t1 - t0 < max_diff); + assert(test2 != 0); + assert(r); + } + else + { + const nanoseconds d = t1 - t0 - milliseconds(250); + std::cout << "diff= " << d.count() << std::endl; + std::cout << "max_diff= " << max_diff.count() << std::endl; + assert(d < max_diff); + assert(test2 == 0); + assert(!r); + } + ++runs; + } catch(...) { + std::cout << "ERROR exception" << __LINE__ << std::endl; + assert(false); + } +} + +int main() +{ + try + { + boost::unique_lock<boost::mutex> lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + test1 = 0; + test2 = 0; + try + { + boost::unique_lock<boost::mutex> lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/assign_fail.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/assign_fail.cpp new file mode 100644 index 000000000..6dba459cb --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/assign_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any& operator=(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> + +void fail() +{ + boost::condition_variable_any cv0; + boost::condition_variable_any cv1; + cv1 = cv0; +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/copy_fail.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/copy_fail.cpp new file mode 100644 index 000000000..71d3a3f06 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/copy_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/detail/lightweight_test.hpp> + +void fail() +{ + boost::condition_variable_any cv0; + boost::condition_variable_any cv1(cv0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/default_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/default_pass.cpp new file mode 100644 index 000000000..21116ebc4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/default_pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::condition_variable_any cv0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/dtor_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/dtor_pass.cpp new file mode 100644 index 000000000..7734d93b7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/dtor_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/locks.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::condition_variable_any* cv; +boost::timed_mutex m; +typedef boost::unique_lock<boost::timed_mutex> Lock; + +bool f_ready = false; +bool g_ready = false; + +void f() +{ + Lock lk(m); + f_ready = true; + cv->notify_one(); + cv->wait(lk); + delete cv; +} + +void g() +{ + Lock lk(m); + g_ready = true; + cv->notify_one(); + while (!f_ready) + { + cv->wait(lk); + } + cv->notify_one(); +} + +int main() +{ + cv = new boost::condition_variable_any; + boost::thread th2(g); + Lock lk(m); + while (!g_ready) + { + cv->wait(lk); + } + lk.unlock(); + boost::thread th1(f); + th1.join(); + th2.join(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/lost_notif_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/lost_notif_pass.cpp new file mode 100644 index 000000000..c696da3c2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/lost_notif_pass.cpp @@ -0,0 +1,241 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2017 Austin J. Beer +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <iostream> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> + +// Summary of each test: +// 1. Start the test thread and wait for it to start up. +// The test thread waits for the flag to be set using a large timeout. +// 2. The main thread takes the lock and then sleeps for a long time while holding +// the lock before setting the flag and calling notify_one(). If the wait +// function being tested is polling pthread_cond_timedwait() internally, any +// notifications sent after pthread_cond_timedwait() times out but before it can +// reacquire the lock may be "lost". pthread_cond_timedwait() will report that +// it timed out and the wait function may incorrectly assume that no +// notification was received. This test ensures that that doesn't happen. +// 3. Measure how it takes the test thread to return. If it received the +// notification, it will return fairly quickly. If it missed the notification, +// the test thread won't return until the wait function being tested times out. + +//------------------------------------------------------------------------------ + +boost::condition_variable_any cv; +boost::mutex mut; + +bool flag; +bool waiting; + +bool flagIsSet() +{ + return flag; +} + +bool threadIsWaiting() +{ + return waiting; +} + +//------------------------------------------------------------------------------ + +#ifdef BOOST_THREAD_USES_DATETIME + +boost::posix_time::milliseconds posix_wait_time(1000); + +template <typename F> +void test_posix_wait_function(F f) +{ + flag = false; + waiting = false; + boost::thread t(f); + while (!threadIsWaiting()) + { + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } + + boost::unique_lock<boost::mutex> lk(mut); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::posix_time::ptime t0 = boost::posix_time::microsec_clock::universal_time(); + flag = true; + cv.notify_one(); + lk.unlock(); + t.join(); + boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::universal_time(); + + BOOST_TEST(t1 - t0 < boost::posix_time::milliseconds(250)); +} + +//------------------------------------------------------------------------------ + +void timed_wait_absolute_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time); + } +} + +void timed_wait_absolute_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void timed_wait_relative_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.timed_wait(lk, posix_wait_time); + } +} + +void timed_wait_relative_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.timed_wait(lk, posix_wait_time, flagIsSet); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_DATETIME not defined for this platform as not supported" +#endif + +//------------------------------------------------------------------------------ + +#ifdef BOOST_THREAD_USES_CHRONO + +boost::chrono::milliseconds chrono_wait_time(1000); + +template <typename F> +void test_chrono_wait_function(F f) +{ + flag = false; + waiting = false; + boost::thread t(f); + while (!threadIsWaiting()) + { + boost::this_thread::sleep_for(boost::chrono::milliseconds(1)); + } + + boost::unique_lock<boost::mutex> lk(mut); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + boost::chrono::steady_clock::time_point t0 = boost::chrono::steady_clock::now(); + flag = true; + cv.notify_one(); + lk.unlock(); + t.join(); + boost::chrono::steady_clock::time_point t1 = boost::chrono::steady_clock::now(); + + BOOST_TEST(t1 - t0 < boost::chrono::milliseconds(250)); +} + +//------------------------------------------------------------------------------ + +void wait_until_system_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time); + } +} + +void wait_until_system_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void wait_until_steady_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time); + } +} + +void wait_until_steady_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void wait_for_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_for(lk, chrono_wait_time); + } +} + +void wait_for_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_for(lk, chrono_wait_time, flagIsSet); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + +//------------------------------------------------------------------------------ + +int main() +{ +#ifdef BOOST_THREAD_USES_DATETIME + test_posix_wait_function(timed_wait_absolute_without_pred); + test_posix_wait_function(timed_wait_absolute_with_pred); + test_posix_wait_function(timed_wait_relative_without_pred); + test_posix_wait_function(timed_wait_relative_with_pred); +#endif + +#ifdef BOOST_THREAD_USES_CHRONO + test_chrono_wait_function(wait_until_system_without_pred); + test_chrono_wait_function(wait_until_system_with_pred); + test_chrono_wait_function(wait_until_steady_without_pred); + test_chrono_wait_function(wait_until_steady_with_pred); + test_chrono_wait_function(wait_for_without_pred); + test_chrono_wait_function(wait_for_with_pred); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pass.cpp new file mode 100644 index 000000000..b1fca89f6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pass.cpp @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::condition_variable_any cv; + +typedef boost::timed_mutex L0; +typedef boost::unique_lock<L0> L1; + +L0 m0; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +typedef boost::chrono::system_clock Clock; +typedef boost::chrono::milliseconds milliseconds; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + L1 lk(m0); + BOOST_TEST(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + milliseconds(250); + while (test2 == 0 && cv.wait_for(lk, t - Clock::now()) == boost::cv_status::no_timeout) {} + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 != 0); + } + else + { + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 == 0); + } + ++runs; +} + +int main() +{ + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } + test1 = 0; + test2 = 0; + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pred_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pred_pass.cpp new file mode 100644 index 000000000..3885b23c1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pred_pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +class Pred +{ + int& i_; +public: + explicit Pred(int& i) : + i_(i) + { + } + + bool operator()() + { + return i_ != 0; + } +}; + +boost::condition_variable_any cv; + +typedef boost::timed_mutex L0; +typedef boost::unique_lock<L0> L1; + +L0 m0; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +typedef boost::chrono::system_clock Clock; +typedef boost::chrono::milliseconds milliseconds; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + L1 lk(m0); + BOOST_TEST(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + cv.wait_for(lk, milliseconds(250), Pred(test2)); + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + ns d = t1 - t0 ; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 != 0); + } + else + { + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 == 0); + } + ++runs; +} + +int main() +{ + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } + test1 = 0; + test2 = 0; + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pass.cpp new file mode 100644 index 000000000..acf5fb1c4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pass.cpp @@ -0,0 +1,115 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +struct Clock +{ + typedef boost::chrono::milliseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef boost::chrono::time_point<Clock> time_point; + static const bool is_steady = true; + + static time_point now() + { + using namespace boost::chrono; + return time_point(duration_cast<duration> (steady_clock::now().time_since_epoch())); + } +}; + +boost::condition_variable_any cv; + +typedef boost::timed_mutex L0; +typedef boost::unique_lock<L0> L1; + +L0 m0; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + L1 lk(m0); + BOOST_TEST(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + Clock::duration(250); + while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout) {} + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 != 0); + } + else + { + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 == 0); + } + ++runs; +} + +int main() +{ + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } + test1 = 0; + test2 = 0; + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pred_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pred_pass.cpp new file mode 100644 index 000000000..f6e9b7ee2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pred_pass.cpp @@ -0,0 +1,134 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +struct Clock +{ + typedef boost::chrono::milliseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef boost::chrono::time_point<Clock> time_point; + static const bool is_steady = true; + + static time_point now() + { + using namespace boost::chrono; + return time_point(duration_cast<duration> (steady_clock::now().time_since_epoch())); + } +}; + +class Pred +{ + int& i_; +public: + explicit Pred(int& i) : + i_(i) + { + } + + bool operator()() + { + return i_ != 0; + } +}; + +boost::condition_variable_any cv; + +typedef boost::timed_mutex L0; +typedef boost::unique_lock<L0> L1; + +L0 m0; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + L1 lk(m0); + BOOST_TEST(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + Clock::duration(250); + bool r = cv.wait_until(lk, t, Pred(test2)); + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 != 0); + BOOST_TEST(r); + } + else + { + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 == 0); + BOOST_TEST(!r); + } + ++runs; +} + +int main() +{ + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } + test1 = 0; + test2 = 0; + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/cv_status/cv_status_pass.cpp b/src/boost/libs/thread/test/sync/conditions/cv_status/cv_status_pass.cpp new file mode 100644 index 000000000..becac4da5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/cv_status/cv_status_pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// static unsigned hardware_concurrency(); + +#include <boost/thread/condition_variable.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + BOOST_TEST(boost::cv_status::no_timeout != boost::cv_status::timeout); + } + { + boost::cv_status st = boost::cv_status::no_timeout; + BOOST_TEST(st == boost::cv_status::no_timeout); + BOOST_TEST(boost::cv_status::no_timeout==st); + BOOST_TEST(st != boost::cv_status::timeout); + BOOST_TEST(boost::cv_status::timeout!=st); + } + { + boost::cv_status st = boost::cv_status::timeout; + BOOST_TEST(st == boost::cv_status::timeout); + BOOST_TEST(boost::cv_status::timeout==st); + BOOST_TEST(st != boost::cv_status::no_timeout); + BOOST_TEST(boost::cv_status::no_timeout!=st); + } + { + boost::cv_status st; + st = boost::cv_status::no_timeout; + BOOST_TEST(st == boost::cv_status::no_timeout); + BOOST_TEST(boost::cv_status::no_timeout==st); + BOOST_TEST(st != boost::cv_status::timeout); + BOOST_TEST(boost::cv_status::timeout!=st); + } + { + boost::cv_status st; + st = boost::cv_status::timeout; + BOOST_TEST(st == boost::cv_status::timeout); + BOOST_TEST(boost::cv_status::timeout==st); + BOOST_TEST(st != boost::cv_status::no_timeout); + BOOST_TEST(boost::cv_status::no_timeout!=st); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/conditions/notify_all_at_thread_exit_pass.cpp b/src/boost/libs/thread/test/sync/conditions/notify_all_at_thread_exit_pass.cpp new file mode 100644 index 000000000..d6eecbd95 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/notify_all_at_thread_exit_pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/condition_variable.hpp> + +// void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); + +#define BOOST_THREAD_USES_MOVE +#define BOOST_THREAD_VESRION 3 + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::condition_variable cv; +boost::mutex mut; + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::high_resolution_clock Clock; + +void func() +{ + boost::unique_lock < boost::mutex > lk(mut); + boost::notify_all_at_thread_exit(cv, boost::move(lk)); + boost::this_thread::sleep_for(ms(300)); +} + +int main() +{ + boost::unique_lock < boost::mutex > lk(mut); + boost::thread(func).detach(); + Clock::time_point t0 = Clock::now(); + cv.wait(lk); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(t1 - t0 > ms(250)); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/async/async_executor_pass.cpp b/src/boost/libs/thread/test/sync/futures/async/async_executor_pass.cpp new file mode 100644 index 000000000..d5a0f4423 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/async/async_executor_pass.cpp @@ -0,0 +1,250 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// template <class Executor, class F, class... Args> +// future<typename result_of<F(Args...)>::type> +// async(Executor& ex, F&& f, Args&&... args); + +#define BOOST_THREAD_VERSION 5 +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#include <iostream> +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/detail/memory.hpp> +#include <boost/thread/csbl/memory/unique_ptr.hpp> +#include <memory> +#include <boost/detail/lightweight_test.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executor.hpp> + +typedef boost::chrono::high_resolution_clock Clock; +typedef boost::chrono::milliseconds ms; + +class A +{ + long data_; + +public: + typedef long result_type; + + explicit A(long i) : + data_(i) + { + } + + long doit() const + { + boost::this_thread::sleep_for(ms(200)); + return data_; + } + long operator()() const + { + boost::this_thread::sleep_for(ms(200)); + return data_; + } +}; + +class MoveOnly +{ +public: + typedef int result_type; + + int value; + +BOOST_THREAD_MOVABLE_ONLY(MoveOnly) + MoveOnly() + { + value = 0; + } + MoveOnly( BOOST_THREAD_RV_REF(MoveOnly)) + { + value = 1; + } + MoveOnly& operator=(BOOST_THREAD_RV_REF(MoveOnly)) + { + value = 2; + return *this; + } + + int operator()() + { + boost::this_thread::sleep_for(ms(200)); + return 3; + } + template <typename OS> + friend OS& operator<<(OS& os, MoveOnly const& v) + { + os << v.value; + return os; + } + }; + + namespace boost + { +BOOST_THREAD_DCL_MOVABLE (MoveOnly) + } + +int f0() +{ + boost::this_thread::sleep_for(ms(200)); + return 3; +} + +int i = 0; + +int& f1() +{ + boost::this_thread::sleep_for(ms(200)); + return i; +} + +void f2() +{ + boost::this_thread::sleep_for(ms(200)); +} + +boost::csbl::unique_ptr<int> f3_0() +{ + boost::this_thread::sleep_for(ms(200)); + boost::csbl::unique_ptr<int> r( (new int(3))); + return boost::move(r); +} +MoveOnly f3_1() +{ + boost::this_thread::sleep_for(ms(200)); + MoveOnly r; + return boost::move(r); +} + +boost::csbl::unique_ptr<int> f3(int i) +{ + boost::this_thread::sleep_for(ms(200)); + return boost::csbl::unique_ptr<int>(new int(i)); +} + +boost::csbl::unique_ptr<int> f4( + BOOST_THREAD_RV_REF_BEG boost::csbl::unique_ptr<int> BOOST_THREAD_RV_REF_END p +) +{ + boost::this_thread::sleep_for(ms(200)); + return boost::move(p); +} + +struct check_timer { + boost::chrono::nanoseconds delay; + Clock::time_point start; + check_timer(boost::chrono::nanoseconds delay) + : delay(delay) + , start(Clock::now()) + { + } + ~check_timer() { + Clock::time_point now = Clock::now(); + BOOST_TEST(now - start < delay); + std::cout << __FILE__ << "[" << __LINE__ << "] " << (now - start).count() << std::endl; + } + +}; + +int main() +{ + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + { + try + { + boost::executor_adaptor<boost::basic_thread_pool> ex(1); + boost::future<int> f = boost::async(ex, &f0); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && defined BOOST_THREAD_PROVIDES_EXECUTORS + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::executor_adaptor<boost::basic_thread_pool> ex(1); + boost::future<long> f = boost::async(ex, A(3)); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } +#endif +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && defined BOOST_THREAD_PROVIDES_EXECUTORS + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::executor_adaptor<boost::basic_thread_pool> ex(1); + MoveOnly mo; + boost::future<int> f = boost::async(ex, boost::move(mo)); + //boost::future<int> f = boost::async(ex, MoveOnly()); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/futures/async/async_pass.cpp b/src/boost/libs/thread/test/sync/futures/async/async_pass.cpp new file mode 100644 index 000000000..86fdfdbec --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/async/async_pass.cpp @@ -0,0 +1,903 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// template <class F, class... Args> +// future<typename result_of<F(Args...)>::type> +// async(F&& f, Args&&... args); + +// template <class F, class... Args> +// future<typename result_of<F(Args...)>::type> +// async(launch policy, F&& f, Args&&... args); + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#include <iostream> +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/detail/memory.hpp> +#include <boost/thread/csbl/memory/unique_ptr.hpp> +#include <memory> +#include <boost/detail/lightweight_test.hpp> + +typedef boost::chrono::high_resolution_clock Clock; +typedef boost::chrono::milliseconds ms; + +class A +{ + long data_; + +public: + typedef long result_type; + + explicit A(long i) : + data_(i) + { + } + + long doit() const + { + boost::this_thread::sleep_for(ms(200)); + return data_; + } + long operator()() const + { + boost::this_thread::sleep_for(ms(200)); + return data_; + } +}; + +class MoveOnly +{ +public: + typedef int result_type; + + int value; + + BOOST_THREAD_MOVABLE_ONLY(MoveOnly) + MoveOnly() + { + value = 0; + } + MoveOnly( BOOST_THREAD_RV_REF(MoveOnly)) + { + value = 1; + } + MoveOnly& operator=(BOOST_THREAD_RV_REF(MoveOnly)) + { + value = 2; + return *this; + } + + int operator()() const + { + boost::this_thread::sleep_for(ms(200)); + return 3; + } + template <typename OS> + friend OS& operator<<(OS& os, MoveOnly const& v) + { + os << v.value; + return os; + } +}; + +namespace boost +{ + BOOST_THREAD_DCL_MOVABLE (MoveOnly) +} + +int f0() +{ + boost::this_thread::sleep_for(ms(200)); + return 3; +} + +int i = 0; + +int& f1() +{ + boost::this_thread::sleep_for(ms(200)); + return i; +} + +void f2() +{ + boost::this_thread::sleep_for(ms(200)); +} + +boost::csbl::unique_ptr<int> f3_0() +{ + boost::this_thread::sleep_for(ms(200)); + boost::csbl::unique_ptr<int> r( (new int(3))); + return boost::move(r); +} +MoveOnly f3_1() +{ + boost::this_thread::sleep_for(ms(200)); + MoveOnly r; + return boost::move(r); +} + +boost::csbl::unique_ptr<int> f3(int i) +{ + boost::this_thread::sleep_for(ms(200)); + return boost::csbl::unique_ptr<int>(new int(i)); +} + +boost::csbl::unique_ptr<int> f4( + BOOST_THREAD_RV_REF_BEG boost::csbl::unique_ptr<int> BOOST_THREAD_RV_REF_END p +) +{ + boost::this_thread::sleep_for(ms(200)); + return boost::move(p); +} + +struct check_timer { + boost::chrono::nanoseconds delay; + Clock::time_point start; + check_timer(boost::chrono::nanoseconds delay) + : delay(delay) + , start(Clock::now()) + { + } + ~check_timer() { + Clock::time_point now = Clock::now(); + BOOST_TEST(now - start < delay); + std::cout << __FILE__ << "[" << __LINE__ << "] " << (now - start).count() << std::endl; + } + +}; + +int main() +{ + { + try { + boost::async(f0); + } catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + { + try { + boost::async(boost::launch::async, f0); + } catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try { + boost::async(boost::launch::deferred, f0); + } catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int> f = boost::async(f0); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::shared_future<int> f = boost::async(f0).share(); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int> f = boost::async(boost::launch::async, f0); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<long> f = boost::async(boost::launch::async, A(3)); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<long> f = boost::async(boost::launch::deferred, A(3)); + //boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } +#endif +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + A a(3); + boost::future<long> f = boost::async(boost::launch::async, &A::doit, &a); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + A a(3); + boost::future<long> f = boost::async(boost::launch::deferred, &A::doit, &a); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int> f = boost::async(boost::launch::async, BOOST_THREAD_MAKE_RV_REF(MoveOnly())); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int> f = boost::async(boost::launch::deferred, BOOST_THREAD_MAKE_RV_REF(MoveOnly())); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int> f = boost::async(boost::launch::any, f0); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<int> f = boost::async(boost::launch::deferred, f0); + //boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int&> f = boost::async(f1); + boost::this_thread::sleep_for(ms(300)); + int* res; + { + check_timer timer(ms(500)); + res = &f.get(); + } + BOOST_TEST(res == &i); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int&> f = boost::async(boost::launch::async, f1); + boost::this_thread::sleep_for(ms(300)); + int* res; + { + check_timer timer(ms(500)); + res = &f.get(); + } + BOOST_TEST(res == &i); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int&> f = boost::async(boost::launch::any, f1); + boost::this_thread::sleep_for(ms(300)); + int* res; + { + check_timer timer(ms(500)); + res = &f.get(); + } + BOOST_TEST(res == &i); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<int&> f = boost::async(boost::launch::deferred, f1); + //boost::this_thread::sleep_for(ms(300)); + int* res; + { + check_timer timer(ms(500)); + res = &f.get(); + } + BOOST_TEST(res == &i); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<void> f = boost::async(f2); + boost::this_thread::sleep_for(ms(300)); + { + check_timer timer(ms(500)); + f.get(); + } + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<void> f = boost::async(boost::launch::async, f2); + boost::this_thread::sleep_for(ms(300)); + { + check_timer timer(ms(500)); + f.get(); + } + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<void> f = boost::async(boost::launch::any, f2); + boost::this_thread::sleep_for(ms(300)); + { + check_timer timer(ms(500)); + f.get(); + } + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<void> f = boost::async(boost::launch::deferred, f2); + //boost::this_thread::sleep_for(ms(300)); + { + check_timer timer(ms(500)); + f.get(); + } + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<MoveOnly> f = boost::async(&f3_1); + boost::this_thread::sleep_for(ms(300)); + MoveOnly res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST_EQ(res.value, 2); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<MoveOnly> f = boost::async(boost::launch::deferred, &f3_1); + //boost::this_thread::sleep_for(ms(300)); + MoveOnly res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST_EQ(res.value, 2); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<MoveOnly> f; + f = boost::async(&f3_1); + boost::this_thread::sleep_for(ms(300)); + MoveOnly res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res.value == 2); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(&f3_0); + boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(boost::launch::async, &f3, 3); + boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(boost::launch::deferred, &f3, 3); + //boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(&f3, 3); + boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(boost::launch::async, &f4, boost::csbl::unique_ptr<int>(new int(3))); + boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(boost::launch::deferred, &f4, boost::csbl::unique_ptr<int>(new int(3))); + //boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(&f4, boost::csbl::unique_ptr<int>(new int(3))); + boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/futures/future/async_deferred_then_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/async_deferred_then_pass.cpp new file mode 100644 index 000000000..b400074cd --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/async_deferred_then_pass.cpp @@ -0,0 +1,153 @@ +// Copyright (C) 2012-2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + + +int p1() +{ + BOOST_THREAD_LOG << "p1 < " << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::future<int> f) +{ + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::future<int> f) +{ + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " <<i << BOOST_THREAD_END_LOG; + return; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + try + { + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + BOOST_TEST(f1.valid()); + { + boost::future<int> f2 = f1.then(&p2); + BOOST_TEST(f2.valid()); + } + BOOST_TEST(! f1.valid()); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(&p2); + BOOST_TEST(f2.valid()); + BOOST_TEST(! f1.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(&p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(boost::launch::deferred, p1).then(&p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::deferred, p1); + boost::future<int> f21 = f1.then(&p2); + boost::future<int> f2= f21.then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::deferred, p1); + boost::future<int> f2= f1.then(&p2).then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(boost::launch::deferred, p1).then(&p2).then(&p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/futures/future/copy_assign_fail.cpp new file mode 100644 index 000000000..170f3a057 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/copy_assign_fail.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// future& operator=(const future&) = delete; + + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::future<T> f0 = p.get_future(); + boost::future<T> f; + f = f0; + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/future/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/futures/future/copy_ctor_fail.cpp new file mode 100644 index 000000000..3a16afd50 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/copy_ctor_fail.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> +// class future<R> + +// future(const future&) = delete; + + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::future<T> f0 = p.get_future(); + boost::future<T> f = f0; + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/future/default_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/default_pass.cpp new file mode 100644 index 000000000..1b4cf392f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/default_pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// future(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::future<int> f; + BOOST_TEST(!f.valid()); + } + { + boost::future<int&> f; + BOOST_TEST(!f.valid()); + } + { + boost::future<void> f; + BOOST_TEST(!f.valid()); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/future/dtor_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/dtor_pass.cpp new file mode 100644 index 000000000..abfca7d8c --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/dtor_pass.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// ~future(); + +#define BOOST_THREAD_VERSION 3 +#include <boost/exception/exception.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" +#endif + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + BOOST_TEST(test_alloc_base::count == 0); + { + typedef int T; + boost::future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<T>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + typedef int& T; + boost::future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + typedef void T; + boost::future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<T>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); +#endif + { + typedef int T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/future/get_or_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/get_or_pass.cpp new file mode 100644 index 000000000..7db938d37 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/get_or_pass.cpp @@ -0,0 +1,187 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// R future::get_or(R&&); +// R& future<R&>::get_or(R&); + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/core/ref.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost +{ +template <typename T> +struct wrap +{ + wrap(T const& v) : value(v){} + T value; + +}; + +template <typename T> +exception_ptr make_exception_ptr(T v) { + return copy_exception(wrap<T>(v)); +} +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(3); +} + +void func2(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3)); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + j = 5; + p.set_value(j); +} + +void func4(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3.5)); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(); +} + +void func6(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(4)); +} + + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef int T; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#else + p.set_value(3); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST(f.get_or(4) == 3); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future<T> f = p.get_future(); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func2, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3)); +#endif + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + try + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(f.get_or(4) == 4); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + catch (...) + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(!f.valid()); +#endif + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef int& T; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#else + int j=5; + p.set_value(j); +#endif + BOOST_TEST(f.valid()); + int k=4; + BOOST_TEST(f.get_or(boost::ref(k)) == 5); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func4, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3.5)); +#endif + try + { + BOOST_TEST(f.valid()); + int j=4; + BOOST_TEST(f.get_or(boost::ref(j)) == 4); + } + catch (...) + { + BOOST_TEST(false); + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/get_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/get_pass.cpp new file mode 100644 index 000000000..ec2ccf8b0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/get_pass.cpp @@ -0,0 +1,268 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// const R& future::get(); +// R& future<R&>::get(); +// void future<void>::get(); + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost +{ +template <typename T> +struct wrap +{ + wrap(T const& v) : value(v){} + T value; + +}; + +template <typename T> +exception_ptr make_exception_ptr(T v) { + return copy_exception(wrap<T>(v)); +} +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(3); +} + +void func2(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3)); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + j = 5; + p.set_value(j); +} + +void func4(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3.5)); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(); +} + +void func6(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(4)); +} + + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef int T; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#else + p.set_value(3); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 3); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future<T> f = p.get_future(); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func2, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3)); +#endif + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + try + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(f.get() == 3); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + catch (boost::wrap<int> const& i) + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(i.value == 3); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + catch (...) + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(!f.valid()); +#endif + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef int& T; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#else + int j=5; + p.set_value(j); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 5); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func4, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3.5)); +#endif + try + { + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 3); + BOOST_TEST(false); + } + catch (boost::wrap<double> const& i) + { + BOOST_TEST(i.value == 3.5); + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func4, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3.5)); +#endif + try + { + BOOST_TEST(f.valid()); + boost::exception_ptr ptr = f.get_exception_ptr(); + } + catch (...) + { + BOOST_TEST(false); + } + BOOST_TEST(f.valid()); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + typedef void T; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#else + p.set_value(); +#endif + BOOST_TEST(f.valid()); + f.get(); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func6, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(4)); +#endif + try + { + BOOST_TEST(f.valid()); + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> const& i) + { + BOOST_TEST(i.value == 4); + } + catch (...) + { + BOOST_TEST(false); + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/move_assign_pass.cpp new file mode 100644 index 000000000..ebb13e5e0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/move_assign_pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <future> + +// class future<R> + +// future& operator=(future&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::future<T> f0; + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::future<T> f0; + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::future<T> f0; + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/futures/future/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/move_ctor_pass.cpp new file mode 100644 index 000000000..8da893a3c --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/move_ctor_pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <future> + +// class future<R> + +// future(future&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::future<T> f0; + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::future<T> f0; + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::future<T> f0; + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/future/share_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/share_pass.cpp new file mode 100644 index 000000000..91c07f5cd --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/share_pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// shared_future<R> share() &&; + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + typedef int T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::future<T> f0; + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::future<T> f0; + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::future<T> f0; + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/future/then_deferred_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/then_deferred_pass.cpp new file mode 100644 index 000000000..0ea37bd7f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/then_deferred_pass.cpp @@ -0,0 +1,137 @@ +// Copyright (C) 2012-2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + BOOST_THREAD_LOG << "p1 < " << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::future<int> f) +{ + assert(f.is_ready()); + + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::future<int> f) +{ + assert(f.is_ready()); + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " <<i << BOOST_THREAD_END_LOG; + return; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(boost::launch::deferred, &p2); + BOOST_TEST(f2.valid()); + BOOST_TEST(! f1.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(boost::launch::deferred, &p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).then(boost::launch::deferred, &p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(p1); + boost::future<int> f21 = f1.then(boost::launch::deferred, &p2); + boost::future<int> f2= f21.then(boost::launch::deferred, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(p1); + boost::future<int> f2= f1.then(boost::launch::deferred, &p2).then(boost::launch::deferred, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).then(boost::launch::deferred, &p2).then(boost::launch::deferred, &p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/then_executor_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/then_executor_pass.cpp new file mode 100644 index 000000000..fcb062a0e --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/then_executor_pass.cpp @@ -0,0 +1,152 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 5 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executor.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + BOOST_THREAD_LOG << "p1 < " << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::future<int> f) +{ + assert(f.is_ready()); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::future<int> f) +{ + assert(f.is_ready()); + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " <<i << BOOST_THREAD_END_LOG; + return; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(ex, &p2); + BOOST_TEST(f2.valid()); + BOOST_TEST(! f1.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(ex, &p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f2 = boost::async(p1).then(ex, &p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f1 = boost::async(p1); + boost::future<int> f21 = f1.then(ex, &p2); + boost::future<int> f2= f21.then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f1 = boost::async(p1); + boost::future<int> f21 = f1.then(ex, &p2); + boost::future<int> f2= f21.then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f1 = boost::async(p1); + boost::future<int> f2= f1.then(&p2).then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f2 = boost::async(p1).then(ex, &p2).then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/then_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/then_pass.cpp new file mode 100644 index 000000000..12270679b --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/then_pass.cpp @@ -0,0 +1,133 @@ +// Copyright (C) 2012-2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + BOOST_THREAD_LOG << "p1 < " << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::future<int> f) +{ + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::future<int> f) +{ + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " <<i << BOOST_THREAD_END_LOG; + return; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(&p2); + BOOST_TEST(f2.valid()); + BOOST_TEST(! f1.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(&p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).then(&p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(p1); + boost::future<int> f21 = f1.then(&p2); + boost::future<int> f2= f21.then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(p1); + boost::future<int> f2= f1.then(&p2).then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).then(&p2).then(&p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/wait_for_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/wait_for_pass.cpp new file mode 100644 index 000000000..71bca7abe --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/wait_for_pass.cpp @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// template <class Rep, class Period> +// future_status +// wait_for(const chrono::duration<Rep, Period>& rel_time) const; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> +#include "../../../timming.hpp" + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func3(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func5(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/wait_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/wait_pass.cpp new file mode 100644 index 000000000..daa9b376f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/wait_pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// template <class Rep, class Period> +// void wait() const; + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#else + func3(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#else + func5(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/wait_until_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/wait_until_pass.cpp new file mode 100644 index 000000000..e9351671d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/wait_until_pass.cpp @@ -0,0 +1,175 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// template <class Rep, class Period> +// future_status +// wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func3(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func5(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/make_ready_future_pass.cpp b/src/boost/libs/thread/test/sync/futures/make_ready_future_pass.cpp new file mode 100644 index 000000000..dfce3cde7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/make_ready_future_pass.cpp @@ -0,0 +1,157 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011,2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// future<void> make_ready_future(); +// template <class T> +// future<decay_t<T>> make_ready_future(T&&); +// template <class T> +// future<T> make_ready_future(remove_reference_t<T>&); +// template <class T> +// future<T> make_ready_future(remove_reference_t<T>&&); +// template <class T, class ...Args> +// future<T> make_ready_future(Args&& ... args); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +struct A +{ + A() : + value(0) + { + } + A(int i) : + value(i) + { + } + A(int i, int j) : + value(i+j) + { + } + int value; +}; + +A make(int i) { + return A(i); +} +A make(int i, int j) { + return A(i, j); +} + +struct movable2 +{ + int value_; + BOOST_THREAD_MOVABLE_ONLY(movable2) + movable2() : value_(1){} + movable2(int i) : value_(i){} + movable2(int i, int j) : value_(i+j){} + + //Move constructor and assignment + movable2(BOOST_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; } + + movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; return *this; } + + bool moved() const //Observer + { return !value_; } + + int value() const //Observer + { return value_; } +}; + + +movable2 move_return_function2(int i) { + return movable2(i); +} + +int main() +{ +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true)); + BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == true)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == false)); +#endif + + { + boost::future<void> f = boost::make_ready_future(); + f.wait(); + } + { + typedef A T; + T i; + boost::future<T> f = boost::make_ready_future(i); + BOOST_TEST(f.get().value==0); + } +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + { + typedef A T; + boost::future<T> f = boost::make_ready_future<T>(); + BOOST_TEST(f.get().value==0); + } + { + typedef A T; + boost::future<T> f = boost::make_ready_future<T>(1); + BOOST_TEST(f.get().value==1); + } + { + typedef A T; + boost::future<T> f = boost::make_ready_future<T>(1,2); + BOOST_TEST(f.get().value==3); + } + { + typedef A T; + T i; + boost::future<T&> f = boost::make_ready_future<T&>(i); + BOOST_TEST(f.get().value==0); + } +#endif +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +// sync/futures/make_ready_future_pass.cpp:125:65: erreur: conversion from Ôboost::future<boost::rv<movable2> >Õ to non-scalar type Ôboost::future<movable2>Õ requested + { + typedef movable2 T; + T i; + boost::future<T> f = boost::make_ready_future(boost::move(i)); + BOOST_TEST_EQ(f.get().value(),1); + } +#endif +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + { + typedef movable2 T; + boost::future<T> f = boost::make_ready_future<T>(); + BOOST_TEST(f.get().value()==1); + } + { + typedef movable2 T; + boost::future<T> f = boost::make_ready_future<T>(1); + BOOST_TEST(f.get().value()==1); + } + { + typedef movable2 T; + boost::future<T> f = boost::make_ready_future<T>(1,2); + BOOST_TEST(f.get().value()==3); + } +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/alloc_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/alloc_ctor_pass.cpp new file mode 100644 index 000000000..e83c06446 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/alloc_ctor_pass.cpp @@ -0,0 +1,181 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// template <class F, class Allocator> +// explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f); + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" + +double fct() +{ + return 5.0; +} +long lfct() +{ + return 5; +} + +class A +{ + long data_; + +public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(A) + static int n_moves; + static int n_copies; + static int n_instances; + static int n_destroy; + + explicit A(long i) : data_(i) + { + ++n_instances; + } + A(BOOST_THREAD_RV_REF(A) a) : data_(BOOST_THREAD_RV(a).data_) + { + ++n_instances; + ++n_moves; BOOST_THREAD_RV(a).data_ = -1; + } + A& operator=(BOOST_THREAD_RV_REF(A) a) + { + data_ = BOOST_THREAD_RV(a).data_; + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + return *this; + } + A(const A& a) : data_(a.data_) + { + ++n_instances; + ++n_copies; + } + A& operator=(BOOST_THREAD_COPY_ASSIGN_REF(A) a) + { + data_ = a.data_; + ++n_copies; + return *this; + } + ~A() + { + --n_instances; + ++n_destroy; + } + + long operator()() const + { return data_;} + long operator()(long i, long j) const + { return data_ + i + j;} +}; + +int A::n_moves = 0; +int A::n_copies = 0; +int A::n_instances = 0; +int A::n_destroy = 0; + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::allocator_arg, + test_allocator<A>(), BOOST_THREAD_MAKE_RV_REF(A(5))); + BOOST_TEST(test_alloc_base::count > 0); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + BOOST_TEST(A::n_copies == 0); + BOOST_TEST(A::n_moves > 0); + BOOST_TEST(A::n_instances == 0); + BOOST_TEST(A::n_destroy > 0); + BOOST_TEST(test_alloc_base::count == 0); + A::n_copies = 0; + A::n_moves = 0; + { + A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::allocator_arg, + test_allocator<A>(), a); + BOOST_TEST(test_alloc_base::count > 0); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + //BOOST_TEST(A::n_copies > 0); + //BOOST_TEST(A::n_moves > 0); + BOOST_TEST(test_alloc_base::count == 0); + A::n_copies = 0; + A::n_moves = 0; + { + const A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::allocator_arg, + test_allocator<A>(), a); + BOOST_TEST(test_alloc_base::count > 0); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + //BOOST_TEST(A::n_copies > 0); + //BOOST_TEST(A::n_moves > 0); + BOOST_TEST(test_alloc_base::count == 0); + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::allocator_arg, + test_allocator<A>(), fct); + BOOST_TEST(test_alloc_base::count > 0); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::allocator_arg, + test_allocator<A>(), &lfct); + BOOST_TEST(test_alloc_base::count > 0); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + + return boost::report_errors(); +} + +#else +int main() +{ + return boost::report_errors(); +} +#endif + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/copy_assign_fail.cpp new file mode 100644 index 000000000..7f068eced --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/copy_assign_fail.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// packaged_task& operator=(packaged_task&) = delete; + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p = p0; + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/copy_ctor_fail.cpp new file mode 100644 index 000000000..22a174961 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/copy_ctor_fail.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// packaged_task(packaged_task&) = delete; + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(p0); + + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/default_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/default_ctor_pass.cpp new file mode 100644 index 000000000..7ab9f1e7c --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/default_ctor_pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// packaged_task(); + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE int() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE int +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <string> + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + BOOST_TEST(!p.valid()); + + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/dtor_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/dtor_pass.cpp new file mode 100644 index 000000000..89620ad05 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/dtor_pass.cpp @@ -0,0 +1,108 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// ~packaged_task(); + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 + + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double(int, char) +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 + 3 +'a' +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double() +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#endif +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#endif + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + +void func(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> ) +{ +} + +void func2(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p) +{ +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif +} + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func, boost::move(p)).detach(); +#else + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE>* p2=new boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE>(boost::move(p)); + delete p2; +#endif + try + { + f.get(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::broken_promise)); + } + } + { + std::cout << __LINE__ << std::endl; + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func2, boost::move(p)).detach(); +#else + p(); +#endif + std::cout << __LINE__ << std::endl; + BOOST_TEST(f.get() == BOOST_THREAD_DETAIL_SIGNATURE_2_RES); + std::cout << __LINE__ << std::endl; + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/func_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/func_ctor_pass.cpp new file mode 100644 index 000000000..a4bd3105f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/func_ctor_pass.cpp @@ -0,0 +1,378 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// template <class F> +// explicit packaged_task(F&& f); + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#define BOOST_THREAD_DETAIL_VOID_SIGNATURE void() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#define BOOST_THREAD_DETAIL_VOID_SIGNATURE void +#endif + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double(int, char) +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 + 3 +'a' +#define BOOST_THREAD_DETAIL_VOID_SIGNATURE_2 void(int) +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double() +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#define BOOST_THREAD_DETAIL_VOID_SIGNATURE_2 void() +#endif +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#define BOOST_THREAD_DETAIL_VOID_SIGNATURE_2 void +#endif + +void void_fct() +{ + return; +} +double fct() +{ + return 5.0; +} +long lfct() +{ + return 5; +} + +class A +{ +public: + long data_; + + static int n_moves; + static int n_copies; + BOOST_THREAD_COPYABLE_AND_MOVABLE(A) + static void reset() + { + n_moves=0; + n_copies=0; + } + + explicit A(long i) : data_(i) + { + } + A(BOOST_THREAD_RV_REF(A) a) : data_(BOOST_THREAD_RV(a).data_) + { + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + } + A& operator=(BOOST_THREAD_RV_REF(A) a) + { + data_ = BOOST_THREAD_RV(a).data_; + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + return *this; + } + A(const A& a) : data_(a.data_) + { + ++n_copies; + } + A& operator=(BOOST_THREAD_COPY_ASSIGN_REF(A) a) + { + data_ = a.data_; + ++n_copies; + return *this; + } + ~A() + { + } + + void operator()(int) const + { } + long operator()() const + { return data_;} + long operator()(long i, long j) const + { return data_ + i + j;} +}; + +int A::n_moves = 0; +int A::n_copies = 0; + +class M +{ + +public: + long data_; + static int n_moves; + + BOOST_THREAD_MOVABLE_ONLY(M) + static void reset() { + n_moves=0; + } + explicit M(long i) : data_(i) + { + } + M(BOOST_THREAD_RV_REF(M) a) : data_(BOOST_THREAD_RV(a).data_) + { + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + } + M& operator=(BOOST_THREAD_RV_REF(M) a) + { + data_ = BOOST_THREAD_RV(a).data_; + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + return *this; + } + ~M() + { + } + + void operator()(int) const + { } + long operator()() const + { return data_;} + long operator()(long i, long j) const + { return data_ + i + j;} +}; + +int M::n_moves = 0; + +class C +{ +public: + long data_; + + static int n_copies; + static void reset() + { + n_copies=0; + } + + explicit C(long i) : data_(i) + { + } + C(const C& a) : data_(a.data_) + { + ++n_copies; + } + C& operator=(C const& a) + { + data_ = a.data_; + ++n_copies; + return *this; + } + ~C() + { + } + + void operator()(int) const + { } + long operator()() const + { return data_;} + long operator()(long i, long j) const + { return data_ + i + j;} +}; +int C::n_copies = 0; + +int main() +{ + { + A::reset(); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(A(5))); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif + BOOST_TEST(f.get() == BOOST_THREAD_DETAIL_SIGNATURE_2_RES); + BOOST_TEST(A::n_copies == 0); + BOOST_TEST_EQ(A::n_moves, 1); + } + { + A::reset(); + A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + BOOST_TEST_EQ(A::n_copies, 1); + BOOST_TEST_EQ(A::n_moves, 0); + } + { + A::reset(); + const A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + BOOST_TEST_EQ(A::n_copies, 1); + BOOST_TEST_EQ(A::n_moves, 0); + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + A::reset(); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(A(5))); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST(A::n_copies == 0); + BOOST_TEST_EQ(A::n_moves, 1); + } + { + A::reset(); + A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(A::n_copies, 1); + BOOST_TEST_EQ(A::n_moves, 0); + } + { + A::reset(); + const A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(A::n_copies, 1); + BOOST_TEST_EQ(A::n_moves, 0); + } +#endif + { + M::reset(); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(M(5))); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif + BOOST_TEST(f.get() == BOOST_THREAD_DETAIL_SIGNATURE_2_RES); + BOOST_TEST_EQ(M::n_moves, 1); + } + { + M::reset(); + M a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::move(a)); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + BOOST_TEST_EQ(M::n_moves, 1); + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + M::reset(); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(M(5))); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(M::n_moves, 1); + } + { + M::reset(); + M a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(boost::move(a)); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(M::n_moves, 1); + } +#endif + { + C::reset(); + C a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + BOOST_TEST_EQ(C::n_copies, 1); + } + + { + C::reset(); + const C a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + BOOST_TEST_EQ(C::n_copies, 1); + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + C::reset(); + C a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(C::n_copies, 1); + } + + { + C::reset(); + const C a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(C::n_copies, 1); + } +#endif + { + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE> p(void_fct); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(fct); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(&lfct); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/get_future_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/get_future_pass.cpp new file mode 100644 index 000000000..7b2985794 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/get_future_pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// future<R> get_future(); + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::future_already_retrieved)); + } + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + try + { + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp new file mode 100644 index 000000000..08db7bbf2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp @@ -0,0 +1,189 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// packaged_task(packaged_task&& other); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO && \ + defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && \ + defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + +class E : public std::exception +{ +public: + long data; + explicit E(long i) : + data(i) + { + } + + const char* what() const throw() { return ""; } + + ~E() throw() {} +}; +class A +{ + long data_; + +public: + explicit A(long i) : + data_(i) + { + } + + long operator()(long i, long j) const + { + if (j == 'z') BOOST_THROW_EXCEPTION( E(6) ); + return data_ + i + j; + } +}; + +void func0_mv(BOOST_THREAD_RV_REF(boost::packaged_task<double(int, char)>) p) +//void func0(boost::packaged_task<double(int, char)> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.make_ready_at_thread_exit(3, 'a'); +} +void func0(boost::packaged_task<double(int, char)> *p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p->make_ready_at_thread_exit(3, 'a'); +} +void func1(boost::packaged_task<double(int, char)> *p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p->make_ready_at_thread_exit(3, 'z'); +} + +void func2(boost::packaged_task<double(int, char)> *p) +{ + p->make_ready_at_thread_exit(3, 'a'); + try + { + p->make_ready_at_thread_exit(3, 'c'); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } +} + +void func3(boost::packaged_task<double(int, char)> *p) +{ + try + { + p->make_ready_at_thread_exit(3, 'a'); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } +} + +int main() +{ + { + boost::packaged_task<double(int, char)> p(A(5)); + boost::future<double> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + boost::thread(func0_mv, boost::move(p)).detach(); +#else + boost::thread(func0, &p).detach(); +#endif + BOOST_TEST(f.get() == 105.0); + } + { + boost::packaged_task<double(int, char)> p2(A(5)); + boost::future<double> f = p2.get_future(); + boost::packaged_task<double(int, char)> p = boost::move(p2); + boost::thread(func0, &p).detach(); + BOOST_TEST(f.get() == 105.0); + } + { + boost::packaged_task<double(int, char)> p(A(5)); + boost::future<double> f = p.get_future(); + //boost::thread(func1, boost::move(p)).detach(); + boost::thread(func1, &p).detach(); + try + { + f.get(); + BOOST_TEST(false); + } + catch (const E& e) + { + BOOST_TEST(e.data == 6); + } + } + { + boost::packaged_task<double(int, char)> p2(A(5)); + boost::future<double> f = p2.get_future(); + boost::packaged_task<double(int, char)> p = boost::move(p2); + boost::thread(func1, &p).detach(); + try + { + f.get(); + BOOST_TEST(false); + } + catch (const E& e) + { + BOOST_TEST(e.data == 6); + } + } + { + boost::packaged_task<double(int, char)> p(A(5)); + boost::future<double> f = p.get_future(); + //boost::thread(func2, boost::move(p)).detach(); + boost::thread(func2, &p).detach(); + BOOST_TEST(f.get() == 105.0); + } + { + boost::packaged_task<double(int, char)> p2(A(5)); + boost::future<double> f = p2.get_future(); + boost::packaged_task<double(int, char)> p = boost::move(p2); + boost::thread(func2, &p).detach(); + BOOST_TEST(f.get() == 105.0); + } + { + boost::packaged_task<double(int, char)> p(A(5)); + //boost::thread t(func3, boost::move(p)); + boost::thread t(func3, &p); + t.join(); + } + { + boost::packaged_task<double(int, char)> p2(A(5)); + boost::packaged_task<double(int, char)> p = boost::move(p2); + boost::thread t(func3, &p); + t.join(); + } + + return boost::report_errors(); +} + +#else +int main() +{ + return boost::report_errors(); +} +//#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/member_swap_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/member_swap_pass.cpp new file mode 100644 index 000000000..fe3c062f8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/member_swap_pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// void swap(packaged_task& other); + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : + data_(i) + { + } + + long operator()() const + { + return data_; + } + long operator()(long i, long j) const + { + return data_ + i + j; + } +}; + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p.swap(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0; + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p.swap(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(!p.valid()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/move_assign_pass.cpp new file mode 100644 index 000000000..fe696c8fb --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/move_assign_pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <future> + +// class promise<R> + +// promise& operator=(promise&& rhs); + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + + +int main() +{ + + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p = boost::move(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + // p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0; + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p = boost::move(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(!p.valid()); + } + + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/move_ctor_pass.cpp new file mode 100644 index 000000000..a5085b311 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/move_ctor_pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// packaged_task(packaged_task&& other); + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p = boost::move(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0; + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p = boost::move(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(!p.valid()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/non_member_swap_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/non_member_swap_pass.cpp new file mode 100644 index 000000000..fb579094d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/non_member_swap_pass.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// template <class R> +// void +// swap(packaged_task<R>& x, packaged_task<R>& y); + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p.swap(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0; + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p.swap(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(!p.valid()); + } + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/operator_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/operator_pass.cpp new file mode 100644 index 000000000..db932f72b --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/operator_pass.cpp @@ -0,0 +1,218 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// void operator()(); + + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double(int, char) +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 + 3 +'a' +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double() +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#endif +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#endif +class E : public std::exception +{ +public: + long data; + explicit E(long i) : + data(i) + { + } + + const char* what() const throw() { return ""; } + + ~E() throw() {} +}; + +class A +{ + long data_; + +public: + explicit A(long i) : + data_(i) + { + } + + long operator()() const + { + if (data_ == 0) BOOST_THROW_EXCEPTION(E(6)); + return data_; + } + long operator()(long i, long j) const + { + if (j == 'z') BOOST_THROW_EXCEPTION(E(6)); + return data_ + i + j; + } + ~A() {} +}; + +void func0(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif +} + +void func1(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'z'); +#else + p(); +#endif +} + +void func2(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p) +{ +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif + try + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'c'); +#else + p(); +#endif + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } +} + +void func3(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p) +{ + try + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } +} + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func0, boost::move(p)).detach(); +#else + //p(); +#endif + //BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(A(0)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#endif + try + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + p(); +#endif + f.get(); + BOOST_TEST(false); + } + catch (const E& e) + { + BOOST_TEST(e.data == 6); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread t(func2, boost::move(p)); +#else + p(); +#endif +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + BOOST_TEST(f.get() == 105); + t.join(); +#else + BOOST_TEST(f.get() == 5.0); +#endif + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread t(func3, boost::move(p)); + t.join(); +#else + try + { + #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); + #else + p(); + #endif + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } +#endif + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/reset_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/reset_pass.cpp new file mode 100644 index 000000000..711e7a57f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/reset_pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// void operator()(); + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : + data_(i) + { + } + + long operator()() const + { + return data_; + } + long operator()(long i, long j) const + { + if (j == 'z') throw A(6); + return data_ + i + j; + } +}; + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + p.reset(); + //p(4, 'a'); + p(); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + try + { + p.reset(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/types_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/types_pass.cpp new file mode 100644 index 000000000..a52fb0439 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/types_pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// template<class R, class... ArgTypes> +// class packaged_task<R(ArgTypes...)> +// { +// public: +// typedef R result_type; + + +#include <boost/thread/future.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct A {}; + +int main() +{ + //BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::packaged_task<A>::result_type, A>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/use_allocator_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/use_allocator_pass.cpp new file mode 100644 index 000000000..ef75b7caa --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/use_allocator_pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class packaged_task<R(ArgTypes...)> + +// template <class Callable, class Alloc> +// struct uses_allocator<packaged_task<Callable>, Alloc> +// : true_type { }; + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" + +int main() +{ + + BOOST_STATIC_ASSERT_MSG((boost::csbl::uses_allocator<boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE>, test_allocator<double> >::value), ""); + + return boost::report_errors(); +} + +#else +int main() +{ + return boost::report_errors(); +} +#endif + + diff --git a/src/boost/libs/thread/test/sync/futures/promise/alloc_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/alloc_ctor_pass.cpp new file mode 100644 index 000000000..0d0c3c0b9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/alloc_ctor_pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// promise(allocator_arg_t, const Allocator& a); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" + +int main() +{ + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<int> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<int&> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<void> p(boost::allocator_arg, test_allocator<void>()); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + + + return boost::report_errors(); +} + +#else +int main() +{ + return boost::report_errors(); +} +#endif + + diff --git a/src/boost/libs/thread/test/sync/futures/promise/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/futures/promise/copy_assign_fail.cpp new file mode 100644 index 000000000..07895578f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/copy_assign_fail.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> +// class promise<R> +// promise& operator=(const promise& rhs) = delete; + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + boost::promise<int> p0; + boost::promise<int> p; + p = p0; + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/promise/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/futures/promise/copy_ctor_fail.cpp new file mode 100644 index 000000000..cfd67a6d7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/copy_ctor_fail.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> +// class promise<R> +// promise& operator=(const promise& rhs) = delete; + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + boost::promise<int> p0; + boost::promise<int> p(p0); + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/promise/default_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/default_pass.cpp new file mode 100644 index 000000000..00198a168 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/default_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// promise(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::promise<int> p; + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + { + boost::promise<int&> p; + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + { + boost::promise<void> p; + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/dtor_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/dtor_pass.cpp new file mode 100644 index 000000000..e449c0378 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/dtor_pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// ~promise(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + typedef int T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p.set_value(3); + } + BOOST_TEST(f.get() == 3); + } + { + typedef int T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + try + { + //T i = + (void)f.get(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::broken_promise)); + } + } + { + typedef int& T; + int i = 4; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p.set_value(i); + } + BOOST_TEST(&f.get() == &i); + } + { + typedef int& T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + try + { + //T i = + (void)f.get(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::broken_promise)); + } + } + { + typedef void T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p.set_value(); + } + f.get(); + BOOST_TEST(true); + } + { + typedef void T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + try + { + f.get(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::broken_promise)); + } + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/emplace_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/emplace_pass.cpp new file mode 100644 index 000000000..6a1a35292 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/emplace_pass.cpp @@ -0,0 +1,207 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011,2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// template <class ...Args> +// void promise::emplace(Args&& ... args); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +struct A +{ + A() : + value(0) + { + } + A(int i) : + value(i) + { + } + A(int i, int j) : + value(i+j) + { + } + BOOST_THREAD_MOVABLE_ONLY(A) + + A(BOOST_THREAD_RV_REF(A) rhs) + { + if(rhs.value==0) + throw 9; + else + { + value=rhs.value; + rhs.value=0; + } + } + A& operator=(BOOST_THREAD_RV_REF(A) rhs) + { + if(rhs.value==0) + throw 9; + else + { + value=rhs.value; + rhs.value=0; + } + return *this; + } + int value; +}; + +A make(int i) { + return A(i); +} +A make(int i, int j) { + return A(i, j); +} + +struct movable2 +{ + int value_; + BOOST_THREAD_MOVABLE_ONLY(movable2) + movable2() : value_(1){} + movable2(int i) : value_(i){} + movable2(int i, int j) : value_(i+j){} + + //Move constructor and assignment + movable2(BOOST_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; } + + movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; return *this; } + + bool moved() const //Observer + { return !value_; } + + int value() const //Observer + { return value_; } +}; + + +movable2 move_return_function2(int i) { + return movable2(i); +} + +int main() +{ +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true)); + BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == true)); +#endif +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.emplace(); + try + { + T a = f.get(); (void)a; + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 9); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.emplace(3); + BOOST_TEST(f.get().value == 3); + try + { + T j(3); + p.set_value(boost::move(j)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + boost::promise<movable2> p; + boost::future<movable2> f = p.get_future(); + p.emplace(3); + BOOST_TEST(f.get().value_ == 3); + try + { + p.emplace(3); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + boost::promise<A> p; + boost::future<A> f = p.get_future(); + p.emplace(1,2); + BOOST_TEST(f.get().value == 3); + try + { + p.emplace(1,2); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + typedef A T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.emplace(3); + boost::promise<T> p2(boost::move(p)); + BOOST_TEST(f.get().value == 3); + + } +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/get_future_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/get_future_pass.cpp new file mode 100644 index 000000000..13a63b13d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/get_future_pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// future<R> get_future(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + boost::promise<double> p; + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p.set_value(105.5); + BOOST_TEST(f.get() == 105.5); + } + { + boost::promise<double> p; + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::future_already_retrieved)); + } + } + { + boost::promise<double> p; + boost::promise<double> p0 = boost::move(p); + try + { + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/move_assign_pass.cpp new file mode 100644 index 000000000..0190527c0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/move_assign_pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <future> + +// class promise<R> + +// promise& operator=(promise&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" +#endif + +boost::mutex m0; +boost::mutex m1; + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<int> p0(boost::allocator_arg, test_allocator<int>()); + boost::promise<int> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 2); + p = boost::move(p0); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + BOOST_TEST(test_alloc_base::count == 1); + } + BOOST_TEST(test_alloc_base::count == 0); + + { + boost::promise<int&> p0(boost::allocator_arg, test_allocator<int>()); + boost::promise<int&> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 2); + p = boost::move(p0); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + BOOST_TEST(test_alloc_base::count == 1); + } + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<void> p0(boost::allocator_arg, test_allocator<void>()); + boost::promise<void> p(boost::allocator_arg, test_allocator<void>()); + BOOST_TEST(test_alloc_base::count == 2); + p = boost::move(p0); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + BOOST_TEST(test_alloc_base::count == 1); + } + BOOST_TEST(test_alloc_base::count == 0); + +#endif + { + boost::promise<int> p0; + boost::promise<int> p; + p = boost::move(p0); + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + { + boost::promise<int&> p0; + boost::promise<int&> p; + p = boost::move(p0); + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + { + boost::promise<void> p0; + boost::promise<void> p; + p = boost::move(p0); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/move_ctor_pass.cpp new file mode 100644 index 000000000..a72eb1829 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/move_ctor_pass.cpp @@ -0,0 +1,151 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <future> + +// class promise<R> + +// promise(promise&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" +#endif + +boost::mutex m; + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<int> p0(boost::allocator_arg, test_allocator<int>()); + boost::promise<int> p(boost::move(p0)); + BOOST_TEST(test_alloc_base::count == 1); + std::cout << __LINE__ << std::endl; + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + std::cout << __LINE__ << std::endl; + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + std::cout << __LINE__ << std::endl; + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + std::cout << __LINE__ << std::endl; + BOOST_TEST(test_alloc_base::count == 1); + } + std::cout << __LINE__ << std::endl; + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<int&> p0(boost::allocator_arg, test_allocator<int>()); + boost::promise<int&> p(boost::move(p0)); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + BOOST_TEST(test_alloc_base::count == 1); + } + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<void> p0(boost::allocator_arg, test_allocator<void>()); + boost::promise<void> p(boost::move(p0)); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + BOOST_TEST(test_alloc_base::count == 1); + } + BOOST_TEST(test_alloc_base::count == 0); +#endif + { + boost::promise<int> p0; + boost::promise<int> p(boost::move(p0)); + std::cout << __LINE__ << std::endl; + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + std::cout << __LINE__ << std::endl; + BOOST_TEST(f.valid()); + std::cout << __LINE__ << std::endl; + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + std::cout << __LINE__ << std::endl; + } + std::cout << __LINE__ << std::endl; + { + boost::promise<int&> p0; + boost::promise<int&> p(boost::move(p0)); + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + { + boost::promise<void> p0; + boost::promise<void> p(boost::move(p0)); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp new file mode 100644 index 000000000..d23d0befb --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise::set_exception_at_thread_exit(exception_ptr p); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +namespace boost +{ + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +void func(boost::promise<int> p) +#else +boost::promise<int> p; +void func() +#endif +{ + //p.set_exception(boost::make_exception_ptr(3)); + p.set_exception_at_thread_exit(boost::make_exception_ptr(3)); +} + +int main() +{ + { + typedef int T; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::promise<T> p; + boost::future<T> f = p.get_future(); + boost::thread(func, boost::move(p)).detach(); +#else + boost::future<T> f = p.get_future(); + boost::thread(func).detach(); +#endif + try + { + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> i) + { + BOOST_TEST(i.value == 3); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int T; + boost::promise<T> p2; + boost::future<T> f = p2.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func, boost::move(p2)).detach(); +#else + p = boost::move(p2); + boost::thread(func).detach(); +#endif + try + { + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> i) + { + BOOST_TEST(i.value == 3); + } + catch (...) + { + BOOST_TEST(false); + } + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_exception_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_exception_pass.cpp new file mode 100644 index 000000000..c27aec293 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_exception_pass.cpp @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void set_exception(exception_ptr p); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +namespace boost +{ + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +int main() +{ + + { + typedef int T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_exception(boost::make_exception_ptr(3)); + try + { + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> i) + { + BOOST_TEST(i.value == 3); + } + try + { + p.set_exception(boost::make_exception_ptr(3)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_exception_deferred(boost::make_exception_ptr(3)); + BOOST_TEST(!f.is_ready()); + p.notify_deferred(); + try + { + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> i) + { + BOOST_TEST(i.value == 3); + } + try + { + p.set_exception(boost::make_exception_ptr(3)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp new file mode 100644 index 000000000..a143dc636 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise<R&>::set_value_at_thread_exit(R& r); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <memory> + +int i = 0; + +//void func(boost::promise<int&> p) +boost::promise<int&> p; +void func() +{ + p.set_value_at_thread_exit(i); + i = 4; +} + +int main() +{ + { + //boost::promise<int&> p; + boost::future<int&> f = p.get_future(); + //boost::thread(func, boost::move(p)).detach(); + boost::thread(func).detach(); + int r = f.get(); + BOOST_TEST(r == 4); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_pass.cpp new file mode 100644 index 000000000..6acfb62d1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_pass.cpp @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise<R&>::set_value(R& r); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +int main() +{ + + { + typedef int& T; + int i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(i); + int& j = f.get(); + BOOST_TEST(j == 3); + ++i; + BOOST_TEST(j == 4); + try + { + p.set_value(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int& T; + int i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(i); + int& j = f.get(); + BOOST_TEST(j == 3); + ++i; + BOOST_TEST(j == 4); + try + { + p.set_value_deferred(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int& T; + int i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value_deferred(i); + BOOST_TEST(!f.is_ready()); + p.notify_deferred(); + int& j = f.get(); + BOOST_TEST(j == 3); + ++i; + BOOST_TEST(j == 4); + try + { + p.set_value_deferred(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int& T; + int i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value_deferred(i); + BOOST_TEST(!f.is_ready()); + p.notify_deferred(); + int& j = f.get(); + BOOST_TEST(j == 3); + ++i; + BOOST_TEST(j == 4); + try + { + p.set_value(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp new file mode 100644 index 000000000..0b23b4834 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011,2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise::set_value_at_thread_exit(R&& p); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/thread/detail/memory.hpp> +#include <boost/thread/csbl/memory/unique_ptr.hpp> + +boost::promise<boost::csbl::unique_ptr<int> > p; +boost::promise<boost::csbl::unique_ptr<int> > p2; +void func() +{ + boost::csbl::unique_ptr<int> uptr(new int(5)); + p.set_value_at_thread_exit(boost::move(uptr)); +} +void func2() +{ + p2.set_value_at_thread_exit(boost::csbl::make_unique<int>(5)); +} + +int main() +{ + { + boost::future<boost::csbl::unique_ptr<int> > f = p.get_future(); + boost::thread(func).detach(); + BOOST_TEST(*f.get() == 5); + } + { + boost::future<boost::csbl::unique_ptr<int> > f = p2.get_future(); + boost::thread(func2).detach(); + BOOST_TEST(*f.get() == 5); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_pass.cpp new file mode 100644 index 000000000..63260d726 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_pass.cpp @@ -0,0 +1,297 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011,2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise::set_value(R&& r); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +struct A +{ + A() : + value(0) + { + } + A(int i) : + value(i) + { + } + BOOST_THREAD_MOVABLE_ONLY(A) + + A(BOOST_THREAD_RV_REF(A) rhs) + { + if(rhs.value==0) + throw 9; + else + { + value=rhs.value; + rhs.value=0; + } + } + A& operator=(BOOST_THREAD_RV_REF(A) rhs) + { + if(rhs.value==0) + throw 9; + else + { + value=rhs.value; + rhs.value=0; + } + return *this; + } + int value; +}; + +A make(int i) { + return A(i); +} + +struct movable2 +{ + int value_; + BOOST_THREAD_MOVABLE_ONLY(movable2) + movable2() : value_(1){} + movable2(int i) : value_(i){} + + //Move constructor and assignment + movable2(BOOST_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; } + + movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; return *this; } + + bool moved() const //Observer + { return !value_; } + + int value() const //Observer + { return value_; } +}; + + +movable2 move_return_function2(int i) { + return movable2(i); +} + +int main() +{ +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true)); + BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == true)); +#endif + + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + try + { + p.set_value(boost::move(i)); + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 9); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + try + { + p.set_value_deferred(boost::move(i)); + BOOST_TEST(!f.is_ready()); + p.notify_deferred(); + + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 9); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + try + { + p.set_value((T())); + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 9); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + try + { + p.set_value_deferred((T())); + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 9); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + T i(3); + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(boost::move(i)); + BOOST_TEST(f.get().value == 3); + try + { + T j(3); + p.set_value(boost::move(j)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + movable2 i(3); + boost::promise<movable2> p; + boost::future<movable2> f = p.get_future(); + p.set_value(move_return_function2(3)); + BOOST_TEST(f.get().value_ == 3); + try + { + movable2 j(3); + p.set_value(boost::move(j)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + boost::promise<A> p; + boost::future<A> f = p.get_future(); + p.set_value(make(3)); + BOOST_TEST(f.get().value == 3); + try + { + A j(3); + p.set_value(boost::move(j)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + typedef A T; + T i(3); + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(boost::move(i)); + BOOST_TEST(i.value == 0); + boost::promise<T> p2(boost::move(p)); + BOOST_TEST(f.get().value == 3); + + } + { + typedef A T; + T i(3); + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(boost::move(i)); + BOOST_TEST(i.value == 0); + boost::promise<T> p2(boost::move(p)); + boost::future<T> f2(boost::move(f)); + BOOST_TEST(f2.get().value == 3); + + } + { + typedef A T; + T i(3); + boost::promise<T> p; + p.set_value(boost::move(i)); + BOOST_TEST(i.value == 0); + boost::promise<T> p2(boost::move(p)); + boost::future<T> f = p2.get_future(); + BOOST_TEST(f.get().value == 3); + + } + + { + typedef boost::future<int> T; + boost::promise<int> pi; + T fi=pi.get_future(); + pi.set_value(3); + + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(boost::move(fi)); + boost::future<T> f2(boost::move(f)); + BOOST_TEST(f2.get().get() == 3); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp new file mode 100644 index 000000000..4972cb7d8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise::set_value_at_thread_exit(const R& r); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +void func(boost::promise<int> p) +#else +boost::promise<int> p; +void func() +#endif +{ + const int i = 5; + p.set_value_at_thread_exit(i); +} + +int main() +{ + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::promise<int> p; + boost::future<int> f = p.get_future(); + boost::thread(func, boost::move(p)).detach(); +#else + boost::future<int> f = p.get_future(); + boost::thread(func).detach(); +#endif + try + { + BOOST_TEST(f.get() == 5); + } + catch (...) + { + BOOST_TEST(false); + } + } + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + boost::promise<int> p2; + boost::future<int> f = p2.get_future(); + p = boost::move(p2); + boost::thread(func).detach(); + BOOST_TEST(f.get() == 5); +#endif + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp new file mode 100644 index 000000000..c79f2a23e --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise<void>::set_value_at_thread_exit(); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int i = 0; + +boost::promise<void> p; +void func() +{ + p.set_value_at_thread_exit(); + i = 1; +} + +//void func2_mv(BOOST_THREAD_RV_REF(boost::promise<void>) p2) +void func2_mv(boost::promise<void> p2) +{ + p2.set_value_at_thread_exit(); + i = 2; +} + +void func2(boost::promise<void> *p2) +{ + p2->set_value_at_thread_exit(); + i = 2; +} +int main() +{ + try + { + boost::future<void> f = p.get_future(); + boost::thread(func).detach(); + f.get(); + BOOST_TEST(i == 1); + + } + catch(std::exception& ) + { + BOOST_TEST(false); + } + catch(...) + { + BOOST_TEST(false); + } + + try + { + boost::promise<void> p2; + boost::future<void> f = p2.get_future(); + p = boost::move(p2); + boost::thread(func).detach(); + f.get(); + BOOST_TEST(i == 1); + + } + catch(std::exception& ex) + { + std::cout << __FILE__ << ":" << __LINE__ << " " << ex.what() << std::endl; + BOOST_TEST(false); + } + catch(...) + { + BOOST_TEST(false); + } + + try + { + boost::promise<void> p2; + boost::future<void> f = p2.get_future(); +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + boost::thread(func2_mv, boost::move(p2)).detach(); +#else + boost::thread(func2, &p2).detach(); +#endif + f.wait(); + f.get(); + BOOST_TEST(i == 2); + } + catch(std::exception& ex) + { + std::cout << __FILE__ << ":" << __LINE__ << " " << ex.what() << std::endl; + BOOST_TEST(false); + } + catch(...) + { + BOOST_TEST(false); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_value_const_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_value_const_pass.cpp new file mode 100644 index 000000000..84f2fb273 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_value_const_pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise::set_value(const R& r); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> +#include <boost/config.hpp> + +#ifdef BOOST_MSVC +# pragma warning(disable: 4702) // unreachable code +#endif + +struct A +{ + A() + { + } + A(const A&) + { + throw 10; + } +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + A& operator= (const A&) = default; +#endif +}; + +int main() +{ + + { + typedef int T; + T i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(i); + ++i; + BOOST_TEST(f.get() == 3); + --i; + try + { + p.set_value(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int T; + T i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value_deferred(i); + p.notify_deferred(); + ++i; + BOOST_TEST(f.get() == 3); + --i; + try + { + p.set_value(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + try + { + p.set_value(i); + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 10); + } + catch (...) + { + BOOST_TEST(false); + } + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_value_void_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_value_void_pass.cpp new file mode 100644 index 000000000..7c11d5b66 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_value_void_pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise<void>::set_value(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +struct A +{ + A() + { + } + A(const A&) + { + throw 10; + } +}; + +int main() +{ + + { + typedef void T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(); + f.get(); + try + { + p.set_value(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value_deferred(); + p.notify_deferred(); + f.get(); + try + { + p.set_value(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/use_allocator_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/use_allocator_pass.cpp new file mode 100644 index 000000000..3b1e96c7e --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/use_allocator_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class promise<R> + +// promise(allocator_arg_t, const Allocator& a); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" + +int main() +{ + + BOOST_STATIC_ASSERT_MSG((boost::csbl::uses_allocator<boost::promise<int>, test_allocator<int> >::value), ""); + BOOST_STATIC_ASSERT_MSG((boost::csbl::uses_allocator<boost::promise<int&>, test_allocator<int&> >::value), ""); + BOOST_STATIC_ASSERT_MSG((boost::csbl::uses_allocator<boost::promise<void>, test_allocator<void> >::value), ""); + + return boost::report_errors(); +} + +#else +int main() +{ + return boost::report_errors(); +} +#endif + + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/copy_assign_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/copy_assign_pass.cpp new file mode 100644 index 000000000..1b23b2d16 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/copy_assign_pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// shared_future& operator=(const shared_future&); + + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f; + f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + + } + { + typedef int T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = f0; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f; + f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = f0; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f; + f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = f0; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + return boost::report_errors(); +} + +//#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/copy_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/copy_ctor_pass.cpp new file mode 100644 index 000000000..fd29c0fe3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/copy_ctor_pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> +// class shared_future<R> + +// shared_future(const future&); + + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::shared_future < T > f0; + boost::shared_future<T> f = f0; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::shared_future < T > f0; + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::shared_future < T > f0; + boost::shared_future<T> f = f0; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + return boost::report_errors(); +} + +//#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/default_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/default_pass.cpp new file mode 100644 index 000000000..59ecea3a3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/default_pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// shared_future(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::shared_future<int> f; + BOOST_TEST(!f.valid()); + } + { + boost::shared_future<int&> f; + BOOST_TEST(!f.valid()); + } + { + boost::shared_future<void> f; + BOOST_TEST(!f.valid()); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/dtor_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/dtor_pass.cpp new file mode 100644 index 000000000..01fb591c0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/dtor_pass.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// ~shared_future(); + +#define BOOST_THREAD_VERSION 3 +#include <boost/exception/exception.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" +#endif + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + BOOST_TEST(test_alloc_base::count == 0); + { + typedef int T; + boost::shared_future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<T>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + typedef int& T; + boost::shared_future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + typedef void T; + boost::shared_future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<T>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); +#endif + { + typedef int T; + boost::shared_future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::shared_future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::shared_future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/get_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/get_pass.cpp new file mode 100644 index 000000000..558fb024f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/get_pass.cpp @@ -0,0 +1,208 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_future.hpp> + +// class shared_future<R> + +// const R& shared_future::get(); +// R& shared_future<R&>::get(); +// void shared_future<void>::get(); +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +namespace boost +{ +template <typename T> +struct wrap +{ + wrap(T const& v) : value(v){} + T value; + +}; + +template <typename T> +exception_ptr make_exception_ptr(T v) { + return copy_exception(wrap<T>(v)); +} +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(3); +} + +void func2(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3)); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + j = 5; + p.set_value(j); +} + +void func4(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3.5)); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(); +} + +void func6(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(4)); +} + + +int main() +{ + { + typedef int T; + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#else + p.set_value(3); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 3); + BOOST_TEST(f.valid()); + } + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func2, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3)); +#endif + try + { + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 3); + BOOST_TEST(false); + } + catch (boost::wrap<int> const& i) + { + BOOST_TEST(i.value == 3); + } + catch (...) + { + BOOST_TEST(false); + } + BOOST_TEST(f.valid()); + } + } + { + typedef int& T; + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#else + int j=5; + p.set_value(j); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 5); + BOOST_TEST(f.valid()); + } + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func4, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3.5)); +#endif + try + { + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 3); + BOOST_TEST(false); + } + catch (boost::wrap<double> const& i) + { + BOOST_TEST(i.value == 3.5); + } + BOOST_TEST(f.valid()); + } + } + + typedef void T; + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#else + p.set_value(); +#endif + BOOST_TEST(f.valid()); + f.get(); + BOOST_TEST(f.valid()); + } + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func6, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(4)); +#endif + try + { + BOOST_TEST(f.valid()); + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> const& i) + { + BOOST_TEST(i.value == 4); + } + catch (...) + { + BOOST_TEST(false); + } + BOOST_TEST(f.valid()); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/move_assign_pass.cpp new file mode 100644 index 000000000..40ff4992c --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/move_assign_pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <future> + +// class shared_future<R> + +// shared_future& shared_future=(shared_future&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/move_ctor_pass.cpp new file mode 100644 index 000000000..533f5ec90 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/move_ctor_pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <future> + +// class shared_future<R> + +// shared_future(shared_future&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::shared_future<T> f0; + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::shared_future<T> f0; + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::shared_future<T> f0; + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/then_executor_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/then_executor_pass.cpp new file mode 100644 index 000000000..73b42fc8a --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/then_executor_pass.cpp @@ -0,0 +1,149 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executor.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + BOOST_THREAD_LOG << "p1 < " << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::shared_future<int> f) +{ + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::shared_future<int> f) +{ + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " << i << BOOST_THREAD_END_LOG; + return ; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(ex, &p2); + BOOST_TEST(f2.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(ex, &p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f2 = boost::async(p1).share().then(ex, &p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::shared_future<int> f1 = boost::async(p1).share(); + boost::shared_future<int> f21 = f1.then(ex, &p2).share(); + boost::future<int> f2= f21.then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::shared_future<int> f1 = boost::async(p1).share(); + boost::shared_future<int> f21 = f1.then(ex, &p2).share(); + boost::future<int> f2= f21.then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::shared_future<int> f1 = boost::async(p1).share(); + boost::future<int> f2= f1.then(ex, &p2).share().then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f2 = boost::async(p1).share().then(ex, &p2).share().then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/then_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/then_pass.cpp new file mode 100644 index 000000000..e7cca062e --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/then_pass.cpp @@ -0,0 +1,156 @@ +// Copyright (C) 2012-2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + BOOST_THREAD_LOG << "p1 < " << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::shared_future<int> f) +{ + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::shared_future<int> f) +{ + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " << i << BOOST_THREAD_END_LOG; + return ; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(&p2); + BOOST_TEST(f2.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(&p2); + boost::future<int> f3 = f1.then(&p2); + BOOST_TEST(f2.valid()); + BOOST_TEST(f3.valid()); + try + { + BOOST_TEST(f2.get()==2); + BOOST_TEST(f3.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(&p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).share().then(&p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::shared_future<int> f1 = boost::async(p1).share(); + boost::shared_future<int> f21 = f1.then(&p2).share(); + boost::future<int> f2= f21.then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::shared_future<int> f1 = boost::async(p1).share(); + boost::future<int> f2= f1.then(&p2).share().then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).share().then(&p2).share().then(&p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/wait_for_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/wait_for_pass.cpp new file mode 100644 index 000000000..e9d8ac684 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/wait_for_pass.cpp @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// template <class Rep, class Period> +// future_status +// wait_for(const chrono::duration<Rep, Period>& rel_time) const; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func3(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func5(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/wait_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/wait_pass.cpp new file mode 100644 index 000000000..d2d1b31f6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/wait_pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// template <class Rep, class Period> +// void wait() const; + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#else + func3(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#else + func5(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/wait_until_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/wait_until_pass.cpp new file mode 100644 index 000000000..8b05725e7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/wait_until_pass.cpp @@ -0,0 +1,175 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// template <class Rep, class Period> +// future_status +// wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func3(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func5(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/test_allocator.hpp b/src/boost/libs/thread/test/sync/futures/test_allocator.hpp new file mode 100644 index 000000000..a73d7d8e3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/test_allocator.hpp @@ -0,0 +1,158 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_TEST_ALLOCATOR_HPP +#define BOOST_THREAD_TEST_ALLOCATOR_HPP + +#include <cstddef> +#include <boost/type_traits.hpp> +#include <boost/thread/detail/move.hpp> +#include <cstdlib> +#include <new> +#include <climits> + +class test_alloc_base +{ +public: + static int count; +public: + static int throw_after; +}; + +int test_alloc_base::count = 0; +int test_alloc_base::throw_after = INT_MAX; + +template <class T> +class test_allocator + : public test_alloc_base +{ + int data_; + + template <class U> friend class test_allocator; +public: + + typedef unsigned size_type; + typedef int difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef typename boost::add_lvalue_reference<value_type>::type reference; + typedef typename boost::add_lvalue_reference<const value_type>::type const_reference; + + template <class U> struct rebind {typedef test_allocator<U> other;}; + + test_allocator() throw() : data_(-1) {} + explicit test_allocator(int i) throw() : data_(i) {} + test_allocator(const test_allocator& a) throw() + : data_(a.data_) {} + template <class U> test_allocator(const test_allocator<U>& a) throw() + : data_(a.data_) {} + ~test_allocator() throw() {data_ = 0;} + pointer address(reference x) const {return &x;} + const_pointer address(const_reference x) const {return &x;} + pointer allocate(size_type n, const void* = 0) + { + if (count >= throw_after) + throw std::bad_alloc(); + ++count; + return (pointer)std::malloc(n * sizeof(T)); + } + void deallocate(pointer p, size_type) + {--count; std::free(p);} + size_type max_size() const throw() + {return UINT_MAX / sizeof(T);} + void construct(pointer p, const T& val) + {::new(p) T(val);} + + void construct(pointer p, BOOST_THREAD_RV_REF(T) val) + {::new(p) T(boost::move(val));} + + void destroy(pointer p) {p->~T();} + + friend bool operator==(const test_allocator& x, const test_allocator& y) + {return x.data_ == y.data_;} + friend bool operator!=(const test_allocator& x, const test_allocator& y) + {return !(x == y);} +}; + +template <> +class test_allocator<void> + : public test_alloc_base +{ + int data_; + + template <class U> friend class test_allocator; +public: + + typedef unsigned size_type; + typedef int difference_type; + typedef void value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + + template <class U> struct rebind {typedef test_allocator<U> other;}; + + test_allocator() throw() : data_(-1) {} + explicit test_allocator(int i) throw() : data_(i) {} + test_allocator(const test_allocator& a) throw() + : data_(a.data_) {} + template <class U> test_allocator(const test_allocator<U>& a) throw() + : data_(a.data_) {} + ~test_allocator() throw() {data_ = 0;} + + friend bool operator==(const test_allocator& x, const test_allocator& y) + {return x.data_ == y.data_;} + friend bool operator!=(const test_allocator& x, const test_allocator& y) + {return !(x == y);} +}; + +template <class T> +class other_allocator +{ + int data_; + + template <class U> friend class other_allocator; + +public: + typedef T value_type; + + other_allocator() : data_(-1) {} + explicit other_allocator(int i) : data_(i) {} + template <class U> other_allocator(const other_allocator<U>& a) + : data_(a.data_) {} + T* allocate(std::size_t n) + {return (T*)std::malloc(n * sizeof(T));} + void deallocate(T* p, std::size_t) + {std::free(p);} + + other_allocator select_on_container_copy_construction() const + {return other_allocator(-2);} + + friend bool operator==(const other_allocator& x, const other_allocator& y) + {return x.data_ == y.data_;} + friend bool operator!=(const other_allocator& x, const other_allocator& y) + {return !(x == y);} + + typedef boost::true_type propagate_on_container_copy_assignment; + typedef boost::true_type propagate_on_container_move_assignment; + typedef boost::true_type propagate_on_container_swap; + +#ifdef BOOST_NO_SFINAE_EXPR + std::size_t max_size() const + {return UINT_MAX / sizeof(T);} +#endif // BOOST_NO_SFINAE_EXPR + +}; + +#endif // BOOST_THREAD_TEST_ALLOCATOR_HPP diff --git a/src/boost/libs/thread/test/sync/futures/when_all/iterators_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_all/iterators_pass.cpp new file mode 100644 index 000000000..2646074f0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_all/iterators_pass.cpp @@ -0,0 +1,362 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// template< typename InputIterator> +// future<vector<typename InputIterator::value_type> > +// when_all(InputIterator first, InputIterator last) + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <stdexcept> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + return 123; +} + +int thr() +{ + throw std::logic_error("123"); +} +int p2() +{ + return 321; +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::csbl::vector<boost::future<int> > v; + boost::future<int> f1; + v.push_back(boost::move(f1)); + v.push_back(boost::make_ready_future(321)); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(v[1].valid()); + + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res.size() == 2); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + // has exception + //BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + boost::future<int> f2 = boost::make_ready_future(321); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[0].is_ready()); + BOOST_TEST(v[1].valid()); + BOOST_TEST(v[1].is_ready()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + boost::shared_future<int> f2 = boost::make_ready_future(321).share(); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[0].is_ready()); + BOOST_TEST(v[1].valid()); + BOOST_TEST(v[1].is_ready()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&thr); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + try { + res[0].get(); + BOOST_TEST(false); + } catch (std::logic_error& ex) { + BOOST_TEST(ex.what() == std::string("123")); + } catch (...) { + BOOST_TEST(false); + } + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::shared_future<int> f2 = pt2.get_future().share(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + BOOST_TEST(! all.is_ready()); + pt1(); + BOOST_TEST(! all.is_ready()); + pt2(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(300)); + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<int> f2 = boost::async(boost::launch::deferred, &p2); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share(); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } +#endif +#if ! defined BOOST_NO_CXX11_LAMBDAS + { // async futures copy-constructible then() + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::future<int> sum = all.then([](boost::future<boost::csbl::vector<boost::future<int> > > f) + { + boost::csbl::vector<boost::future<int> > v = f.get(); + return v[0].get() + v[1].get(); + }); + BOOST_TEST(sum.valid()); + BOOST_TEST(sum.get() == 444); + } +#endif +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_all/none_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_all/none_pass.cpp new file mode 100644 index 000000000..613e2368d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_all/none_pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// future<tuple<>> when_all(); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + + { + boost::future<boost::csbl::tuple<> > all = boost::when_all(); + BOOST_TEST(all.valid()); + BOOST_TEST(all.is_ready()); + } +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_all/one_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_all/one_pass.cpp new file mode 100644 index 000000000..026abcf53 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_all/one_pass.cpp @@ -0,0 +1,186 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// template <class T, class Ts> +// future<tuple<T>> when_all(T&&); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <stdexcept> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + return 123; +} + +int thr() +{ + throw std::logic_error("123"); +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::future<int> f1; + BOOST_TEST(! f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + // has exception + //BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + pt1(); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + pt1(); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&thr); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + pt1(); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + try { + boost::csbl::get<0>(res).get(); + BOOST_TEST(false); + } catch (std::logic_error& ex) { + BOOST_TEST(ex.what() == std::string("123")); + } catch (...) { + BOOST_TEST(false); + } + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } +#endif +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_all/variadic_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_all/variadic_pass.cpp new file mode 100644 index 000000000..f3b93b8be --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_all/variadic_pass.cpp @@ -0,0 +1,300 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// template <class T, class Ts> +// future<tuple<T, Ts...>> when_all(T&&, Ts&& ...); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <stdexcept> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); + return 123; +} + +int thr() +{ + throw std::logic_error("123"); +} +int p2() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + return 321; +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::future<int> f1; + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(! f1.valid()); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + // has exception + //BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + boost::shared_future<int> f2 = boost::make_ready_future(321).share(); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&thr); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + try { + boost::csbl::get<0>(res).get(); + BOOST_TEST(false); + } catch (std::logic_error& ex) { + BOOST_TEST(ex.what() == std::string("123")); + } catch (...) { + BOOST_TEST(false); + } + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::shared_future<int> f2 = pt2.get_future().share(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + BOOST_TEST(! all.is_ready()); + pt1(); + BOOST_TEST(! all.is_ready()); + pt2(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(300)); + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<int> f2 = boost::async(boost::launch::deferred, &p2); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share(); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } +#endif +#if ! defined BOOST_NO_CXX11_LAMBDAS + { // async futures copy-constructible then() + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::future<int> sum = all.then([](boost::future<boost::csbl::tuple<boost::future<int>, boost::future<int> > > f) + { + boost::csbl::tuple<boost::future<int>,boost::future<int> > v = f.get(); + return boost::csbl::get<0>(v).get()+boost::csbl::get<1>(v).get(); + }); + BOOST_TEST(sum.valid()); + BOOST_TEST(sum.get() == 444); + } +#endif +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_any/iterators_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_any/iterators_pass.cpp new file mode 100644 index 000000000..03336d022 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_any/iterators_pass.cpp @@ -0,0 +1,363 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// template< typename InputIterator> +// future<vector<typename InputIterator::value_type> > +// when_any(InputIterator first, InputIterator last) + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <stdexcept> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + return 123; +} + +int thr() +{ + throw std::logic_error("123"); +} +int p2() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + return 321; +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::csbl::vector<boost::future<int> > v; + boost::future<int> f1; + v.push_back(boost::move(f1)); + v.push_back(boost::make_ready_future(321)); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(v[1].valid()); + + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res.size() == 2); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + // has exception + //BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + boost::future<int> f2 = boost::make_ready_future(321); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[0].is_ready()); + BOOST_TEST(v[1].valid()); + BOOST_TEST(v[1].is_ready()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + boost::shared_future<int> f2 = boost::make_ready_future(321).share(); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[0].is_ready()); + BOOST_TEST(v[1].valid()); + BOOST_TEST(v[1].is_ready()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&thr); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + try { + res[0].get(); + BOOST_TEST(false); + } catch (std::logic_error& ex) { + BOOST_TEST(ex.what() == std::string("123")); + } catch (...) { + BOOST_TEST(false); + } + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::shared_future<int> f2 = pt2.get_future().share(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + BOOST_TEST(! all.is_ready()); + pt1(); + pt2(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(300)); + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(! res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(! res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + if (0) // fixme + BOOST_TEST(! res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<int> f2 = boost::async(boost::launch::deferred, &p2); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(! res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share(); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(! res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } +#endif +#if ! defined BOOST_NO_CXX11_LAMBDAS + { // async futures copy-constructible then() + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::future<int> sum = all.then([](boost::future<boost::csbl::vector<boost::future<int> > > f) + { + boost::csbl::vector<boost::future<int> > v = f.get(); + return v[0].get() + v[1].get(); + }); + BOOST_TEST(sum.valid()); + BOOST_TEST(sum.get() == 444); + } +#endif +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_any/none_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_any/none_pass.cpp new file mode 100644 index 000000000..2edd0bc6d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_any/none_pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// future<tuple<>> when_any(); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + + { + boost::future<boost::csbl::tuple<> > all = boost::when_any(); + BOOST_TEST(all.valid()); + BOOST_TEST(all.is_ready()); + } +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_any/one_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_any/one_pass.cpp new file mode 100644 index 000000000..61882ef6d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_any/one_pass.cpp @@ -0,0 +1,159 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// future<tuple<T>> when_any(T&&); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + return 123; +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::future<int> f1; + BOOST_TEST(! f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + // has exception + //BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + pt1(); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + pt1(); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } +#endif +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_any/variadic_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_any/variadic_pass.cpp new file mode 100644 index 000000000..09b3951fc --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_any/variadic_pass.cpp @@ -0,0 +1,323 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/future.hpp> + +// template <class T, class Ts> +// future<tuple<T, Ts...>> when_any(T&&, Ts&& ...); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <stdexcept> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + return 123; +} + +int thr() +{ + throw std::logic_error("123"); +} +int p2() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + return 321; +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::future<int> f1; + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(! f1.valid()); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + // has exception + //BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + boost::shared_future<int> f2 = boost::make_ready_future(321).share(); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&thr); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + try { + boost::csbl::get<0>(res).get(); + BOOST_TEST(false); + } catch (std::logic_error& ex) { + BOOST_TEST(ex.what() == std::string("123")); + } catch (...) { + BOOST_TEST(false); + } + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::shared_future<int> f2 = pt2.get_future().share(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + BOOST_TEST(! all.is_ready()); + pt1(); + pt2(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(300)); + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + //BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<int> f2 = boost::async(boost::launch::deferred, &p2); + std::cout << __FILE__ << " " << __LINE__ << std::endl; + + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + std::cout << __FILE__ << " " << __LINE__ << std::endl; + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + std::cout << __FILE__ << " " << __LINE__ << std::endl; + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + std::cout << __FILE__ << " " << __LINE__ << std::endl; + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + //BOOST_TEST(! boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + boost::future<int> f2 = boost::async(boost::launch::deferred, &p2); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + //BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share(); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } +#endif +#if ! defined BOOST_NO_CXX11_LAMBDAS + { // async futures copy-constructible then() + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::future<int> sum = all.then([](boost::future<boost::csbl::tuple<boost::future<int>, boost::future<int> > > f) + { + boost::csbl::tuple<boost::future<int>,boost::future<int> > v = f.get(); + return boost::csbl::get<0>(v).get()+boost::csbl::get<1>(v).get(); + }); + BOOST_TEST(sum.valid()); + BOOST_TEST(sum.get() == 444); + } +#endif +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp new file mode 100644 index 000000000..bd9ff152f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp @@ -0,0 +1,468 @@ +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/sync_deque.hpp> + +// class sync_deque<T> + +// sync_deque(); + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD + +#include <boost/thread/concurrent_queues/sync_deque.hpp> +#include <boost/thread/concurrent_queues/deque_adaptor.hpp> +#include <boost/thread/concurrent_queues/deque_views.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +class non_copyable +{ + int val; +public: + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + +}; + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES +BOOST_STATIC_ASSERT( ! boost::is_copy_constructible<non_copyable>::value ); +BOOST_STATIC_ASSERT( boost::has_move_emulation_enabled<non_copyable>::value ); +#endif + +int main() +{ + + { + // default queue invariants + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // default queue invariants + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + + + { + // empty queue try_pull fails + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + int i; + BOOST_TEST( boost::queue_op_status::empty == q.try_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue/copyable succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + q.push(1); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue/copyable succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + +#if 0 + { + // empty queue push rvalue/non_copyable succeeds + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_back<non_copyable> q(sq); + q.push(non_copyable(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // empty queue push rvalue/non_copyable succeeds + boost::deque_adaptor<boost::sync_deque<non_copyable> > q; + //boost::sync_deque<non_copyable> q; + //boost::deque_back<non_copyable> q(sq); + non_copyable nc(1); + q.push_back(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue push rvalue succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + q.push(1); + q.push(2); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#if 0 + { + // empty queue try_push rvalue/non-copyable succeeds + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_back<non_copyable> q(sq); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // empty queue try_push lvalue succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + int i=0; + BOOST_TEST(boost::queue_op_status::success == q.try_push(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + +#if 0 + { + // empty queue nonblocking_push_back rvalue/non-copyable succeeds + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_back<non_copyable> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // empty queue nonblocking_push_back rvalue/non-copyable succeeds + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_back<non_copyable> q(sq); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc2(2); + q.pull(nc2); + BOOST_TEST_EQ(nc1, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + int i = q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc = q.pull(); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue try_pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue try_pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // 1-element queue nonblocking_pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue nonblocking_pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue wait_pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue wait_pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // closed invariants + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed invariants + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + q.close(); + try { + q.push(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + q.close(); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull_front fails + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/adopt_lock_pass.cpp new file mode 100644 index 000000000..b6039c556 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/adopt_lock_pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(mutex_type& m, adopt_lock_t); + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif +boost::mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#ifdef BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + m.lock(); + boost::lock_guard<boost::mutex> lg(m, boost::adopt_lock); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + m.lock(); + boost::lock_guard<boost::mutex> lg(m, boost::adopt_lock); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#ifdef BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_assign_fail.cpp new file mode 100644 index 000000000..a3957c750 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_assign_fail.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard& operator=(lock_guard const&) = delete; + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::lock_guard<boost::mutex> lk0(m0); + boost::lock_guard<boost::mutex> lk1(m1); + lk1 = lk0; + +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_ctor_fail.cpp new file mode 100644 index 000000000..5c1b3a1c2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_ctor_fail.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(lock_guard const&) = delete; + + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::lock_guard<boost::mutex> lk0(m0); + boost::lock_guard<boost::mutex> lk1 = lk0; +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/default_pass.cpp new file mode 100644 index 000000000..4fcc26a9b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/default_pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(Mutex &); + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#ifdef BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::lock_guard<boost::mutex> lg(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::lock_guard<boost::mutex> lg(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#ifdef BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_fail.cpp new file mode 100644 index 000000000..9aab78ddd --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_fail.cpp @@ -0,0 +1,21 @@ +// Copyright (C) 2018 Tom Hughes +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/lock_guard.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(Mutex& m_, adopt_lock_t) + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +void fail() +{ + boost::lock_guard<boost::mutex> lk(m, boost::adopt_lock); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_pass.cpp new file mode 100644 index 000000000..a158677ad --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_pass.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2018 Tom Hughes +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/lock_guard.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(Mutex& m_, adopt_lock_t) + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +void pass() +{ + m.lock(); + boost::lock_guard<boost::mutex> lk(m, boost::adopt_lock); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_fail.cpp new file mode 100644 index 000000000..eead4501c --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_fail.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2018 Tom Hughes +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/lock_guard.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(Mutex& m_) + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +void fail() +{ + boost::lock_guard<boost::mutex> lk0(m); + boost::lock_guard<boost::mutex> lk1(m); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_pass.cpp new file mode 100644 index 000000000..aee2e40e4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_pass.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2018 Tom Hughes +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/lock_guard.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(Mutex& m_) + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +void pass() +{ + { + boost::lock_guard<boost::mutex> lk0(m); + } + boost::lock_guard<boost::mutex> lk1(m); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_adopt_lock_pass.cpp new file mode 100644 index 000000000..cecdc84ce --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_adopt_lock_pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/lock_guard.hpp> + +// template <class Lockable> +// lock_guard<Lockable> make_lock_guard(Lockable &, adopt_lock_t); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif +boost::mutex m; + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#ifdef BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + m.lock(); + auto&& lg = boost::make_lock_guard(m, boost::adopt_lock); (void)lg; + + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + m.lock(); + auto&& lg = boost::make_lock_guard(m, boost::adopt_lock); (void)lg; + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} +#endif + +int main() +{ +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD + m.lock(); + boost::thread t(f); +#ifdef BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_pass.cpp new file mode 100644 index 000000000..853fae743 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/lock_guard.hpp> + +// template <class Lockable> +// lock_guard<Lockable> make_lock_guard(Lockable &); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD && defined BOOST_THREAD_USES_CHRONO + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + t0 = Clock::now(); + { + const auto&& lg = boost::make_lock_guard(m); (void)lg; + t1 = Clock::now(); + } +} +#endif + +int main() +{ + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD && defined BOOST_THREAD_USES_CHRONO + { + m.lock(); + boost::thread t(f); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } +#endif + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/types_pass.cpp new file mode 100644 index 000000000..7c2d39375 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/types_pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class lock_guard +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::lock_guard<boost::mutex>::mutex_type, + boost::mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp new file mode 100644 index 000000000..c5d9a39b5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class nested_strict_lock; + +// nested_strict_lock& operator=(nested_strict_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::unique_lock<boost::mutex> lk0(m0); + boost::unique_lock<boost::mutex> lk1(m1); + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk0(lk0); + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk1(lk1); + lk1 = lk0; + +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp new file mode 100644 index 000000000..1c0abf94a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class nested_strict_lock; + +// nested_strict_lock(nested_strict_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > lk0(m0); + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > lk1 = lk0; +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/default_pass.cpp new file mode 100644 index 000000000..0182bdd95 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/default_pass.cpp @@ -0,0 +1,79 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class nested_strict_lock; + +// nested_strict_lock(Mutex &); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#ifdef BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + boost::unique_lock<boost::mutex> lg(m); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlg(lg); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + boost::unique_lock<boost::mutex> lg(m); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlg(lg); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + { + m.lock(); + boost::thread t(f); +#ifdef BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp new file mode 100644 index 000000000..5a10728cb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/strict_lock.hpp> + +// template <class Lockable> +// strict_lock<Lockable> make_strict_lock(Lockable &); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK && defined BOOST_THREAD_USES_CHRONO + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + t0 = Clock::now(); + boost::unique_lock<boost::mutex> lg(m); + { + const auto&& nlg = boost::make_nested_strict_lock(lg); (void)nlg; + t1 = Clock::now(); + } +} +#endif + +int main() +{ + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK && defined BOOST_THREAD_USES_CHRONO + { + m.lock(); + boost::thread t(f); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } +#endif + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/owns_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/owns_lock_pass.cpp new file mode 100644 index 000000000..be06b6a06 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/owns_lock_pass.cpp @@ -0,0 +1,60 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class nested_strict_lock; + +// bool owns_lock(Mutex *) const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m; + boost::mutex m2; + { + boost::unique_lock<boost::mutex> lk(m); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk(lk); + BOOST_TEST(nlk.owns_lock(&m) == true); + BOOST_TEST(!nlk.owns_lock(&m2) == true); + } + BOOST_TEST(lk.owns_lock() == true && lk.mutex()==&m); + } + { + m.lock(); + boost::unique_lock<boost::mutex> lk(m, boost::adopt_lock); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk(lk); + BOOST_TEST(nlk.owns_lock(&m) == true); + BOOST_TEST(!nlk.owns_lock(&m2) == true); + } + BOOST_TEST(lk.owns_lock() == true && lk.mutex()==&m); + } + { + boost::unique_lock<boost::mutex> lk(m, boost::defer_lock); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk(lk); + BOOST_TEST(nlk.owns_lock(&m) == true); + BOOST_TEST(!nlk.owns_lock(&m2) == true); + } + BOOST_TEST(lk.owns_lock() == true && lk.mutex()==&m); + } + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk(lk); + BOOST_TEST(nlk.owns_lock(&m) == true); + BOOST_TEST(!nlk.owns_lock(&m2) == true); + } + BOOST_TEST(lk.owns_lock() == true && lk.mutex()==&m); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/types_pass.cpp new file mode 100644 index 000000000..5a7c690e4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/types_pass.cpp @@ -0,0 +1,35 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Lock> +// class nested_strict_lock +// { +// public: +// typedef typename Lock::mutex_type mutex_type; +// ... +// }; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::nested_strict_lock<boost::unique_lock<boost::mutex> >::mutex_type, + boost::mutex>::value), ""); + + BOOST_STATIC_ASSERT_MSG((boost::is_strict_lock<boost::nested_strict_lock<boost::unique_lock<boost::mutex> > >::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_assign_fail.cpp new file mode 100644 index 000000000..408e0f267 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_assign_fail.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class reverse_lock; + +// reverse_lock& operator=(reverse_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/reverse_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_types.hpp> + + +int main() +{ + boost::mutex m0; + boost::mutex m1; + boost::unique_lock<boost::mutex> lk0(m0); + boost::unique_lock<boost::mutex> lk1(m1); + { + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg0(lk0); + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg1(lk1); + lg1 = lg0; + } + +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_ctor_fail.cpp new file mode 100644 index 000000000..c936c11b8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_ctor_fail.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class reverse_lock; + +// reverse_lock(reverse_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/reverse_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_types.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::mutex m0; + boost::unique_lock<boost::mutex> lk0(m0); + { + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg0(lk0); + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg1(lg0); + } +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp new file mode 100644 index 000000000..13a17fd3a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp @@ -0,0 +1,34 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class unlock_guard +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/mutex.hpp> +#include <boost/thread/reverse_lock.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::reverse_lock<boost::unique_lock<boost::mutex> >::mutex_type, + boost::mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/unique_lock_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/unique_lock_ctor_pass.cpp new file mode 100644 index 000000000..57a1f1e01 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/unique_lock_ctor_pass.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unlock_guard; + +// unlock_guard(unlock_guard const&) = delete; + +#include <boost/thread/reverse_lock.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + { + boost::mutex m; + boost::unique_lock<boost::mutex> lk(m); + BOOST_TEST(lk.owns_lock()); + BOOST_TEST(lk.mutex()==&m); + + { + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg(lk); + BOOST_TEST(!lk.owns_lock()); + BOOST_TEST(lk.mutex()==0); + } + BOOST_TEST(lk.owns_lock()); + BOOST_TEST(lk.mutex()==&m); + } + + { + boost::mutex m; + boost::unique_lock<boost::mutex> lk(m, boost::defer_lock); + BOOST_TEST(! lk.owns_lock()); + BOOST_TEST(lk.mutex()==&m); + { + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg(lk); + BOOST_TEST(!lk.owns_lock()); + BOOST_TEST(lk.mutex()==0); + } + BOOST_TEST(lk.owns_lock()); + BOOST_TEST(lk.mutex()==&m); + } + + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/adopt_lock_pass.cpp new file mode 100644 index 000000000..f9089e7a8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/adopt_lock_pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(mutex_type& m, adopt_lock_t); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + boost::shared_mutex m; + m.lock_shared(); + boost::shared_lock<boost::shared_mutex> lk(m, boost::adopt_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_assign_fail.cpp new file mode 100644 index 000000000..2bc99f34b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_assign_fail.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock& operator=(shared_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::shared_lock<boost::shared_mutex> lk0(m0); + boost::shared_lock<boost::shared_mutex> lk1(m1); + lk1 = lk0; + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_ctor_fail.cpp new file mode 100644 index 000000000..43fddebe8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_ctor_fail.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(shared_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::shared_lock<boost::shared_mutex> lk0(m0); + boost::shared_lock<boost::shared_mutex> lk1 = lk0; + BOOST_TEST(lk1.mutex() == &m1); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp new file mode 100644 index 000000000..9ccae93b7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(shared_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_lock<boost::shared_mutex> ul; + BOOST_TEST(!ul.owns_lock()); + BOOST_TEST(ul.mutex() == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp new file mode 100644 index 000000000..84388aca4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(mutex_type& m, adopt_lock_t); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_mutex m; + m.lock(); + boost::shared_lock<boost::shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp new file mode 100644 index 000000000..45037c224 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Rep, class Period> +// shared_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/chrono/chrono_io.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::shared_lock<boost::shared_mutex> lk(m, ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::shared_lock<boost::shared_mutex> lk(m, ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp new file mode 100644 index 000000000..ef54e229f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_mutex.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(shared_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m0); + boost::shared_lock<boost::shared_mutex> lk1(m1); + lk1 = boost::move(lk0); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + + boost::shared_lock<boost::shared_mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(m0)); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + { + boost::unique_lock<boost::shared_mutex> lk0(m0); + boost::shared_lock<boost::shared_mutex> lk1(m1); + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(boost::move(lk0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + + boost::shared_lock<boost::shared_mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(boost::unique_lock<boost::shared_mutex>(m0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + { + boost::upgrade_lock<boost::shared_mutex> lk0(m0); + boost::shared_lock<boost::shared_mutex> lk1(m1); + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(boost::move(lk0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + + boost::shared_lock<boost::shared_mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(boost::upgrade_lock<boost::shared_mutex>(m0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp new file mode 100644 index 000000000..307c76142 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock& operator=(shared_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk( (BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(m)))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp new file mode 100644 index 000000000..38f6e7d7d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock& operator=(shared_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + + { + boost::unique_lock<boost::shared_mutex> lk0(m); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk( (boost::unique_lock<boost::shared_mutex>(m))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::unique_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp new file mode 100644 index 000000000..36ecb6a5a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock& operator=(shared_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + + { + boost::upgrade_lock<boost::shared_mutex> lk0(m); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk( (boost::upgrade_lock<boost::shared_mutex>(m))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::upgrade_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp new file mode 100644 index 000000000..f50aa6199 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// explicit shared_lock(Mutex& m); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::shared_lock<boost::shared_mutex> ul(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::shared_lock<boost::shared_mutex> ul(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp new file mode 100644 index 000000000..41d9cd8f9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Clock, class Duration> +// shared_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::shared_lock<boost::shared_mutex> lk(m, Clock::now() + ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::shared_lock<boost::shared_mutex> lk(m, Clock::now() + ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp new file mode 100644 index 000000000..5f3036c0c --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp @@ -0,0 +1,115 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(mutex_type& m, try_to_lock_t); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + for (;;) + { + boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) { + t1 = Clock::now(); + break; + } + } +#else +// time_point t0 = Clock::now(); +// { +// boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } + for (;;) + { + boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) break; + } + //time_point t1 = Clock::now(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/lock_pass.cpp new file mode 100644 index 000000000..456c26dfd --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/lock_pass.cpp @@ -0,0 +1,126 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// void lock(); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + boost::shared_lock < boost::shared_mutex > lk(m, boost::defer_lock); + t0 = Clock::now(); + lk.lock(); + t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#else + boost::shared_lock < boost::shared_mutex > lk(m, boost::defer_lock); + //time_point t0 = Clock::now(); + lk.lock(); + //time_point t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_for_pass.cpp new file mode 100644 index 000000000..07d32df39 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_for_pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_for_called = false; + +typedef boost::chrono::milliseconds ms; + +struct shared_mutex +{ + template <class Rep, class Period> + bool try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time) + { + BOOST_TEST(rel_time == ms(5)); + try_lock_for_called = !try_lock_for_called; + return try_lock_for_called; + } + void unlock_shared() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_for(ms(5)) == true); + BOOST_TEST(try_lock_for_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_for(ms(5)) == false); + BOOST_TEST(try_lock_for_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_pass.cpp new file mode 100644 index 000000000..6a1997238 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_called = false; + +struct shared_mutex +{ + bool try_lock_shared() + { + try_lock_called = !try_lock_called; + return try_lock_called; + } + void unlock_shared() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock() == true); + BOOST_TEST(try_lock_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock() == false); + BOOST_TEST(try_lock_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_until_pass.cpp new file mode 100644 index 000000000..cdfd0e161 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_until_pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_until_called = false; + +struct shared_mutex +{ + template <class Clock, class Duration> + bool try_lock_shared_until(const boost::chrono::time_point<Clock, Duration>& abs_time) + { + typedef boost::chrono::milliseconds ms; + BOOST_TEST(Clock::now() - abs_time < ms(5)); + try_lock_until_called = !try_lock_until_called; + return try_lock_until_called; + } + void unlock_shared() + { + } +}; + +shared_mutex m; + +int main() +{ + typedef boost::chrono::steady_clock Clock; + boost::shared_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_until(Clock::now()) == true); + BOOST_TEST(try_lock_until_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_until(Clock::now()) == false); + BOOST_TEST(try_lock_until_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/unlock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/unlock_pass.cpp new file mode 100644 index 000000000..e8ed7c74c --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/unlock_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool unlock_called = false; + +struct shared_mutex +{ + void lock_shared() + { + } + void unlock_shared() + { + unlock_called = true; + } +}; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk(m); + lk.unlock(); + BOOST_TEST(unlock_called == true); + BOOST_TEST(lk.owns_lock() == false); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + lk.release(); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/member_swap_pass.cpp new file mode 100644 index 000000000..11f366bd6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/member_swap_pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// void swap(shared_lock& u); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + void lock_shared() + { + } + void unlock_shared() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk1(m); + boost::shared_lock<shared_mutex> lk2; + lk1.swap(lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/non_member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/non_member_swap_pass.cpp new file mode 100644 index 000000000..c0ccb8b9d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/non_member_swap_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> +// void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + void lock_shared() + { + } + void unlock_shared() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk1(m); + boost::shared_lock<shared_mutex> lk2; + swap(lk1, lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/release_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/release_pass.cpp new file mode 100644 index 000000000..c39ca50aa --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/release_pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// void Mutex* release(); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + static int lock_count; + static int unlock_count; + void lock_shared() + { + ++lock_count; + } + void unlock_shared() + { + ++unlock_count; + } +}; + +int shared_mutex::lock_count = 0; +int shared_mutex::unlock_count = 0; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk(m); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(shared_mutex::lock_count == 1); + BOOST_TEST(shared_mutex::unlock_count == 0); + BOOST_TEST(lk.release() == &m); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(shared_mutex::lock_count == 1); + BOOST_TEST(shared_mutex::unlock_count == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/mutex_pass.cpp new file mode 100644 index 000000000..2012186ae --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/mutex_pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// Mutex *mutex() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::shared_lock<boost::shared_mutex> lk0; + BOOST_TEST(lk0.mutex() == 0); + boost::shared_lock<boost::shared_mutex> lk1(m); + BOOST_TEST(lk1.mutex() == &m); + lk1.unlock(); + BOOST_TEST(lk1.mutex() == &m); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/op_bool_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/op_bool_pass.cpp new file mode 100644 index 000000000..407bfcc6f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/op_bool_pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// explicit operator bool() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::shared_lock < boost::shared_mutex > lk0; + BOOST_TEST(bool(lk0) == false); + boost::shared_lock < boost::shared_mutex > lk1(m); + BOOST_TEST(bool(lk1) == true); + lk1.unlock(); + BOOST_TEST(bool(lk1) == false); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/owns_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/owns_lock_pass.cpp new file mode 100644 index 000000000..dce14d3e9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/owns_lock_pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// bool owns_lock() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::shared_lock<boost::shared_mutex> lk0; + BOOST_TEST(lk0.owns_lock() == false); + boost::shared_lock<boost::shared_mutex> lk1(m); + BOOST_TEST(lk1.owns_lock() == true); + lk1.unlock(); + BOOST_TEST(lk1.owns_lock() == false); + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/types_pass.cpp new file mode 100644 index 000000000..2f83ef98f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/types_pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class shared_lock +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::shared_lock<boost::shared_mutex>::mutex_type, + boost::shared_mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/adopt_lock_pass.cpp new file mode 100644 index 000000000..fe125e8a0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/adopt_lock_pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_lock_guard.hpp> + +// template <class Mutex> class shared_lock_guard; + +// shared_lock_guard(mutex_type& m, adopt_lock_t); + +#include <boost/thread/shared_lock_guard.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +boost::shared_mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + m.lock_shared(); + boost::shared_lock_guard<boost::shared_mutex> lg(m, boost::adopt_lock); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + m.lock_shared(); + boost::shared_lock_guard<boost::shared_mutex> lg(m, boost::adopt_lock); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_assign_fail.cpp new file mode 100644 index 000000000..43607ac26 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_assign_fail.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_lock_guard.hpp> + +// template <class Mutex> class shared_lock_guard; + +// shared_lock_guard& operator=(shared_lock_guard const&) = delete; + +#include <boost/thread/shared_lock_guard.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::shared_lock_guard<boost::shared_mutex> lk0(m0); + boost::shared_lock_guard<boost::shared_mutex> lk1(m1); + lk1 = lk0; + +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_ctor_fail.cpp new file mode 100644 index 000000000..a7d4f006d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_ctor_fail.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_lock_guard.hpp> + +// template <class Mutex> class shared_lock_guard; + +// shared_lock_guard(shared_lock_guard const&) = delete; + + +#include <boost/thread/shared_lock_guard.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::shared_lock_guard<boost::shared_mutex> lk0(m0); + boost::shared_lock_guard<boost::shared_mutex> lk1 = lk0; +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/default_pass.cpp new file mode 100644 index 000000000..694ba4a14 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/default_pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_lock_guard.hpp> + +// template <class Mutex> class shared_lock_guard; + +// shared_lock_guard(shared_lock_guard const&) = delete; + +#include <boost/thread/shared_lock_guard.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +boost::shared_mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::shared_lock_guard<boost::shared_mutex> lg(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::shared_lock_guard<boost::shared_mutex> lg(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/types_pass.cpp new file mode 100644 index 000000000..57a2116d1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/types_pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_lock_guard.hpp> + +// <mutex> + +// template <class Mutex> +// class shared_lock_guard +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/shared_lock_guard.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::shared_lock_guard<boost::shared_mutex>::mutex_type, + boost::shared_mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_assign_fail.cpp new file mode 100644 index 000000000..1852224bb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_assign_fail.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class strict_lock; + +// strict_lock& operator=(strict_lock const&) = delete; + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::strict_lock<boost::mutex> lk0(m0); + boost::strict_lock<boost::mutex> lk1(m1); + lk1 = lk0; + +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_ctor_fail.cpp new file mode 100644 index 000000000..331610cb1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_ctor_fail.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class strict_lock; + +// strict_lock(strict_lock const&) = delete; + + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::strict_lock<boost::mutex> lk0(m0); + boost::strict_lock<boost::mutex> lk1 = lk0; +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/default_pass.cpp new file mode 100644 index 000000000..aa2fb0071 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/default_pass.cpp @@ -0,0 +1,74 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class strict_lock; + +// strict_lock(Mutex &); + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#ifdef BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::strict_lock<boost::mutex> lg(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::strict_lock<boost::mutex> lg(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#ifdef BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp new file mode 100644 index 000000000..c5a3069f0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/strict_lock.hpp> + +// template <class Lockable> +// strict_lock<Lockable> make_strict_lock(Lockable &); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK && defined BOOST_THREAD_USES_CHRONO + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + t0 = Clock::now(); + { + const auto&& lg = boost::make_strict_lock(m); (void)lg; + t1 = Clock::now(); + } + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} +#endif + +int main() +{ + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK && defined BOOST_THREAD_USES_CHRONO + { + m.lock(); + boost::thread t(f); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } +#endif + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/owns_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/owns_lock_pass.cpp new file mode 100644 index 000000000..c0c2ec861 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/owns_lock_pass.cpp @@ -0,0 +1,34 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class strict_lock; + +// bool owns_lock(Mutex *) const; + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +#endif + +int main() +{ + boost::mutex m; + boost::mutex m2; + + boost::strict_lock<boost::mutex> lk(m); + BOOST_TEST(lk.owns_lock(&m) == true); + BOOST_TEST(!lk.owns_lock(&m2) == true); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/types_pass.cpp new file mode 100644 index 000000000..f813e5ca8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/types_pass.cpp @@ -0,0 +1,34 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class strict_lock +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::strict_lock<boost::mutex>::mutex_type, + boost::mutex>::value), ""); + + BOOST_STATIC_ASSERT_MSG((boost::is_strict_lock<boost::strict_lock<boost::mutex> >::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/adopt_lock_pass.cpp new file mode 100644 index 000000000..42d33378e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/adopt_lock_pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(mutex_type& m, adopt_lock_t); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + boost::mutex m; + m.lock(); + boost::unique_lock<boost::mutex> lk(m, boost::adopt_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_assign_fail.cpp new file mode 100644 index 000000000..d69a1eec7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_assign_fail.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock& operator=(unique_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::unique_lock<boost::mutex> lk0(m0); + boost::unique_lock<boost::mutex> lk1(m1); + lk1 = lk0; + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_ctor_fail.cpp new file mode 100644 index 000000000..08fc3c344 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_ctor_fail.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(unique_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::unique_lock<boost::mutex> lk0(m0); + boost::unique_lock<boost::mutex> lk1 = lk0; + BOOST_TEST(lk1.mutex() == &m1); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/default_pass.cpp new file mode 100644 index 000000000..7989b8173 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/default_pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(unique_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::unique_lock<boost::mutex> ul; + BOOST_TEST(!ul.owns_lock()); + BOOST_TEST(ul.mutex() == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/defer_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/defer_lock_pass.cpp new file mode 100644 index 000000000..5045af26e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/defer_lock_pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(mutex_type& m, adopt_lock_t); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m; + boost::unique_lock<boost::mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp new file mode 100644 index 000000000..19aa0575f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp @@ -0,0 +1,94 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Rep, class Period> +// unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/chrono/chrono_io.hpp> +#include "../../../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::unique_lock<boost::timed_mutex> lk(m, ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::unique_lock<boost::timed_mutex> lk(m, ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_adopt_lock_pass.cpp new file mode 100644 index 000000000..2f385ec87 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_adopt_lock_pass.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/lock_factories.hpp> + +// template <class Mutex> class unique_lock; +// unique_lock<Mutex> make_unique_lock(Mutex&, adopt_lock_t); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_factories.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m; + m.lock(); +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::adopt_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_defer_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_defer_lock_pass.cpp new file mode 100644 index 000000000..e32fad168 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_defer_lock_pass.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/lock_factories.hpp> + +// template <class Mutex> class unique_lock; +// unique_lock<Mutex> make_unique_lock(Mutex&, defer_lock_t); + +// unique_lock(mutex_type& m, adopt_lock_t); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_factories.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m; +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::defer_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_mutex_pass.cpp new file mode 100644 index 000000000..97b625564 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_mutex_pass.cpp @@ -0,0 +1,100 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/lock_factories.hpp> + +// template <class Mutex> +// unique_lock<Mutex> make_unique_lock(Mutex&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/lock_factories.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +//#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + //&& + _ = boost::make_unique_lock(m); (void)_; + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + //&& + _ = boost::make_unique_lock(m); (void)_; + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} +//#else +//int main() +//{ +// return boost::report_errors(); +//} +//#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_try_to_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_try_to_lock_pass.cpp new file mode 100644 index 000000000..d0149d906 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_try_to_lock_pass.cpp @@ -0,0 +1,146 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; +// unique_lock<Mutex> make_unique_lock(Mutex&, try_to_lock_t); + +#define BOOST_THREAD_VERSION 4 + + +#include <boost/thread/lock_factories.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + { + t0 = Clock::now(); +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + t0 = Clock::now(); +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + t0 = Clock::now(); +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + t0 = Clock::now(); + for (;;) + { +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::try_to_lock); + if (lk.owns_lock()) { + t1 = Clock::now(); + break; + } + } + } +#else +// time_point t0 = Clock::now(); +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } + for (;;) + { +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::try_to_lock); + if (lk.owns_lock()) break; + } + //time_point t1 = Clock::now(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_locks_mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_locks_mutex_pass.cpp new file mode 100644 index 000000000..72c574b20 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_locks_mutex_pass.cpp @@ -0,0 +1,94 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/lock_factories.hpp> + +// template <class Mutex> +// unique_lock<Mutex> make_unique_lock(Mutex&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_factories.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + +boost::mutex m1; +boost::mutex m2; +boost::mutex m3; + + +#if defined BOOST_THREAD_USES_CHRONO + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + auto&& _ = boost::make_unique_locks(m1,m2,m3); (void)_; + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + auto&& _ = boost::make_unique_locks(m1,m2,m3); (void)_; + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m1.lock(); + m2.lock(); + m3.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m1.unlock(); + m2.unlock(); + m3.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} +#else +int main() +{ + return boost::report_errors(); +} +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp new file mode 100644 index 000000000..7c84d1520 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(unique_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + { + boost::unique_lock<boost::mutex> lk0(m0); + boost::unique_lock<boost::mutex> lk1(m1); + lk1 = boost::move(lk0); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + + { + + boost::unique_lock<boost::mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(m0)); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp new file mode 100644 index 000000000..cf682fbd4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(unique_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + { + boost::unique_lock<boost::mutex> lk0(m); + boost::unique_lock<boost::mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::mutex> lk( (BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(m)))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::unique_lock<boost::mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp new file mode 100644 index 000000000..0e61cb1a7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Rep, class Period> +// unique_lock(shared_lock<mutex_type>&&, +// const chrono::duration<Rep, Period>&); + +#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::shared_mutex> + lk(boost::shared_lock<boost::shared_mutex>(m), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp new file mode 100644 index 000000000..3068866f0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(shared_lock&& u, try_to_lock); + +#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock ); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::shared_mutex> lk(boost::shared_lock<boost::shared_mutex>(m), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp new file mode 100644 index 000000000..f1e54cf45 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Clock, class Duration> +// unique_lock(shared_lock<mutex_type>&&, +// const chrono::time_point<Clock, Duration>&); + +#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::unique_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::shared_mutex> + lk( boost::shared_lock<boost::shared_mutex>(m), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp new file mode 100644 index 000000000..7437ee0e7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Clock, class Duration> +// unique_lock(shared_lock<mutex_type>&&, +// const chrono::duration<Rep, Period>&); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::upgrade_mutex m; + +int main() +{ + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::upgrade_mutex> + lk(boost::upgrade_lock<boost::upgrade_mutex>(m), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp new file mode 100644 index 000000000..c72067ae9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(upgrade_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::upgrade_mutex m; + +int main() +{ + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m); + boost::unique_lock<boost::upgrade_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::upgrade_mutex> lk( (BOOST_THREAD_MAKE_RV_REF(boost::upgrade_lock<boost::upgrade_mutex>(m)))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::upgrade_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::upgrade_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp new file mode 100644 index 000000000..fdbdf2165 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(upgrade_lock&& u, try_to_lock); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::upgrade_mutex m; + +int main() +{ + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::try_to_lock ); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::upgrade_mutex> lk(boost::upgrade_lock<boost::upgrade_mutex>(m), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp new file mode 100644 index 000000000..cd33f709c --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Clock, class Duration> +// unique_lock(shared_lock<mutex_type>&&, +// const chrono::time_point<Clock, Duration>&); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::upgrade_mutex m; + +int main() +{ + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m); + boost::unique_lock<boost::upgrade_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::upgrade_mutex> + lk( boost::upgrade_lock<boost::upgrade_mutex>(m), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::upgrade_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::upgrade_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp new file mode 100644 index 000000000..d5b7ca295 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// explicit unique_lock(Mutex& m); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../../timming.hpp" + + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::unique_lock<boost::mutex> ul(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::unique_lock<boost::mutex> ul(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp new file mode 100644 index 000000000..53358de6e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Clock, class Duration> +// unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::unique_lock<boost::timed_mutex> lk(m, Clock::now() + ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::unique_lock<boost::timed_mutex> lk(m, Clock::now() + ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_TEST(d < max_diff); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp new file mode 100644 index 000000000..0f0c8ded4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(mutex_type& m, try_to_lock_t); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + for (;;) + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) { + t1 = Clock::now(); + break; + } + } + //m.unlock(); +#else +// time_point t0 = Clock::now(); +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } + for (;;) + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) break; + } + //time_point t1 = Clock::now(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + std::cout << "d_ns: " << d_ns.count() << std::endl; + std::cout << "d_ms: " << d_ms.count() << std::endl; + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/lock_pass.cpp new file mode 100644 index 000000000..94edb4342 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/lock_pass.cpp @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// void lock(); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../../timming.hpp" + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + boost::unique_lock < boost::mutex > lk(m, boost::defer_lock); + t0 = Clock::now(); + lk.lock(); + t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#else + boost::unique_lock < boost::mutex > lk(m, boost::defer_lock); + //time_point t0 = Clock::now(); + lk.lock(); + //time_point t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_for_pass.cpp new file mode 100644 index 000000000..2be8416eb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_for_pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + + +bool try_lock_for_called = false; + +typedef boost::chrono::milliseconds ms; + +struct mutex +{ + template <class Rep, class Period> + bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time) + { + BOOST_TEST(rel_time == ms(5)); + try_lock_for_called = !try_lock_for_called; + return try_lock_for_called; + } + void unlock() + { + } +}; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_for(ms(5)) == true); + BOOST_TEST(try_lock_for_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_for(ms(5)) == false); + BOOST_TEST(try_lock_for_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_pass.cpp new file mode 100644 index 000000000..8553c1c0b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_called = false; + +struct mutex +{ + bool try_lock() + { + try_lock_called = !try_lock_called; + return try_lock_called; + } + void unlock() + { + } +}; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock() == true); + BOOST_TEST(try_lock_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock() == false); + BOOST_TEST(try_lock_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_until_pass.cpp new file mode 100644 index 000000000..df6e7369e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_until_pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + + +bool try_lock_until_called = false; + +struct mutex +{ + template <class Clock, class Duration> + bool try_lock_until(const boost::chrono::time_point<Clock, Duration>& abs_time) + { + typedef boost::chrono::milliseconds ms; + BOOST_TEST(Clock::now() - abs_time < ms(5)); + try_lock_until_called = !try_lock_until_called; + return try_lock_until_called; + } + void unlock() + { + } +}; + +mutex m; + +int main() +{ + typedef boost::chrono::steady_clock Clock; + boost::unique_lock<mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_until(Clock::now()) == true); + BOOST_TEST(try_lock_until_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_until(Clock::now()) == false); + BOOST_TEST(try_lock_until_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/unlock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/unlock_pass.cpp new file mode 100644 index 000000000..4ad954f24 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/unlock_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// bool unlock(); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +bool unlock_called = false; + +struct mutex +{ + void lock() + { + } + void unlock() + { + unlock_called = true; + } +}; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk(m); + lk.unlock(); + BOOST_TEST(unlock_called == true); + BOOST_TEST(lk.owns_lock() == false); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + lk.release(); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/member_swap_pass.cpp new file mode 100644 index 000000000..617682fe3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/member_swap_pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// void swap(unique_lock& u); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct mutex +{ + void lock() + { + } + void unlock() + { + } +}; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk1(m); + boost::unique_lock<mutex> lk2; + lk1.swap(lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/non_member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/non_member_swap_pass.cpp new file mode 100644 index 000000000..74ba5ff3f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/non_member_swap_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> +// void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct mutex +{ + void lock() + { + } + void unlock() + { + } +}; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk1(m); + boost::unique_lock<mutex> lk2; + swap(lk1, lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/release_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/release_pass.cpp new file mode 100644 index 000000000..63c3831e5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/release_pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// void Mutex* release(); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct mutex +{ + static int lock_count; + static int unlock_count; + void lock() + { + ++lock_count; + } + void unlock() + { + ++unlock_count; + } +}; + +int mutex::lock_count = 0; +int mutex::unlock_count = 0; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk(m); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(mutex::lock_count == 1); + BOOST_TEST(mutex::unlock_count == 0); + BOOST_TEST(lk.release() == &m); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(mutex::lock_count == 1); + BOOST_TEST(mutex::unlock_count == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/mutex_pass.cpp new file mode 100644 index 000000000..68f1bbb6d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/mutex_pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// Mutex *mutex() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + boost::unique_lock<boost::mutex> lk0; + BOOST_TEST(lk0.mutex() == 0); + boost::unique_lock<boost::mutex> lk1(m); + BOOST_TEST(lk1.mutex() == &m); + lk1.unlock(); + BOOST_TEST(lk1.mutex() == &m); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_bool_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_bool_pass.cpp new file mode 100644 index 000000000..3fa18225a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_bool_pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// explicit operator bool() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + { + boost::unique_lock<boost::mutex> lk0; + BOOST_TEST(bool(lk0) == false); + boost::unique_lock<boost::mutex> lk1(m); + BOOST_TEST(bool(lk1) == true); + lk1.unlock(); + BOOST_TEST(bool(lk1) == false); + } + + { + boost::unique_lock<boost::mutex> lk0; + if (lk0) BOOST_TEST(false); + boost::unique_lock<boost::mutex> lk1(m); + if (!lk1) BOOST_TEST(false); + lk1.unlock(); + if (lk1) BOOST_TEST(false); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_int_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_int_fail.cpp new file mode 100644 index 000000000..92fe0ffcb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_int_fail.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// explicit operator bool() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + { + boost::unique_lock<boost::mutex> lk0; + int i = int(lk0); + BOOST_TEST(i == 0); + } + + return boost::report_errors(); +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/owns_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/owns_lock_pass.cpp new file mode 100644 index 000000000..6a9f019aa --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/owns_lock_pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// bool owns_lock() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + boost::mutex m; + + boost::unique_lock<boost::mutex> lk0; + BOOST_TEST(lk0.owns_lock() == false); + boost::unique_lock<boost::mutex> lk1(m); + BOOST_TEST(lk1.owns_lock() == true); + lk1.unlock(); + BOOST_TEST(lk1.owns_lock() == false); + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/types_pass.cpp new file mode 100644 index 000000000..69b963a6f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/types_pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class unique_lock +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::unique_lock<boost::mutex>::mutex_type, + boost::mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/adopt_lock_pass.cpp new file mode 100644 index 000000000..1822fe0b6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/adopt_lock_pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(mutex_type& m, adopt_lock_t); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + boost::shared_mutex m; + m.lock_upgrade(); + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::adopt_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_assign_fail.cpp new file mode 100644 index 000000000..521304d81 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_assign_fail.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock& operator=(upgrade_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::upgrade_lock<boost::shared_mutex> lk0(m0); + boost::upgrade_lock<boost::shared_mutex> lk1(m1); + lk1 = lk0; + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_ctor_fail.cpp new file mode 100644 index 000000000..8e20196b1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_ctor_fail.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(upgrade_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::upgrade_lock<boost::shared_mutex> lk0(m0); + boost::upgrade_lock<boost::shared_mutex> lk1(lk0); + BOOST_TEST(lk1.mutex() == &m1); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/default_pass.cpp new file mode 100644 index 000000000..59ea2a9a2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/default_pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(upgrade_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::upgrade_lock<boost::shared_mutex> ul; + BOOST_TEST(!ul.owns_lock()); + BOOST_TEST(ul.mutex() == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/defer_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/defer_lock_pass.cpp new file mode 100644 index 000000000..ececb845c --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/defer_lock_pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(mutex_type& m, adopt_lock_t); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_mutex m; + m.lock(); + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp new file mode 100644 index 000000000..b6506b9b3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Rep, class Period> +// upgrade_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/chrono/chrono_io.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::upgrade_lock<boost::shared_mutex> lk(m, ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::upgrade_lock<boost::shared_mutex> lk(m, ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp new file mode 100644 index 000000000..42ef355c9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_mutex.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(upgrade_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + { + boost::upgrade_lock<boost::shared_mutex> lk0(m0); + boost::upgrade_lock<boost::shared_mutex> lk1(m1); + lk1 = boost::move(lk0); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + + boost::upgrade_lock<boost::shared_mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::upgrade_lock<boost::shared_mutex>(m0)); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + { + boost::unique_lock<boost::shared_mutex> lk0(m0); + boost::upgrade_lock<boost::shared_mutex> lk1(m1); + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::upgrade_lock<boost::shared_mutex>(boost::move(lk0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + + boost::upgrade_lock<boost::shared_mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::upgrade_lock<boost::shared_mutex>(boost::unique_lock<boost::shared_mutex>(m0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp new file mode 100644 index 000000000..5d5c0a948 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock& operator=(upgrade_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::upgrade_lock<boost::shared_mutex> lk0(m); + boost::upgrade_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk( (BOOST_THREAD_MAKE_RV_REF(boost::upgrade_lock<boost::shared_mutex>(m)))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp new file mode 100644 index 000000000..ccad7b1ac --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Clock, class Duration> +// upgrade_lock(shared_lock<mutex_type>&&, +// const chrono::duration<Rep, Period>&); + +#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> + lk(boost::shared_lock<boost::shared_mutex>(m), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp new file mode 100644 index 000000000..93deda8c3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(shared_lock&& u, try_to_lock); + +#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock ); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk(boost::shared_lock<boost::shared_mutex>(m), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp new file mode 100644 index 000000000..3d2c2871b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Clock, class Duration> +// upgrade_lock(shared_lock<mutex_type>&&, +// const chrono::time_point<Clock, Duration>&); + +#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::upgrade_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> + lk( boost::shared_lock<boost::shared_mutex>(m), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::upgrade_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::upgrade_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp new file mode 100644 index 000000000..3d591d176 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock& operator=(unique_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::unique_lock<boost::shared_mutex> lk0(m); + boost::upgrade_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk( (boost::unique_lock<boost::shared_mutex>(m))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp new file mode 100644 index 000000000..1e634807d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// explicit upgrade_lock(Mutex& m); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::upgrade_lock<boost::shared_mutex> ul(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::upgrade_lock<boost::shared_mutex> ul(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp new file mode 100644 index 000000000..4cf71476b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Clock, class Duration> +// upgrade_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::upgrade_lock<boost::shared_mutex> lk(m, Clock::now() + ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::upgrade_lock<boost::shared_mutex> lk(m, Clock::now() + ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp new file mode 100644 index 000000000..9a7fe26bf --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(mutex_type& m, try_to_lock_t); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + for (;;) + { + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) { + t1 = Clock::now(); + break; + } + } + //m.unlock(); +#else +// time_point t0 = Clock::now(); +// { +// boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } + for (;;) + { + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) break; + } + //time_point t1 = Clock::now(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/lock_pass.cpp new file mode 100644 index 000000000..2ff49ac96 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/lock_pass.cpp @@ -0,0 +1,126 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// void lock(); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + boost::upgrade_lock < boost::shared_mutex > lk(m, boost::defer_lock); + t0 = Clock::now(); + lk.lock(); + t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#else + boost::upgrade_lock < boost::shared_mutex > lk(m, boost::defer_lock); + //time_point t0 = Clock::now(); + lk.lock(); + //time_point t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_for_pass.cpp new file mode 100644 index 000000000..5f8f4f5fe --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_for_pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_for_called = false; + +typedef boost::chrono::milliseconds ms; + +struct shared_mutex +{ + template <class Rep, class Period> + bool try_lock_upgrade_for(const boost::chrono::duration<Rep, Period>& rel_time) + { + BOOST_TEST(rel_time == ms(5)); + try_lock_for_called = !try_lock_for_called; + return try_lock_for_called; + } + void unlock_upgrade() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_for(ms(5)) == true); + BOOST_TEST(try_lock_for_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_for(ms(5)) == false); + BOOST_TEST(try_lock_for_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_pass.cpp new file mode 100644 index 000000000..820fd71a3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_called = false; + +struct shared_mutex +{ + bool try_lock_upgrade() + { + try_lock_called = !try_lock_called; + return try_lock_called; + } + void unlock_upgrade() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock() == true); + BOOST_TEST(try_lock_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock() == false); + BOOST_TEST(try_lock_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_until_pass.cpp new file mode 100644 index 000000000..1c53d6a5b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_until_pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_until_called = false; + +struct shared_mutex +{ + template <class Clock, class Duration> + bool try_lock_upgrade_until(const boost::chrono::time_point<Clock, Duration>& abs_time) + { + typedef boost::chrono::milliseconds ms; + BOOST_TEST(Clock::now() - abs_time < ms(5)); + try_lock_until_called = !try_lock_until_called; + return try_lock_until_called; + } + void unlock_upgrade() + { + } +}; + +shared_mutex m; + +int main() +{ + typedef boost::chrono::steady_clock Clock; + boost::upgrade_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_until(Clock::now()) == true); + BOOST_TEST(try_lock_until_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_until(Clock::now()) == false); + BOOST_TEST(try_lock_until_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/unlock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/unlock_pass.cpp new file mode 100644 index 000000000..bc49a0433 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/unlock_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool unlock_called = false; + +struct shared_mutex +{ + void lock_upgrade() + { + } + void unlock_upgrade() + { + unlock_called = true; + } +}; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk(m); + lk.unlock(); + BOOST_TEST(unlock_called == true); + BOOST_TEST(lk.owns_lock() == false); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + lk.release(); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/member_swap_pass.cpp new file mode 100644 index 000000000..4b0752ef5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/member_swap_pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// void swap(upgrade_lock& u); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + void lock_upgrade() + { + } + void unlock_upgrade() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk1(m); + boost::upgrade_lock<shared_mutex> lk2; + lk1.swap(lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/non_member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/non_member_swap_pass.cpp new file mode 100644 index 000000000..c7ebaa271 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/non_member_swap_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> +// void swap(upgrade_lock<Mutex>& x, upgrade_lock<Mutex>& y); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + void lock_upgrade() + { + } + void unlock_upgrade() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk1(m); + boost::upgrade_lock<shared_mutex> lk2; + swap(lk1, lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/release_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/release_pass.cpp new file mode 100644 index 000000000..226819446 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/release_pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// void Mutex* release(); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + static int lock_count; + static int unlock_count; + void lock_upgrade() + { + ++lock_count; + } + void unlock_upgrade() + { + ++unlock_count; + } +}; + +int shared_mutex::lock_count = 0; +int shared_mutex::unlock_count = 0; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk(m); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(shared_mutex::lock_count == 1); + BOOST_TEST(shared_mutex::unlock_count == 0); + BOOST_TEST(lk.release() == &m); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(shared_mutex::lock_count == 1); + BOOST_TEST(shared_mutex::unlock_count == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/mutex_pass.cpp new file mode 100644 index 000000000..276cd0a93 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/mutex_pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// Mutex *mutex() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::upgrade_lock<boost::shared_mutex> lk0; + BOOST_TEST(lk0.mutex() == 0); + boost::upgrade_lock<boost::shared_mutex> lk1(m); + BOOST_TEST(lk1.mutex() == &m); + lk1.unlock(); + BOOST_TEST(lk1.mutex() == &m); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/op_bool_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/op_bool_pass.cpp new file mode 100644 index 000000000..4e722d174 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/op_bool_pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// explicit operator bool() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::upgrade_lock < boost::shared_mutex > lk0; + BOOST_TEST(bool(lk0) == false); + boost::upgrade_lock < boost::shared_mutex > lk1(m); + BOOST_TEST(bool(lk1) == true); + lk1.unlock(); + BOOST_TEST(bool(lk1) == false); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/owns_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/owns_lock_pass.cpp new file mode 100644 index 000000000..9d8b80d69 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/owns_lock_pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// bool owns_lock() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::upgrade_lock<boost::shared_mutex> lk0; + BOOST_TEST(lk0.owns_lock() == false); + boost::upgrade_lock<boost::shared_mutex> lk1(m); + BOOST_TEST(lk1.owns_lock() == true); + lk1.unlock(); + BOOST_TEST(lk1.owns_lock() == false); + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/types_pass.cpp new file mode 100644 index 000000000..876428e46 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/types_pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class upgrade_lock +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::upgrade_lock<boost::upgrade_mutex>::mutex_type, + boost::upgrade_mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/assign_fail.cpp new file mode 100644 index 000000000..fa1aff9b5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/assign_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// mutex& operator=(const mutex&) = delete; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m0; + boost::mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/copy_fail.cpp new file mode 100644 index 000000000..e6f6d6b88 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/copy_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// mutex(const mutex&) = delete; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m0; + boost::mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/default_pass.cpp new file mode 100644 index 000000000..a911eefcf --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// mutex(); + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_fail.cpp new file mode 100644 index 000000000..f6bf74b56 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_fail.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2017 Tom Hughes +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// class mutex; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +void fail() +{ + boost::mutex m0; + m0.lock(); + m0.lock(); + m0.unlock(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_pass.cpp new file mode 100644 index 000000000..9da22a59d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_pass.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2017 Tom Hughes +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// class mutex; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +void pass() +{ + boost::mutex m0; + m0.lock(); + m0.unlock(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_pass.cpp new file mode 100644 index 000000000..94818fbad --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// void lock(); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + m.lock(); + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/native_handle_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/native_handle_pass.cpp new file mode 100644 index 000000000..489ec375d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/native_handle_pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// typedef pthread_mutex_t* native_handle_type; +// native_handle_type native_handle(); + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE + boost::mutex m; + boost::mutex::native_handle_type h = m.native_handle(); + BOOST_TEST(h); +#else +#error "Test not applicable: BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE not defined for this platform as not supported" +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_fail.cpp new file mode 100644 index 000000000..05c2016cb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_fail.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2017 Tom Hughes +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// class mutex; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +void fail() +{ + boost::mutex m0; + if (!m0.try_lock()) { + m0.unlock(); + } +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_pass.cpp new file mode 100644 index 000000000..e4cec906a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_pass.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2017 Tom Hughes +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// class mutex; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +void pass() +{ + boost::mutex m0; + if (m0.try_lock()) { + m0.unlock(); + } +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_pass.cpp new file mode 100644 index 000000000..b973c1b23 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_pass.cpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// bool try_lock(); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif + +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/assign_fail.cpp new file mode 100644 index 000000000..e8b440abd --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/assign_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// null_mutex& operator=(const null_mutex&) = delete; + +#include <boost/thread/null_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::null_mutex m0; + boost::null_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/copy_fail.cpp new file mode 100644 index 000000000..66668f5e0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/copy_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// null_mutex(const null_mutex&) = delete; + +#include <boost/thread/null_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::null_mutex m0; + boost::null_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/default_pass.cpp new file mode 100644 index 000000000..343431a9e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// null_mutex(); + +#include <boost/thread/null_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::null_mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/lock_pass.cpp new file mode 100644 index 000000000..3c91e25f6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/lock_pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// void lock(); + +#include <boost/thread/null_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::null_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + time_point t0 = Clock::now(); + m.lock(); + time_point t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); + ns d = t1 - t0 ; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); + //ns d = t1 - t0 ; + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); + m.unlock(); + t.join(); + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_for_pass.cpp new file mode 100644 index 000000000..1f5f5e9fc --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_for_pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/null_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + + +boost::null_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + time_point t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(250)) == true); + time_point t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); + ns d = t1 - t0 ; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_pass.cpp new file mode 100644 index 000000000..cc51928bb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// bool try_lock(); + +#include <boost/thread/null_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + + + +boost::null_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + time_point t0 = Clock::now(); + BOOST_TEST(m.try_lock()); + time_point t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +#else + BOOST_TEST(m.try_lock()); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); + m.unlock(); + t.join(); + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_until_pass.cpp new file mode 100644 index 000000000..8a6985165 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_until_pass.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/null_mutex> + +// class null_mutex; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/null_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::null_mutex m; + +typedef boost::chrono::steady_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + time_point t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(250)) == true); + time_point t1 = Clock::now(); + m.unlock(); + ns d = t1 - t0 ; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + + +int main() +{ + { + m.lock(); + boost::thread t(f1); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/once/call_once/call_once_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/once/call_once/call_once_pass.cpp new file mode 100644 index 000000000..ac7b80769 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/once/call_once/call_once_pass.cpp @@ -0,0 +1,297 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/once.hpp> + +// struct once_flag; + +// template<class Callable, class ...Args> +// void call_once(once_flag& flag, Callable&& func, Args&&... args); + +//#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_USES_MOVE +#define BOOST_THREAD_PROVIDES_ONCE_CXX11 + +#include <boost/thread/once.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 +#define BOOST_INIT_ONCE_INIT +#else +#define BOOST_INIT_ONCE_INIT =BOOST_ONCE_INIT +#endif + +typedef boost::chrono::milliseconds ms; + +boost::once_flag flg0 BOOST_INIT_ONCE_INIT; + +int init0_called = 0; + +void init0() +{ + boost::this_thread::sleep_for(ms(250)); + ++init0_called; +} + +void f0() +{ + boost::call_once(flg0, init0); +} + +boost::once_flag flg3 BOOST_INIT_ONCE_INIT; + +int init3_called = 0; +int init3_completed = 0; + +void init3() +{ + ++init3_called; + boost::this_thread::sleep_for(ms(250)); + if (init3_called == 1) + throw 1; + ++init3_completed; +} + +void f3() +{ + try + { + boost::call_once(flg3, init3); + } + catch (...) + { + } +} + +struct init1 +{ + static int called; + typedef void result_type; + + void operator()(int i) {called += i;} + void operator()(int i) const {called += i;} +}; + +int init1::called = 0; + +boost::once_flag flg1 BOOST_INIT_ONCE_INIT; + +void f1() +{ + boost::call_once(flg1, init1(), 1); +} + +boost::once_flag flg1_member BOOST_INIT_ONCE_INIT; + +struct init1_member +{ + static int called; + typedef void result_type; + void call(int i) { + called += i; + } +}; +int init1_member::called = 0; + +void f1_member_l() +{ + init1_member o; + int i=1; + boost::call_once(flg1_member, &init1_member::call, o, i); +} +void f1_member_r() +{ + init1_member o; + boost::call_once(flg1_member, &init1_member::call, o, 1); +} +struct init2 +{ + static int called; + typedef void result_type; + + void operator()(int i, int j) {called += i + j;} + void operator()(int i, int j) const {called += i + j;} +}; + +int init2::called = 0; + +boost::once_flag flg2 BOOST_INIT_ONCE_INIT; + +void f2() +{ + boost::call_once(flg2, init2(), 2, 3); + boost::call_once(flg2, init2(), 4, 5); +} + +boost::once_flag flg41 BOOST_INIT_ONCE_INIT; +boost::once_flag flg42 BOOST_INIT_ONCE_INIT; + +int init41_called = 0; +int init42_called = 0; + +void init42(); + +void init41() +{ + boost::this_thread::sleep_for(ms(250)); + ++init41_called; +} + +void init42() +{ + boost::this_thread::sleep_for(ms(250)); + ++init42_called; +} + +void f41() +{ + boost::call_once(flg41, init41); + boost::call_once(flg42, init42); +} + +void f42() +{ + boost::call_once(flg42, init42); + boost::call_once(flg41, init41); +} + +class MoveOnly +{ +public: + typedef void result_type; + + BOOST_THREAD_MOVABLE_ONLY(MoveOnly) + MoveOnly() + { + } + MoveOnly(BOOST_THREAD_RV_REF(MoveOnly)) + {} + + void operator()(BOOST_THREAD_RV_REF(MoveOnly)) + { + } + void operator()(int) + { + } + void operator()() + { + } +}; + + +struct id_string +{ + static boost::once_flag flag; + static void do_init(id_string & ) + {} + void operator()() + { + boost::call_once(flag, &id_string::do_init, boost::ref(*this)); + } +// void operator()(int,int) +// { +// // This should fail but works with gcc-4.6.3 +// //std::bind(&id_string::do_init, *this)(); +// std::bind(&id_string::do_init, std::ref(*this))(); +// } +// void operator()(int) const +// { +// //std::bind(&id_string::do_init, *this)(); +// } +}; + + +boost::once_flag id_string::flag BOOST_INIT_ONCE_INIT; + +int main() +{ + + // + { + id_string id; + id(); + //id(1,1); + } + // check basic functionality + { + boost::thread t0(f0); + boost::thread t1(f0); + t0.join(); + t1.join(); + BOOST_TEST(init0_called == 1); + } + // check basic exception safety + { + boost::thread t0(f3); + boost::thread t1(f3); + t0.join(); + t1.join(); + BOOST_TEST(init3_called == 2); + BOOST_TEST(init3_completed == 1); + } + // check deadlock avoidance + { + boost::thread t0(f41); + boost::thread t1(f42); + t0.join(); + t1.join(); + BOOST_TEST(init41_called == 1); + BOOST_TEST(init42_called == 1); + } + // check functors with 1 arg + { + boost::thread t0(f1); + boost::thread t1(f1); + t0.join(); + t1.join(); + BOOST_TEST(init1::called == 1); + } + // check functors with 2 args + { + boost::thread t0(f2); + boost::thread t1(f2); + t0.join(); + t1.join(); + BOOST_TEST(init2::called == 5); + } + + // check member function with 1 arg + { + boost::thread t0(f1_member_l); + boost::thread t1(f1_member_r); + t0.join(); + t1.join(); + BOOST_TEST(init1_member::called == 1); + } +#if defined BOOST_THREAD_PLATFORM_PTHREAD || (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ > 40600) + { + boost::once_flag f BOOST_INIT_ONCE_INIT; + boost::call_once(f, MoveOnly()); + } +#endif +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + boost::once_flag f BOOST_INIT_ONCE_INIT; + boost::call_once(f, MoveOnly(), 1); + } + { + boost::once_flag f BOOST_INIT_ONCE_INIT; + boost::call_once(f, MoveOnly(), MoveOnly()); + } +#endif // BOOST_THREAD_PLATFORM_PTHREAD + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp new file mode 100644 index 000000000..05a628230 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp @@ -0,0 +1,468 @@ +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/sync_queue.hpp> + +// class sync_queue<T> + +// sync_queue(); + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD + +#include <boost/thread/concurrent_queues/sync_queue.hpp> +#include <boost/thread/concurrent_queues/queue_adaptor.hpp> +#include <boost/thread/concurrent_queues/queue_views.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +class non_copyable +{ + int val; +public: + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + +}; + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES +BOOST_STATIC_ASSERT( ! boost::is_copy_constructible<non_copyable>::value ); +BOOST_STATIC_ASSERT( boost::has_move_emulation_enabled<non_copyable>::value ); +#endif + +int main() +{ + + { + // default queue invariants + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // default queue invariants + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + + + { + // empty queue try_pull fails + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + int i; + BOOST_TEST( boost::queue_op_status::empty == q.try_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue/copyable succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + q.push(1); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue/copyable succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + +#if 0 + { + // empty queue push rvalue/non_copyable succeeds + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_back<non_copyable> q(sq); + q.push(non_copyable(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // empty queue push rvalue/non_copyable succeeds + boost::queue_adaptor<boost::sync_queue<non_copyable> > q; + //boost::sync_queue<non_copyable> q; + //boost::queue_back<non_copyable> q(sq); + non_copyable nc(1); + q.push(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // empty queue push rvalue succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + q.push(1); + q.push(2); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#if 0 + { + // empty queue try_push rvalue/non-copyable succeeds + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_back<non_copyable> q(sq); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // empty queue try_push lvalue succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + int i=0; + BOOST_TEST(boost::queue_op_status::success == q.try_push(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + +#if 0 + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_back<non_copyable> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_back<non_copyable> q(sq); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc2(2); + q.pull(nc2); + BOOST_TEST_EQ(nc1, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + int i = q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc = q.pull(); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue try_pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue try_pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue nonblocking_pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue nonblocking_pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue wait_pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue wait_pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // closed invariants + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed invariants + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + q.close(); + try { + q.push(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + q.close(); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull fails + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/assign_fail.cpp new file mode 100644 index 000000000..041102e91 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/assign_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// recursive_mutex& operator=(const recursive_mutex&) = delete; + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_mutex m0; + boost::recursive_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/copy_fail.cpp new file mode 100644 index 000000000..932422d15 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/copy_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// recursive_mutex(const recursive_mutex&) = delete; + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_mutex m0; + boost::recursive_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/default_pass.cpp new file mode 100644 index 000000000..6b6199720 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// recursive_mutex(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/lock_pass.cpp new file mode 100644 index 000000000..a5410d25e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/lock_pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// void lock(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + + +boost::recursive_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + m.lock(); + t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/native_handle_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/native_handle_pass.cpp new file mode 100644 index 000000000..b784f24e5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/native_handle_pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// typedef pthread_recursive_mutex_t* native_handle_type; +// native_handle_type native_handle(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE + boost::recursive_mutex m; + boost::recursive_mutex::native_handle_type h = m.native_handle(); + BOOST_TEST(h); +#else +#error "Test not applicable: BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE not defined for this platform as not supported" +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/try_lock_pass.cpp new file mode 100644 index 000000000..0f8fe822a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/try_lock_pass.cpp @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// bool try_lock(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../timming.hpp" + +boost::recursive_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); +// BOOST_TEST(!m.try_lock()); +// BOOST_TEST(!m.try_lock()); +// BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + //time_point t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/assign_fail.cpp new file mode 100644 index 000000000..48b9cc47d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/assign_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_timed_mutex m0; + boost::recursive_timed_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp new file mode 100644 index 000000000..b4e96c7ac --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// recursive_timed_mutex(const recursive_timed_mutex&) = delete; + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_timed_mutex m0; + boost::recursive_timed_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp new file mode 100644 index 000000000..1e75b7b04 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// recursive_timed_mutex(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_timed_mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp new file mode 100644 index 000000000..bd0646f64 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// void lock(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../timming.hpp" + +boost::recursive_timed_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + m.lock(); + t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp new file mode 100644 index 000000000..bcd375e53 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// typedef pthread_recursive_mutex_t* native_handle_type; +// native_handle_type native_handle(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE + boost::recursive_timed_mutex m; + boost::recursive_timed_mutex::native_handle_type h = m.native_handle(); + BOOST_TEST(h); +#else +#error "Test not applicable: BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE not defined for this platform as not supported" +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp new file mode 100644 index 000000000..c7f6d2b0b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::recursive_timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(750)) == true); + t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); +} + +void f2() +{ + time_point t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(250)) == false); + time_point t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp new file mode 100644 index 000000000..3874d6853 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// bool try_lock(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::recursive_timed_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + //time_point t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp new file mode 100644 index 000000000..238467204 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/recursive_mutex> + +// class recursive_timed_mutex; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::recursive_timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(750)) == true); + t1 = Clock::now(); + m.unlock(); +} + +void f2() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(250)) == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/assign_fail.cpp new file mode 100644 index 000000000..ee6446d7e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/assign_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// shared_mutex& operator=(const shared_mutex&) = delete; + +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_mutex m0; + boost::shared_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/copy_fail.cpp new file mode 100644 index 000000000..9627f9f66 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/copy_fail.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// shared_mutex(const shared_mutex&) = delete; + +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_mutex m0; + boost::shared_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/default_pass.cpp new file mode 100644 index 000000000..730c9cafc --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/timed_mutex.hpp> + +// class shared_mutex; + +// shared_mutex(); + +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/lock_pass.cpp new file mode 100644 index 000000000..0b53fb275 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/lock_pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// void lock(); + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + m.lock(); + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp new file mode 100644 index 000000000..bc06576ec --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(750)) == true); + t1 = Clock::now(); + m.unlock(); +} + +void f2() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(250)) == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp new file mode 100644 index 000000000..515589a6f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// bool try_lock(); + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp new file mode 100644 index 000000000..dd8a1a816 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(750)) == true); + t1 = Clock::now(); + m.unlock(); +} + +void f2() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(250)) == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp new file mode 100644 index 000000000..9975a995a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp @@ -0,0 +1,252 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/sync_bounded_queue.hpp> + +// class sync_queue<T> + +// push || pull; + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/sync_bounded_queue.hpp> +#include <boost/thread/future.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> + +struct call_push +{ + boost::sync_bounded_queue<int> &q_; + boost::barrier& go_; + + call_push(boost::sync_bounded_queue<int> &q, boost::barrier &go) : + q_(q), go_(go) + { + } + typedef void result_type; + void operator()() + { + go_.count_down_and_wait(); + q_.push(42); + + } +}; + +struct call_push_2 +{ + boost::sync_bounded_queue<int> &q_; + boost::barrier& go_; + boost::barrier& end_; + + call_push_2(boost::sync_bounded_queue<int> &q, boost::barrier &go, boost::barrier &end) : + q_(q), go_(go), end_(end) + { + } + typedef void result_type; + void operator()() + { + go_.count_down_and_wait(); + q_.push(42); + end_.count_down_and_wait(); + + } +}; + +struct call_pull +{ + boost::sync_bounded_queue<int> &q_; + boost::barrier& go_; + + call_pull(boost::sync_bounded_queue<int> &q, boost::barrier &go) : + q_(q), go_(go) + { + } + typedef int result_type; + int operator()() + { + go_.count_down_and_wait(); + return q_.pull(); + } +}; + +void test_concurrent_push_and_pull_on_empty_queue() +{ + boost::sync_bounded_queue<int> q(4); + + boost::barrier go(2); + + boost::future<void> push_done; + boost::future<int> pull_done; + + try + { + push_done=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() + { + go.wait(); + q.push(42); + } +#else + call_push(q,go) +#endif + ); + pull_done=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() -> int + { + go.wait(); + return q.pull(); + } +#else + call_pull(q,go) +#endif + ); + + push_done.get(); + BOOST_TEST_EQ(pull_done.get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_push_on_empty_queue() +{ + boost::sync_bounded_queue<int> q(4); + const unsigned int n = 3; + boost::barrier go(n); + boost::future<void> push_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + push_done[i]=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() + { + go.wait(); + q.push(42); + } +#else + call_push(q,go) +#endif + ); + + for (unsigned int i = 0; i < n; ++i) + push_done[i].get(); + + BOOST_TEST(!q.empty()); + for (unsigned int i =0; i< n; ++i) + BOOST_TEST_EQ(q.pull(), 42); + BOOST_TEST(q.empty()); + + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_push_on_full_queue() +{ + const unsigned int size = 2; + boost::sync_bounded_queue<int> q(size); + const unsigned int n = 2*size; + boost::barrier go(n); + boost::barrier end(size+1); + boost::future<void> push_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + push_done[i]=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go,&end]() + { + go.wait(); + q.push(42); + end.wait(); + } +#else + call_push_2(q,go,end) +#endif + ); + + end.wait(); + BOOST_TEST(!q.empty()); + BOOST_TEST(q.full()); + for (unsigned int i =0; i< size; ++i) + BOOST_TEST_EQ(q.pull(), 42); + end.wait(); + + for (unsigned int i = 0; i < n; ++i) + push_done[i].get(); + + BOOST_TEST(!q.empty()); + for (unsigned int i =0; i< size; ++i) + BOOST_TEST_EQ(q.pull(), 42); + BOOST_TEST(q.empty()); + + } + catch (...) + { + BOOST_TEST(false); + } +} +void test_concurrent_pull_on_queue() +{ + boost::sync_bounded_queue<int> q(4); + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<int> pull_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + q.push(42); + + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() -> int + { + go.wait(); + return q.pull(); + } +#else + call_pull(q,go) +#endif + ); + + for (unsigned int i = 0; i < n; ++i) + BOOST_TEST_EQ(pull_done[i].get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +int main() +{ + test_concurrent_push_and_pull_on_empty_queue(); + test_concurrent_push_on_empty_queue(); + test_concurrent_push_on_full_queue(); + test_concurrent_pull_on_queue(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp new file mode 100644 index 000000000..201e0bc13 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp @@ -0,0 +1,600 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/sync_bounded_queue.hpp> + +// class sync_bounded_queue<T> + +// sync_bounded_queue(); + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD + +#include <boost/thread/sync_bounded_queue.hpp> + +#include <boost/detail/lightweight_test.hpp> + +class non_copyable +{ + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + int val; +public: + non_copyable() {} + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + +}; + + +int main() +{ + + { + // default queue invariants + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST_EQ(q.capacity(), 2u); + BOOST_TEST(! q.closed()); + } +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + { + // empty queue try_pull fails + boost::sync_bounded_queue<int> q(2); + int i; + BOOST_TEST(! q.try_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_pull fails + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(! q.try_pull()); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + q.push(1); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + q.push(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<int> q(3); + q.push(1); + BOOST_TEST_EQ(q.size(), 1u); + q.push(2); + BOOST_TEST_EQ(q.size(), 2u); + q.push(2); + BOOST_TEST_EQ(q.size(), 3u); + BOOST_TEST(! q.empty()); + BOOST_TEST( q.full()); + BOOST_TEST(! q.closed()); + } + { + // empty queue push value succeeds + boost::sync_bounded_queue<int> q(2); + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + BOOST_TEST(q.try_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push value succeeds + boost::sync_bounded_queue<int> q(2); + int i=1; + BOOST_TEST(q.try_push(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(q.try_push(boost::no_block, 1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + BOOST_TEST(q.try_push(boost::no_block, boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + q.push(boost::move(nc)); + non_copyable nc2(2); + q.pull(nc2); + BOOST_TEST_EQ(nc, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + int i = q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + int i; + BOOST_TEST(q.try_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + int i; + BOOST_TEST(q.try_pull(boost::no_block, i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + boost::shared_ptr<int> i = q.try_pull(); + BOOST_TEST_EQ(*i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // full queue try_push rvalue fails + boost::sync_bounded_queue<int> q(2); + q.push(1); + q.push(2); + BOOST_TEST(! q.try_push(3)); + BOOST_TEST(! q.empty()); + BOOST_TEST( q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + { + // full queue try_push succeeds + boost::sync_bounded_queue<int> q(2); + q.push(1); + q.push(2); + BOOST_TEST(q.try_pull()); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + { + // closed invariants + boost::sync_bounded_queue<int> q(2); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::sync_bounded_queue<int> q(2); + q.close(); + try { + q.push(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + q.close(); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } +#endif + { + // empty queue try_pull fails + boost::sync_bounded_queue<int> q(2); + int i; + BOOST_TEST( boost::queue_op_status::empty == q.try_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + q.push_back(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<int> q(3); + q.push_back(1); + BOOST_TEST_EQ(q.size(), 1u); + q.push_back(2); + BOOST_TEST_EQ(q.size(), 2u); + q.push_back(3); + BOOST_TEST_EQ(q.size(), 3u); + BOOST_TEST(! q.empty()); + BOOST_TEST( q.full()); + BOOST_TEST(! q.closed()); + } + { + // empty queue push value succeeds + boost::sync_bounded_queue<int> q(2); + int i; + q.push_back(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push value succeeds + boost::sync_bounded_queue<int> q(2); + int i=1; + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back( 1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue wait_push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_push_back(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue wait_push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.wait_push_back(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue wait_push value succeeds + boost::sync_bounded_queue<int> q(2); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_push_back(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + int i; + q.pull_front(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + q.push_back(boost::move(nc)); + non_copyable nc2(2); + q.pull_front(nc2); + BOOST_TEST_EQ(nc, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + int i = q.pull_front(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue nonblocking_pull_front succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull_front succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // full queue try_push rvalue fails + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + q.push_back(2); + BOOST_TEST(boost::queue_op_status::full == q.try_push_back(3)); + BOOST_TEST(! q.empty()); + BOOST_TEST( q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + + { + // closed invariants + boost::sync_bounded_queue<int> q(2); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::sync_bounded_queue<int> q(2); + q.close(); + try { + q.push_back(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // closed empty queue try_pull_front closed + boost::sync_bounded_queue<int> q(2); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.try_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue nonblocking_pull_front closed + boost::sync_bounded_queue<int> q(2); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.nonblocking_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue pull_front succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + q.close(); + int i; + q.pull_front(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull_front succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull_front closed + boost::sync_bounded_queue<int> q(2); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + { + // closed queue wait_push_back fails + boost::sync_bounded_queue<int> q(2); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_push_back(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp new file mode 100644 index 000000000..703c54f40 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp @@ -0,0 +1,256 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/concurrent_queues/sync_deque.hpp> + +// class sync_deque<T> + +// push || pull; + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/concurrent_queues/sync_deque.hpp> +#include <boost/thread/future.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> + +template <typename ValueType> +struct call_push_back +{ + boost::sync_deque<ValueType> *q_; + boost::barrier *go_; + + call_push_back(boost::sync_deque<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef void result_type; + void operator()() + { + go_->count_down_and_wait(); + q_->push_back(42); + } +}; + +template <typename ValueType> +struct call_pull_front +{ + boost::sync_deque<ValueType> *q_; + boost::barrier *go_; + + call_pull_front(boost::sync_deque<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef ValueType result_type; + ValueType operator()() + { + go_->count_down_and_wait(); + return q_->pull_front(); + } +}; + +template <typename ValueType> +struct call_wait_pull_front +{ + boost::sync_deque<ValueType> *q_; + boost::barrier *go_; + + call_wait_pull_front(boost::sync_deque<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef boost::queue_op_status result_type; + boost::queue_op_status operator()(ValueType& v) + { + go_->wait(); + return q_->wait_pull_front(v); + } +}; + +void test_concurrent_push_back_and_pull_front_on_empty_queue() +{ + boost::sync_deque<int> q; + + boost::barrier go(2); + + boost::future<void> push_done; + boost::future<int> pull_done; + + try + { + push_done=boost::async(boost::launch::async, + call_push_back<int>(&q,&go)); + pull_done=boost::async(boost::launch::async, + call_pull_front<int>(&q,&go)); + + push_done.get(); + BOOST_TEST_EQ(pull_done.get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +void test_concurrent_push_back_and_wait_pull_front_on_empty_queue() +{ + boost::sync_deque<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<boost::queue_op_status> pull_done[n]; + int results[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, + call_wait_pull_front<int>(&q,&go), + boost::ref(results[i])); + + for (unsigned int i =0; i< n; ++i) + q.push_back(42); + + for (unsigned int i = 0; i < n; ++i) { + BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success); + BOOST_TEST_EQ(results[i], 42); + } + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_wait_pull_front_and_close_on_empty_queue() +{ + boost::sync_deque<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<boost::queue_op_status> pull_done[n]; + int results[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, + call_wait_pull_front<int>(&q,&go), + boost::ref(results[i])); + + q.close(); + + for (unsigned int i = 0; i < n; ++i) { + BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed); + } + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} +#endif + +void test_concurrent_push_back_on_empty_queue() +{ + boost::sync_deque<int> q; + const unsigned int n = 3; + boost::barrier go(n); + boost::future<void> push_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + push_done[i]=boost::async(boost::launch::async, + call_push_back<int>(&q,&go)); + + } + catch (...) + { + BOOST_TEST(false); + } + try + { + for (unsigned int i = 0; i < n; ++i) + push_done[i].get(); + + } + catch (...) + { + BOOST_TEST(false); + } + try + { + BOOST_TEST(!q.empty()); + for (unsigned int i =0; i< n; ++i) + BOOST_TEST_EQ(q.pull_front(), 42); + BOOST_TEST(q.empty()); + + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_pull_front_on_queue() +{ + boost::sync_deque<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<int> pull_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + q.push_back(42); + + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() -> int + { + go.wait(); + return q.pull_front(); + } +#else + call_pull_front<int>(&q,&go) +#endif + ); + + for (unsigned int i = 0; i < n; ++i) + BOOST_TEST_EQ(pull_done[i].get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +int main() +{ + test_concurrent_push_back_and_pull_front_on_empty_queue(); +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + test_concurrent_push_back_and_wait_pull_front_on_empty_queue(); + test_concurrent_wait_pull_front_and_close_on_empty_queue(); +#endif + test_concurrent_push_back_on_empty_queue(); + test_concurrent_pull_front_on_queue(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp new file mode 100644 index 000000000..5170bcf61 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp @@ -0,0 +1,403 @@ +// Copyright (C) 2013,2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/concurrent_queues/sync_deque.hpp> + +// class sync_deque<T> + +// sync_deque(); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/concurrent_queues/sync_deque.hpp> + +#include <boost/detail/lightweight_test.hpp> + +class non_copyable +{ + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + int val; +public: + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + +}; + + + +int main() +{ + + { + // default queue invariants + boost::sync_deque<int> q; + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_pull fails + boost::sync_deque<int> q; + int i; + BOOST_TEST( boost::queue_op_status::empty == q.try_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue/copyable succeeds + boost::sync_deque<int> q; + q.push_back(1); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue/copyable succeeds + boost::sync_deque<int> q; + int i; + q.push_back(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue push rvalue/non_copyable succeeds + boost::sync_deque<non_copyable> q; + q.push_back(non_copyable(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue push rvalue/non_copyable succeeds + boost::sync_deque<non_copyable> q; + non_copyable nc(1); + q.push_back(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + { + // empty queue push rvalue succeeds + boost::sync_deque<int> q; + q.push_back(1); + q.push_back(2); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue succeeds + boost::sync_deque<int> q; + int i; + q.push_back(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::sync_deque<int> q; + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::sync_deque<int> q; + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue try_push rvalue/non-copyable succeeds + boost::sync_deque<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue try_push rvalue/non-copyable succeeds + boost::sync_deque<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + { + // empty queue try_push lvalue succeeds + boost::sync_deque<int> q; + int i=1; + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_deque<int> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue nonblocking_push_back rvalue/non-copyable succeeds + boost::sync_deque<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue nonblocking_push_back rvalue/non-copyable succeeds + boost::sync_deque<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + int i; + q.pull_front(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc2(2); + q.pull_front(nc2); + BOOST_TEST_EQ(nc1, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + int i = q.pull_front(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc = q.pull_front(); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue nonblocking_pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue nonblocking_pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + + { + // closed invariants + boost::sync_deque<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::sync_deque<int> q; + q.close(); + try { + q.push_back(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::sync_deque<int> q; + q.push_back(1); + q.close(); + int i; + q.pull_front(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull_front fails + boost::sync_deque<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp new file mode 100644 index 000000000..92e183079 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp @@ -0,0 +1,219 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <exception> + +#include <boost/thread/thread.hpp> +#include <boost/thread/barrier.hpp> +#include <boost/thread/concurrent_queues/sync_priority_queue.hpp> + +#include <boost/core/lightweight_test.hpp> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::concurrent::sync_priority_queue<int> sync_pq; + +int call_pull(sync_pq* q, boost::barrier* go) +{ + go->wait(); + return q->pull(); + +} + +void call_push(sync_pq* q, boost::barrier* go, int val) +{ + go->wait(); + q->push(val); +} + +void test_pull(const int n) +{ + sync_pq pq; + BOOST_TEST(pq.empty()); + for(int i = 0; i < n; i++) + { + pq.push(i); + } + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(n)); + pq.close(); + BOOST_TEST(pq.closed()); + boost::barrier b(n); + boost::thread_group tg; + for(int i = 0; i < n; i++) + { + tg.create_thread(boost::bind(call_pull, &pq, &b)); + } + tg.join_all(); + BOOST_TEST(pq.empty()); +} + +void test_push(const int n) +{ + sync_pq pq; + BOOST_TEST(pq.empty()); + + boost::barrier b(n); + boost::thread_group tg; + for(int i = 0; i < n; i++) + { + tg.create_thread(boost::bind(call_push, &pq, &b, i)); + } + tg.join_all(); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(n)); +} + +void test_both(const int n) +{ + sync_pq pq; + BOOST_TEST(pq.empty()); + + boost::barrier b(2*n); + boost::thread_group tg; + for(int i = 0; i < n; i++) + { + tg.create_thread(boost::bind(call_pull, &pq, &b)); + tg.create_thread(boost::bind(call_push, &pq, &b, i)); + } + tg.join_all(); + BOOST_TEST(pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(0)); +} + +void push_range(sync_pq* q, const int begin, const int end) +{ + for(int i = begin; i < end; i++) + q->push(i); +} + +void atomic_pull(sync_pq* q, boost::atomic<int>* sum) +{ + while(1) + { + try{ + const int val = q->pull(); + sum->fetch_add(val); + } + catch(std::exception& ){ + break; + } + } +} + +/** + * This test computes the sum of the first N integers upto $limit using + * $n threads for the push operation and $n threads for the pull and count + * operation. The push operation push a range of numbers on the queue while + * the pull operation pull from the queue and increments an atomic int. + * At the end of execution the value of atomic<int> $sum should be the same + * as n*(n+1)/2 as this is the closed form solution to this problem. + */ +void compute_sum(const int n) +{ + const int limit = 1000; + sync_pq pq; + BOOST_TEST(pq.empty()); + boost::atomic<int> sum(0); + boost::thread_group tg1; + boost::thread_group tg2; + for(int i = 0; i < n; i++) + { + tg1.create_thread(boost::bind(push_range, &pq, i*(limit/n)+1, (i+1)*(limit/n)+1)); + tg2.create_thread(boost::bind(atomic_pull, &pq, &sum)); + } + tg1.join_all(); + pq.close(); //Wait until all enqueuing is done before closing. + BOOST_TEST(pq.closed()); + tg2.join_all(); + BOOST_TEST(pq.empty()); + BOOST_TEST_EQ(sum.load(), limit*(limit+1)/2); +} + +void move_between_queues(sync_pq* q1, sync_pq* q2) +{ + while(1){ + try{ + const int val = q1->pull(); + q2->push(val); + } + catch(std::exception& ){ + break; + } + } +} + +/** + * This test computes the sum of the first N integers upto $limit by moving + * numbers between 2 sync_priority_queues. A range of numbers are pushed onto + * one queue by $n threads while $n threads pull from this queue and push onto + * another sync_pq. At the end the main thread ensures the the values in the + * second queue are in proper order and then sums all the values from this + * queue. The sum should match n*(n+1)/2, the closed form solution to this + * problem. + */ +void sum_with_moving(const int n) +{ + const int limit = 1000; + sync_pq pq1; + sync_pq pq2; + BOOST_TEST(pq1.empty()); + BOOST_TEST(pq2.empty()); + boost::thread_group tg1; + boost::thread_group tg2; + for(int i = 0; i < n; i++) + { + tg1.create_thread(boost::bind(push_range, &pq1, i*(limit/n)+1, (i+1)*(limit/n)+1)); + tg2.create_thread(boost::bind(move_between_queues, &pq1, &pq2)); + } + tg1.join_all(); + pq1.close(); //Wait until all enqueuing is done before closing. + BOOST_TEST(pq1.closed()); + tg2.join_all(); + BOOST_TEST(pq1.empty()); + BOOST_TEST(!pq2.empty()); + int sum = 0; + for(int i = 1000; i > 0; i--){ + const int val = pq2.pull(); + BOOST_TEST_EQ(i,val); + sum += val; + } + BOOST_TEST(pq2.empty()); + BOOST_TEST_EQ(sum, limit*(limit+1)/2); +} + +int main() +{ + for(int i = 1; i <= 64; i *= 2) + { + test_pull(i); + test_push(i); + test_both(i); + } + //These numbers must divide 1000 + compute_sum(1); + compute_sum(4); + compute_sum(10); + compute_sum(25); + compute_sum(50); + sum_with_moving(1); + sum_with_moving(4); + sum_with_moving(10); + sum_with_moving(25); + sum_with_moving(50); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp new file mode 100644 index 000000000..b51827731 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp @@ -0,0 +1,429 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014,2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <iostream> + +#include <boost/thread.hpp> +#include <boost/chrono.hpp> +#include <boost/thread/concurrent_queues/sync_priority_queue.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +using namespace boost::chrono; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +typedef boost::concurrent::sync_priority_queue<int> sync_pq; + +class non_copyable +{ + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + int val; +public: + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + bool operator <(const non_copyable& other) const + { + return val < other.val; + } +}; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void test_pull_for() +{ + sync_pq pq; + steady_clock::time_point start = steady_clock::now(); + int val; + boost::queue_op_status st = pq.pull_for(milliseconds(500), val); + ns d = steady_clock::now() - start - milliseconds(500); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(boost::queue_op_status::timeout == st); +} + +void test_pull_until() +{ + sync_pq pq; + steady_clock::time_point start = steady_clock::now(); + int val; + boost::queue_op_status st = pq.pull_until(start + milliseconds(500), val); + ns d = steady_clock::now() - start - milliseconds(500); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(boost::queue_op_status::timeout == st); +} + +void test_nonblocking_pull() +{ + sync_pq pq; + steady_clock::time_point start = steady_clock::now(); + int val; + boost::queue_op_status st = pq.nonblocking_pull(val); + ns d = steady_clock::now() - start; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(boost::queue_op_status::empty == st); +} + +void test_pull_for_when_not_empty() +{ + sync_pq pq; + pq.push(1); + steady_clock::time_point start = steady_clock::now(); + int val; + boost::queue_op_status st = pq.pull_for(milliseconds(500), val); + ns d = steady_clock::now() - start; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(boost::queue_op_status::success == st); + BOOST_TEST(1 == val); +} + +void test_pull_until_when_not_empty() +{ + sync_pq pq; + pq.push(1); + steady_clock::time_point start = steady_clock::now(); + int val; + boost::queue_op_status st = pq.pull_until(start + milliseconds(500), val); + ns d = steady_clock::now() - start; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(boost::queue_op_status::success == st); + BOOST_TEST(1 == val); +} + +int main() +{ + sync_pq pq; + BOOST_TEST(pq.empty()); + BOOST_TEST(!pq.closed()); + BOOST_TEST_EQ(pq.size(), std::size_t(0)); + + for(int i = 1; i <= 5; i++){ + pq.push(i); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 6; i <= 10; i++){ + boost::queue_op_status succ = pq.try_push(i); + BOOST_TEST(succ == boost::queue_op_status::success ); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 10; i > 5; i--){ + int val = pq.pull(); + BOOST_TEST_EQ(val, i); + } + +// for(int i = 5; i > 0; i--){ +// boost::optional<int> val = pq.try_pull(); +// BOOST_TEST(val); +// BOOST_TEST_EQ(*val, i); +// } + +// BOOST_TEST(pq.empty()); + pq.close(); + BOOST_TEST(pq.closed()); + + test_pull_for(); + test_pull_until(); + test_nonblocking_pull(); + + test_pull_for_when_not_empty(); + //test_pull_until_when_not_empty(); + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue try_push rvalue/non-copyable succeeds + boost::concurrent::sync_priority_queue<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + //fixme + // empty queue try_push rvalue/non-copyable succeeds + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // empty queue try_push lvalue succeeds + boost::concurrent::sync_priority_queue<int> q; + int i=1; + BOOST_TEST(boost::queue_op_status::success == q.try_push(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#if 0 + { + // empty queue try_push rvalue succeeds + boost::concurrent::sync_priority_queue<int> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::concurrent::sync_priority_queue<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // 1-element queue pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + int i; + i=q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // 1-element queue pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc2(2); + nc2=q.pull(); + BOOST_TEST_EQ(nc1, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // 1-element queue pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + int i = q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // 1-element queue pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc = q.pull(); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // 1-element queue try_pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // 1-element queue try_pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue nonblocking_pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // 1-element queue nonblocking_pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue wait_pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // 1-element queue wait_pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // closed invariants + boost::concurrent::sync_priority_queue<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::concurrent::sync_priority_queue<int> q; + q.close(); + try { + q.push(1); + BOOST_TEST(false); // fixme + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + q.close(); + int i; + i=q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull fails + boost::concurrent::sync_priority_queue<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_multi_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_multi_thread_pass.cpp new file mode 100644 index 000000000..77656f8b3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_multi_thread_pass.cpp @@ -0,0 +1,124 @@ +// Copyright (C) 2019 Austin Beer +// Copyright (C) 2019 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread.hpp> +#include <boost/chrono.hpp> +#include <boost/thread/concurrent_queues/sync_timed_queue.hpp> + +#include <boost/core/lightweight_test.hpp> +#include "../../../timming.hpp" + +using namespace boost::chrono; + +typedef boost::concurrent::sync_timed_queue<int> sync_tq; + +const int cnt = 5; + +void call_push(sync_tq* q, const steady_clock::time_point start) +{ + // push elements onto the queue every 500 milliseconds but with a decreasing delay each time + for (int i = 0; i < cnt; ++i) + { + boost::this_thread::sleep_until(start + milliseconds(i * 500)); + const steady_clock::time_point expected = start + milliseconds(i * 500) + seconds(cnt - i); + q->push(i, expected); + } +} + +void call_pull(sync_tq* q, const steady_clock::time_point start) +{ + // pull elements off of the queue (earliest element first) + for (int i = cnt - 1; i >= 0; --i) + { + int j; + q->pull(j); + BOOST_TEST_EQ(i, j); + const steady_clock::time_point expected = start + milliseconds(i * 500) + seconds(cnt - i); + BOOST_TEST_GE(steady_clock::now(), expected - milliseconds(BOOST_THREAD_TEST_TIME_MS)); + BOOST_TEST_LE(steady_clock::now(), expected + milliseconds(BOOST_THREAD_TEST_TIME_MS)); + } +} + +void call_pull_until(sync_tq* q, const steady_clock::time_point start) +{ + // pull elements off of the queue (earliest element first) + for (int i = cnt - 1; i >= 0; --i) + { + int j; + q->pull_until(steady_clock::now() + hours(1), j); + BOOST_TEST_EQ(i, j); + const steady_clock::time_point expected = start + milliseconds(i * 500) + seconds(cnt - i); + BOOST_TEST_GE(steady_clock::now(), expected - milliseconds(BOOST_THREAD_TEST_TIME_MS)); + BOOST_TEST_LE(steady_clock::now(), expected + milliseconds(BOOST_THREAD_TEST_TIME_MS)); + } +} + +void call_pull_for(sync_tq* q, const steady_clock::time_point start) +{ + // pull elements off of the queue (earliest element first) + for (int i = cnt - 1; i >= 0; --i) + { + int j; + q->pull_for(hours(1), j); + BOOST_TEST_EQ(i, j); + const steady_clock::time_point expected = start + milliseconds(i * 500) + seconds(cnt - i); + BOOST_TEST_GE(steady_clock::now(), expected - milliseconds(BOOST_THREAD_TEST_TIME_MS)); + BOOST_TEST_LE(steady_clock::now(), expected + milliseconds(BOOST_THREAD_TEST_TIME_MS)); + } +} + +void test_push_while_pull() +{ + sync_tq tq; + BOOST_TEST(tq.empty()); + boost::thread_group tg; + const steady_clock::time_point start = steady_clock::now(); + tg.create_thread(boost::bind(call_push, &tq, start)); + tg.create_thread(boost::bind(call_pull, &tq, start)); + tg.join_all(); + BOOST_TEST(tq.empty()); +} + +void test_push_while_pull_until() +{ + sync_tq tq; + BOOST_TEST(tq.empty()); + boost::thread_group tg; + const steady_clock::time_point start = steady_clock::now(); + tg.create_thread(boost::bind(call_push, &tq, start)); + tg.create_thread(boost::bind(call_pull_until, &tq, start)); + tg.join_all(); + BOOST_TEST(tq.empty()); +} + +void test_push_while_pull_for() +{ + sync_tq tq; + BOOST_TEST(tq.empty()); + boost::thread_group tg; + const steady_clock::time_point start = steady_clock::now(); + tg.create_thread(boost::bind(call_push, &tq, start)); + tg.create_thread(boost::bind(call_pull_for, &tq, start)); + tg.join_all(); + BOOST_TEST(tq.empty()); +} + +int main() +{ + test_push_while_pull(); + test_push_while_pull_until(); + test_push_while_pull_for(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp new file mode 100644 index 000000000..dd4dfc17f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp @@ -0,0 +1,155 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread.hpp> +#include <boost/chrono.hpp> +#include <boost/function.hpp> +#include <boost/thread/concurrent_queues/sync_timed_queue.hpp> +#include <boost/thread/executors/work.hpp> + +#include <boost/core/lightweight_test.hpp> + +using namespace boost::chrono; + +typedef boost::concurrent::sync_timed_queue<int> sync_tq; + +void test_all() +{ + sync_tq pq; + BOOST_TEST(pq.empty()); + BOOST_TEST(!pq.closed()); + BOOST_TEST_EQ(pq.size(), std::size_t(0)); + + for(int i = 1; i <= 5; i++){ + pq.push(i, milliseconds(i*100)); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 6; i <= 10; i++){ + pq.push(i,steady_clock::now() + milliseconds(i*100)); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 1; i <= 10; i++){ + int val = pq.pull(); + BOOST_TEST_EQ(val, i); + } + + int val; + boost::queue_op_status st = pq.nonblocking_pull(val); + BOOST_TEST(boost::queue_op_status::empty == st); + + BOOST_TEST(pq.empty()); + pq.close(); + BOOST_TEST(pq.closed()); +} + +void test_all_with_try() +{ + sync_tq pq; + BOOST_TEST(pq.empty()); + BOOST_TEST(!pq.closed()); + BOOST_TEST_EQ(pq.size(), std::size_t(0)); + + for(int i = 1; i <= 5; i++){ + boost::queue_op_status st = pq.try_push(i, milliseconds(i*100)); + BOOST_TEST(st == boost::queue_op_status::success ); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 6; i <= 10; i++){ + boost::queue_op_status st = pq.try_push(i,steady_clock::now() + milliseconds(i*100)); + BOOST_TEST(st == boost::queue_op_status::success ); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 1; i <= 10; i++){ + int val=0; + boost::queue_op_status st = pq.wait_pull(val); + BOOST_TEST(st == boost::queue_op_status::success ); + BOOST_TEST_EQ(val, i); + } + + int val; + boost::queue_op_status st = pq.nonblocking_pull(val); + BOOST_TEST(st == boost::queue_op_status::empty ); + + BOOST_TEST(pq.empty()); + pq.close(); + BOOST_TEST(pq.closed()); +} + +void func(steady_clock::time_point pushed, steady_clock::duration dur) +{ + BOOST_TEST(pushed + dur <= steady_clock::now()); +} +void func2() +{ + BOOST_TEST(false); +} + +/** + * This test ensures that when items come of the front of the queue + * that at least $dur has elapsed. + */ +void test_deque_times() +{ + boost::concurrent::sync_timed_queue<boost::function<void()> > tq; + for(int i = 0; i < 10; i++) + { + steady_clock::duration d = milliseconds(i*100); + boost::function<void()> fn = boost::bind(func, steady_clock::now(), d); + tq.push(fn, d); + } + while(!tq.empty()) + { + boost::function<void()> fn = tq.pull(); + fn(); + } +} + +/** + * This test ensures that when items come of the front of the queue + * that at least $dur has elapsed. + */ +#if 0 +void test_deque_times2() +{ + boost::concurrent::sync_timed_queue<boost::executors::work> tq; + for(int i = 0; i < 10; i++) + { + steady_clock::duration d = milliseconds(i*100); + tq.push(func2, d); + } + while(!tq.empty()) + { + boost::executors::work fn = tq.pull(); + fn(); + } +} +#endif + +int main() +{ + test_all(); + test_all_with_try(); + test_deque_times(); + //test_deque_times2(); // rt fails + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp new file mode 100644 index 000000000..556ca68e9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp @@ -0,0 +1,256 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/sync_queue.hpp> + +// class sync_queue<T> + +// push || pull; + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/sync_queue.hpp> +#include <boost/thread/future.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> + +template <typename ValueType> +struct call_push +{ + boost::sync_queue<ValueType> *q_; + boost::barrier *go_; + + call_push(boost::sync_queue<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef void result_type; + void operator()() + { + go_->count_down_and_wait(); + q_->push(42); + } +}; + +template <typename ValueType> +struct call_pull +{ + boost::sync_queue<ValueType> *q_; + boost::barrier *go_; + + call_pull(boost::sync_queue<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef ValueType result_type; + ValueType operator()() + { + go_->count_down_and_wait(); + return q_->pull(); + } +}; + +template <typename ValueType> +struct call_wait_pull +{ + boost::sync_queue<ValueType> *q_; + boost::barrier *go_; + + call_wait_pull(boost::sync_queue<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef boost::queue_op_status result_type; + boost::queue_op_status operator()(ValueType& v) + { + go_->wait(); + return q_->wait_pull(v); + } +}; + +void test_concurrent_push_and_pull_on_empty_queue() +{ + boost::sync_queue<int> q; + + boost::barrier go(2); + + boost::future<void> push_done; + boost::future<int> pull_done; + + try + { + push_done=boost::async(boost::launch::async, + call_push<int>(&q,&go)); + pull_done=boost::async(boost::launch::async, + call_pull<int>(&q,&go)); + + push_done.get(); + BOOST_TEST_EQ(pull_done.get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +void test_concurrent_push_and_wait_pull_on_empty_queue() +{ + boost::sync_queue<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<boost::queue_op_status> pull_done[n]; + int results[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, + call_wait_pull<int>(&q,&go), + boost::ref(results[i])); + + for (unsigned int i =0; i< n; ++i) + q.push(42); + + for (unsigned int i = 0; i < n; ++i) { + BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success); + BOOST_TEST_EQ(results[i], 42); + } + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_wait_pull_and_close_on_empty_queue() +{ + boost::sync_queue<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<boost::queue_op_status> pull_done[n]; + int results[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, + call_wait_pull<int>(&q,&go), + boost::ref(results[i])); + + q.close(); + + for (unsigned int i = 0; i < n; ++i) { + BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed); + } + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} +#endif + +void test_concurrent_push_on_empty_queue() +{ + boost::sync_queue<int> q; + const unsigned int n = 3; + boost::barrier go(n); + boost::future<void> push_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + push_done[i]=boost::async(boost::launch::async, + call_push<int>(&q,&go)); + + } + catch (...) + { + BOOST_TEST(false); + } + try + { + for (unsigned int i = 0; i < n; ++i) + push_done[i].get(); + + } + catch (...) + { + BOOST_TEST(false); + } + try + { + BOOST_TEST(!q.empty()); + for (unsigned int i =0; i< n; ++i) + BOOST_TEST_EQ(q.pull(), 42); + BOOST_TEST(q.empty()); + + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_pull_on_queue() +{ + boost::sync_queue<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<int> pull_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + q.push(42); + + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() -> int + { + go.wait(); + return q.pull(); + } +#else + call_pull<int>(&q,&go) +#endif + ); + + for (unsigned int i = 0; i < n; ++i) + BOOST_TEST_EQ(pull_done[i].get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +int main() +{ + test_concurrent_push_and_pull_on_empty_queue(); +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + test_concurrent_push_and_wait_pull_on_empty_queue(); + test_concurrent_wait_pull_and_close_on_empty_queue(); +#endif + test_concurrent_push_on_empty_queue(); + test_concurrent_pull_on_queue(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/single_thread_pass.cpp new file mode 100644 index 000000000..8f47ec82a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/single_thread_pass.cpp @@ -0,0 +1,374 @@ +// Copyright (C) 2013,2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/sync_queue.hpp> + +// class sync_queue<T> + +// sync_queue(); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/sync_queue.hpp> + +#include <boost/detail/lightweight_test.hpp> + +class non_copyable +{ + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + int val; +public: + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + +}; + + + +int main() +{ + + { + // default queue invariants + boost::sync_queue<int> q; + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue push rvalue/non_copyable succeeds + boost::sync_queue<non_copyable> q; + q.push(non_copyable(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue push rvalue/non_copyable succeeds + boost::sync_queue<non_copyable> q; + non_copyable nc(1); + q.push(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + { + // empty queue push rvalue succeeds + boost::sync_queue<int> q; + q.push(1); + q.push(2); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue succeeds + boost::sync_queue<int> q; + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::sync_queue<int> q; + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::sync_queue<int> q; + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue try_push rvalue/non-copyable succeeds + boost::sync_queue<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue try_push rvalue/non-copyable succeeds + boost::sync_queue<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + { + // empty queue try_push lvalue succeeds + boost::sync_queue<int> q; + int i=1; + BOOST_TEST(boost::queue_op_status::success == q.try_push(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_queue<int> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::sync_queue<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::sync_queue<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_queue<int> q; + q.push(1); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc2(2); + q.pull(nc2); + BOOST_TEST_EQ(nc1, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_queue<int> q; + q.push(1); + int i = q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc = q.pull(); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue nonblocking_pull succeed + boost::sync_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue nonblocking_pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull succeed + boost::sync_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + + { + // closed invariants + boost::sync_queue<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::sync_queue<int> q; + q.close(); + try { + q.push(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::sync_queue<int> q; + q.push(1); + q.close(); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull succeed + boost::sync_queue<int> q; + q.push(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull fails + boost::sync_queue<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/call_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/call_pass.cpp new file mode 100644 index 000000000..f1ed8be4a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/call_pass.cpp @@ -0,0 +1,144 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// template <typename F> +// inline typename boost::result_of<F(value_type&)>::type +// operator()(BOOST_THREAD_RV_REF(F) fct); +// template <typename F> +// inline typename boost::result_of<F(value_type const&)>::type +// operator()(BOOST_THREAD_RV_REF(F) fct) const; + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +struct S { + int f() const {return 1;} + int g() {return 1;} +}; + +void c(S const& s) +{ + BOOST_TEST(s.f()==1); +} + +void nc(S & s) +{ + BOOST_TEST(s.f()==1); + BOOST_TEST(s.g()==1); +} + +struct cfctr { + typedef void result_type; + void operator()(S const& s) const { + BOOST_TEST(s.f()==1); + } +}; +struct ncfctr { + typedef void result_type; + void operator()(S& s) const { + BOOST_TEST(s.f()==1); + BOOST_TEST(s.g()==1); + } +}; + +struct cfctr3 { + typedef void result_type; + BOOST_THREAD_MOVABLE_ONLY(cfctr3) + cfctr3() + {} + cfctr3(BOOST_THREAD_RV_REF(cfctr3)) + {} + void operator()(S const& s) const { + BOOST_TEST(s.f()==1); + } +}; +struct ncfctr3 { + typedef void result_type; + BOOST_THREAD_MOVABLE_ONLY(ncfctr3) + ncfctr3() + {} + ncfctr3(BOOST_THREAD_RV_REF(ncfctr3)) + {} + void operator()(S& s) const { + BOOST_TEST(s.f()==1); + BOOST_TEST(s.g()==1); + } +}; + +cfctr3 make_cfctr3() { + return BOOST_THREAD_MAKE_RV_REF(cfctr3()); +} + +ncfctr3 make_ncfctr3() { + return BOOST_THREAD_MAKE_RV_REF(ncfctr3()); +} + +int main() +{ + { + boost::synchronized_value<S> v; + v(&nc); + v(&c); + } + { + const boost::synchronized_value<S> v; + v(&c); + } + { + boost::synchronized_value<S> v; + v(ncfctr()); + } + { + const boost::synchronized_value<S> v; + v(cfctr()); + } + { + boost::synchronized_value<S> v; + ncfctr fct; + v(fct); + } + { + const boost::synchronized_value<S> v; + cfctr fct; + v(fct); + } + { + boost::synchronized_value<S> v; + v(make_ncfctr3()); + } + { + const boost::synchronized_value<S> v; + v(make_cfctr3()); + } +#if ! defined BOOST_NO_CXX11_LAMBDAS + { + boost::synchronized_value<S> v; + v([](S& s) { + BOOST_TEST(s.f()==1); + BOOST_TEST(s.g()==1); + }); + } + { + const boost::synchronized_value<S> v; + v([](S const& s) { + BOOST_TEST(s.f()==1); + }); + } +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_assign_pass.cpp new file mode 100644 index 000000000..3b43f8f90 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_assign_pass.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value& operator=(T const&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + int i = 1; + boost::synchronized_value<int> v; + v = i; + BOOST_TEST(v.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_ctor_pass.cpp new file mode 100644 index 000000000..e395c57aa --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_ctor_pass.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value(T const&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + int i = 1; + boost::synchronized_value<int> v(i); + BOOST_TEST(v.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_assign_pass.cpp new file mode 100644 index 000000000..d4e80b0ce --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_assign_pass.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value& operator=(synchronized_value const&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + int i = 1; + boost::synchronized_value<int> v1(i); + boost::synchronized_value<int> v2; + v2 = v1; + BOOST_TEST(v2.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_ctor_pass.cpp new file mode 100644 index 000000000..13fcf6d80 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_ctor_pass.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value(synchronized_value const&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + int i = 1; + boost::synchronized_value<int> v1(i); + boost::synchronized_value<int> v2(v1); + BOOST_TEST(v2.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/default_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/default_ctor_pass.cpp new file mode 100644 index 000000000..7b4095650 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/default_ctor_pass.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value(); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int, boost::mutex > f; + } + { + boost::synchronized_value<int, boost::timed_mutex> f; + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/indirect_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/indirect_pass.cpp new file mode 100644 index 000000000..09b8e89d2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/indirect_pass.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// strict_lock_ptr<T,M> operator->(); +// const_strict_lock_ptr<T,M> operator->() const; + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +struct S { + int f() const {return 1;} + int g() {return 1;} +}; + +int main() +{ + { + boost::synchronized_value<S> v; + BOOST_TEST(v->f()==1); + BOOST_TEST(v->g()==1); + } + { + const boost::synchronized_value<S> v; + BOOST_TEST(v->f()==1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_assign_pass.cpp new file mode 100644 index 000000000..146ed2e51 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_assign_pass.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value& operator=(T &&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v; + v = 1; + BOOST_TEST(v.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_ctor_pass.cpp new file mode 100644 index 000000000..564d57da8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_ctor_pass.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value(T &&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v(1); + BOOST_TEST(v.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_assign_pass.cpp new file mode 100644 index 000000000..818216382 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_assign_pass.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value& operator=(synchronized_value &&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v1(1); + boost::synchronized_value<int> v2; + v2 = boost::move(v1); + BOOST_TEST(v2.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_ctor_pass.cpp new file mode 100644 index 000000000..7250e896f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_ctor_pass.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value(synchronized_value &&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v1(1); + boost::synchronized_value<int> v2(boost::move(v1)); + BOOST_TEST(v2.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_T_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_T_pass.cpp new file mode 100644 index 000000000..801b514d6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_T_pass.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// void swap(synchronized_value&,synchronized_value&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v1(1); + int v2(2); + boost::swap(v1,v2); + BOOST_TEST(v1.value() == 2); + BOOST_TEST(v2 == 1); + } + { + boost::synchronized_value<int> v1(1); + int v2(2); + boost::swap(v2,v1); + BOOST_TEST(v1.value() == 2); + BOOST_TEST(v2 == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_pass.cpp new file mode 100644 index 000000000..c52069ff3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_pass.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// void swap(synchronized_value&,synchronized_value&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v1(1); + boost::synchronized_value<int> v2(2); + swap(v1,v2); + BOOST_TEST(v1.value() == 2); + BOOST_TEST(v2.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/synchronize_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/synchronize_pass.cpp new file mode 100644 index 000000000..af24d79b6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/synchronize_pass.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// strict_lock_ptr<T,M> synchronize(); +// const_strict_lock_ptr<T,M> synchronize() const; + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +struct S { + int f() const {return 1;} + int g() {return 1;} +}; + +int main() +{ + { + boost::synchronized_value<S> v; + boost::strict_lock_ptr<S> ptr = v.synchronize(); + BOOST_TEST(ptr->f()==1); + BOOST_TEST(ptr->g()==1); + } + { + const boost::synchronized_value<S> v; + boost::const_strict_lock_ptr<S> ptr = v.synchronize(); + BOOST_TEST(ptr->f()==1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/assign_fail.cpp new file mode 100644 index 000000000..49188e130 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/assign_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// timed_mutex& operator=(const timed_mutex&) = delete; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::timed_mutex m0; + boost::timed_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/copy_fail.cpp new file mode 100644 index 000000000..ed0a4c955 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/copy_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// timed_mutex(const timed_mutex&) = delete; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::timed_mutex m0; + boost::timed_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/default_pass.cpp new file mode 100644 index 000000000..6b7c6f2b3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// timed_mutex(); + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::timed_mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/lock_pass.cpp new file mode 100644 index 000000000..8d2733e1f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/lock_pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// void lock(); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::timed_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + m.lock(); + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp new file mode 100644 index 000000000..b203e5d91 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// typedef pthread_timed_mutex_t* native_handle_type; +// native_handle_type native_handle(); + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ +#if defined BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE + boost::timed_mutex m; + boost::timed_mutex::native_handle_type h = m.native_handle(); + BOOST_TEST(h); +#else +#error "Test not applicable: BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE not defined for this platform as not supported" +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp new file mode 100644 index 000000000..94d790e0e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(750)) == true); + t1 = Clock::now(); + m.unlock(); +} + +void f2() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(250)) == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp new file mode 100644 index 000000000..96e99e7f7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// bool try_lock(); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + + +boost::timed_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp new file mode 100644 index 000000000..958a42d03 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(750)) == true); + t1 = Clock::now(); + m.unlock(); +} + +void f2() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(250)) == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp new file mode 100644 index 000000000..9ec0dfdfb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp @@ -0,0 +1,145 @@ +// (C) Copyright 2013 Ruslan Baratov +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See www.boost.org/libs/thread for documentation. + +#define BOOST_THREAD_VERSION 4 + +#include <boost/detail/lightweight_test.hpp> // BOOST_TEST + +#include <boost/thread/mutex.hpp> +#include <boost/thread/with_lock_guard.hpp> +#include <boost/bind/bind.hpp> + +class Foo { + public: + Foo(int value): value_(value) { + } + + int func(int a, int b) const { + BOOST_TEST(a == 1); + BOOST_TEST(b == 31); + return a + b + value_; + } + + int func_ref(int& a) const { + a = 133; + return 36; + } + + void func_ref(int& a, int& b, int* c) const { + BOOST_TEST(value_ == 3); + a = 567; + b = 897; + *c = 345; + } + + private: + int value_; +}; + +void test_bind() { + boost::mutex m; + + Foo foo(2); + + int res_bind = boost::with_lock_guard( + m, + boost::bind(&Foo::func, foo, 1, 31) + ); + BOOST_TEST(res_bind == 34); + + int a = 0; + int res_bind_ref = boost::with_lock_guard( + m, + boost::bind(&Foo::func_ref, foo, boost::ref(a)) + ); + BOOST_TEST(res_bind_ref == 36); + BOOST_TEST(a == 133); + + a = 0; + int b = 0; + int c = 0; + Foo boo(3); + boost::with_lock_guard( + m, boost::bind(&Foo::func_ref, boo, boost::ref(a), boost::ref(b), &c) + ); + BOOST_TEST(a == 567); + BOOST_TEST(b == 897); + BOOST_TEST(c == 345); +} + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +void test_bind_non_const() { + std::cout << "c++11 variadic templates disabled" << std::endl; +} +#else + +// calling non-const bind methods supported only with c++11 variadic templates +class Boo { + public: + Boo(int value): value_(value) { + } + + int func(int a, int b) { + BOOST_TEST(a == 7); + BOOST_TEST(b == 3); + return a - b + value_; + } + + int func_ref(int& a) { + a = 598; + return 23; + } + + void func_ref(int& a, int& b, int* c) { + BOOST_TEST(value_ == 67); + a = 111; + b = 222; + *c = 333; + } + + private: + int value_; +}; + +void test_bind_non_const() { + boost::mutex m; + + Boo boo(20); + + int res_bind = boost::with_lock_guard( + m, + boost::bind(&Boo::func, boo, 7, 3) + ); + BOOST_TEST(res_bind == 24); + + int a = 0; + int res_bind_ref = boost::with_lock_guard( + m, + boost::bind(&Boo::func_ref, boo, boost::ref(a)) + ); + BOOST_TEST(res_bind_ref == 23); + BOOST_TEST(a == 598); + + a = 0; + int b = 0; + int c = 0; + Boo foo(67); + boost::with_lock_guard( + m, boost::bind(&Boo::func_ref, foo, boost::ref(a), boost::ref(b), &c) + ); + BOOST_TEST(a == 111); + BOOST_TEST(b == 222); + BOOST_TEST(c == 333); +} +#endif + +int main() { + test_bind(); + test_bind_non_const(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_lambda.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_lambda.cpp new file mode 100644 index 000000000..8eda53dea --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_lambda.cpp @@ -0,0 +1,59 @@ +// (C) Copyright 2013 Ruslan Baratov +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See www.boost.org/libs/thread for documentation. + +#include <boost/config.hpp> + +#if !defined(BOOST_NO_CXX11_DECLTYPE) +# define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/detail/lightweight_test.hpp> // BOOST_TEST + +#include <iostream> // std::cout +#include <boost/thread/mutex.hpp> +#include <boost/thread/with_lock_guard.hpp> + +#if defined(BOOST_NO_CXX11_LAMBDAS) || (defined BOOST_MSVC && _MSC_VER < 1700) +void test_lambda() { + std::cout << "C++11 lambda disabled" << std::endl; +} +#else +void test_lambda() { + boost::mutex m; + int res_1 = boost::with_lock_guard( + m, + [](int a) { + BOOST_TEST(a == 13); + return a + 3; + }, + 13 + ); + BOOST_TEST(res_1 == 16); + + int v = 0; + int res_2 = boost::with_lock_guard( + m, + [&v](int a) { + BOOST_TEST(a == 55); + v = 15; + return 45; + }, + 55 + ); + BOOST_TEST(res_2 == 45); + BOOST_TEST(v == 15); +} +#endif + +int main() { + std::cout << std::boolalpha; + test_lambda(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_move.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_move.cpp new file mode 100644 index 000000000..2c685790d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_move.cpp @@ -0,0 +1,110 @@ +// (C) Copyright 2013 Ruslan Baratov +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See www.boost.org/libs/thread for documentation. + +#define BOOST_THREAD_VERSION 4 + +#include <boost/detail/lightweight_test.hpp> // BOOST_TEST + +#include <boost/thread/mutex.hpp> +#include <boost/thread/with_lock_guard.hpp> + +class Foo { + public: + explicit Foo(int a) : a_(a) { + } + + Foo(BOOST_RV_REF(Foo) foo) : a_(foo.a_) { + BOOST_ASSERT(&foo != this); + foo.a_ = 0; + } + + Foo& operator=(BOOST_RV_REF(Foo) foo) { + BOOST_ASSERT(&foo != this); + a_ = foo.a_; + foo.a_ = 0; + return *this; + } + + int get() const { + return a_; + } + + private: + BOOST_MOVABLE_BUT_NOT_COPYABLE(Foo) + + int a_; +}; + +template <class T1, class T2> +bool func_with_2_arg(BOOST_FWD_REF(T1) arg_1, BOOST_FWD_REF(T2) arg_2) { + BOOST_TEST(arg_1.get() == 3); + BOOST_TEST(arg_2.get() == 767); + return false; +} + +void test_movable() { + boost::mutex m; + + Foo foo_1(3); + Foo foo_2(767); + + bool res = boost::with_lock_guard( + m, &func_with_2_arg<Foo, Foo>, boost::move(foo_1), boost::move(foo_2) + ); + BOOST_TEST(!res); +} + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +void test_real_movable() { + std::cout << "c++11 move emulated" << std::endl; +} +#else +// test real one +class Boo { + public: + Boo(int a) : a_(a) { + } + + Boo(Boo&& boo) : a_(boo.a_) { + BOOST_ASSERT(&boo != this); + boo.a_ = 0; + } + + int get() const { + return a_; + } + + BOOST_DELETED_FUNCTION(Boo(Boo&)) + BOOST_DELETED_FUNCTION(Boo& operator=(Boo&)) + BOOST_DELETED_FUNCTION(Boo& operator=(Boo&&)) + private: + int a_; +}; + +void func_with_3_arg(Boo&& boo_1, Boo&& boo_2, Boo&& boo_3) { + BOOST_TEST(boo_1.get() == 11); + BOOST_TEST(boo_2.get() == 12); + BOOST_TEST(boo_3.get() == 13); +} + +void test_real_movable() { + boost::mutex m; + + Boo boo_3(13); + + boost::with_lock_guard( + m, func_with_3_arg, Boo(11), Boo(12), boost::move(boo_3) + ); +} +#endif + +int main() { + test_movable(); + test_real_movable(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_simple.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_simple.cpp new file mode 100644 index 000000000..dc9c44455 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_simple.cpp @@ -0,0 +1,139 @@ +// (C) Copyright 2013 Ruslan Baratov +// (C) Copyright 2013 Ruslan Baratov +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See www.boost.org/libs/thread for documentation. + +#define BOOST_THREAD_VERSION 4 + +#include <boost/detail/lightweight_test.hpp> // BOOST_TEST + +#include <boost/thread/mutex.hpp> +#include <boost/thread/with_lock_guard.hpp> +#include <boost/ref.hpp> + +void func_with_0_arg() { +} + +void func_with_1_arg(int arg_1) { + BOOST_TEST(arg_1 == 3); +} + +bool func_with_2_arg(int arg_1, bool arg_2) { + BOOST_TEST(arg_1 == 3); + BOOST_TEST(arg_2 == true); + return !arg_2; +} + +int func_with_3_arg(int arg_1, bool arg_2, const char* arg_3) { + BOOST_TEST(arg_1 == 13); + BOOST_TEST(arg_2 == false); + BOOST_TEST(std::string(arg_3) == "message for func with 3 arg"); + return 12; +} + +const char* func_with_4_arg(int arg_1, bool arg_2, int* arg_3, int& arg_4) { + BOOST_TEST(arg_1 == 23); + BOOST_TEST(arg_2 == false); + *arg_3 = 128; + arg_4 = 456; + return "hello"; +} + +void test_simple() { + boost::mutex m; + + // #0 + boost::with_lock_guard(m, func_with_0_arg); + + // #1 + boost::with_lock_guard(m, func_with_1_arg, 3); + + // #2 + bool res2 = boost::with_lock_guard(m, func_with_2_arg, 3, true); + BOOST_TEST(res2 == false); + + // #3 + int arg1 = 13; + const char* mes = "message for func with 3 arg"; + int res3 = boost::with_lock_guard(m, func_with_3_arg, arg1, false, mes); + BOOST_TEST(res3 == 12); + + // #4 + int arg3 = 0; + int arg4 = 0; + const char* res4 = boost::with_lock_guard( + m, + func_with_4_arg, + 23, + false, + &arg3, + boost::ref(arg4) + ); + BOOST_TEST(arg3 == 128); + BOOST_TEST(arg4 == 456); + BOOST_TEST(std::string(res4) == "hello"); +} + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +void test_variadic_templates() { + std::cout << "C++11 variadic templates disabled" << std::endl; +} +#else +int func_with_5_args(int a1, char a2, int& a3, bool* a4, bool a5) { + BOOST_TEST(a1 == 12); + BOOST_TEST(a2 == 'x'); + BOOST_TEST(a5 == false); + a3 = 135; + *a4 = false; + return 45; +} + +int func_with_6_args(int a1, char a2, int& a3, bool* a4, int&& a5, bool a6) { + BOOST_TEST(a1 == 12); + BOOST_TEST(a2 == 'N'); + BOOST_TEST(a5 == 2 || a5 == 13); + BOOST_TEST(a6 == false); + a3 = 200; + *a4 = true; + return 888; +} + +void test_variadic_templates() { + boost::mutex m; + + int a3 = 0; + bool a4 = true; + int res5 = boost::with_lock_guard( + m, func_with_5_args, 12, 'x', a3, &a4, false + ); + BOOST_TEST(a3 == 135); + BOOST_TEST(a4 == false); + BOOST_TEST(res5 == 45); + + int res6 = boost::with_lock_guard( + m, func_with_6_args, 12, 'N', a3, &a4, 2, false + ); + BOOST_TEST(a3 == 200); + BOOST_TEST(a4 == true); + BOOST_TEST(res6 == 888); + + a3 = 0; + a4 = false; + int a5 = 13; + int res6_move = boost::with_lock_guard( + m, func_with_6_args, 12, 'N', a3, &a4, boost::move(a5), false + ); + BOOST_TEST(a3 == 200); + BOOST_TEST(a4 == true); + BOOST_TEST_EQ(res6_move, 888); +} +#endif + +int main() { + test_simple(); + test_variadic_templates(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test.mcp b/src/boost/libs/thread/test/test.mcp Binary files differnew file mode 100644 index 000000000..f27f0b97b --- /dev/null +++ b/src/boost/libs/thread/test/test.mcp diff --git a/src/boost/libs/thread/test/test_10340.cpp b/src/boost/libs/thread/test/test_10340.cpp new file mode 100644 index 000000000..5311e8210 --- /dev/null +++ b/src/boost/libs/thread/test/test_10340.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> + +struct foo +{ + foo(int i_): i(i_) {} + int i; +}; + +int main() +{ + boost::promise<foo> p; + const foo f(42); + p.set_value(f); + + // Clearly a const future ref isn't much use, but I needed to + // prove the problem wasn't me trying to copy a unique_future + + const boost::future<foo>& fut = boost::make_ready_future( foo(42) ); + return 0; +} + diff --git a/src/boost/libs/thread/test/test_10963.cpp b/src/boost/libs/thread/test/test_10963.cpp new file mode 100644 index 000000000..1ec8d6cfc --- /dev/null +++ b/src/boost/libs/thread/test/test_10963.cpp @@ -0,0 +1,61 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread/future.hpp> +#include <boost/static_assert.hpp> +#include <cassert> +#include <boost/thread/executors/basic_thread_pool.hpp> + + +struct TestCallback +{ + typedef boost::future<void> result_type; + + result_type operator()(boost::future<void> future) const + { + assert(future.is_ready()); + future.get(); + return boost::make_ready_future(); + } + + result_type operator()(boost::future<boost::future<void> > future) const + { + assert(future.is_ready()); + future.get(); + return boost::make_ready_future(); + } +}; + +int main() +{ +#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS + { + boost::promise<void> test_promise; + boost::future<void> test_future(test_promise.get_future()); + auto f1 = test_future.then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f2 = f1.then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<boost::future<void> > >::value); + } + { + boost::basic_thread_pool executor; + boost::promise<void> test_promise; + boost::future<void> test_future(test_promise.get_future()); + auto f1 = test_future.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f2 = f1.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<boost::future<void> > >::value); + + } +#endif + return 0; +} diff --git a/src/boost/libs/thread/test/test_10964.cpp b/src/boost/libs/thread/test/test_10964.cpp new file mode 100644 index 000000000..48ee5cd95 --- /dev/null +++ b/src/boost/libs/thread/test/test_10964.cpp @@ -0,0 +1,191 @@ +// Copyright (C) 2015 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread/future.hpp> +#include <boost/static_assert.hpp> +#include <cassert> +#include <iostream> +#include <boost/thread/executors/basic_thread_pool.hpp> + +struct TestCallback +{ + typedef boost::future<void> result_type; + + result_type operator()(boost::future<void> future) const + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + future.wait(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + return boost::make_ready_future(); + } + + result_type operator()(boost::future<boost::future<void> > future) const + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.get().is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + //boost::future<void> ff = future.get(); + + return boost::make_ready_future(); + } + result_type operator()(boost::shared_future<void> future) const + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + future.wait(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + return boost::make_ready_future(); + } + + result_type operator()(boost::shared_future<boost::future<void> > future) const + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.get().is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + //boost::future<void> ff = future.get(); + + return boost::make_ready_future(); + } +}; + +void p1() +{ +} + +int main() +{ + const int number_of_tests = 2; + (void)(number_of_tests); + +#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + f1.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + auto f1 = boost::make_ready_future().then(TestCallback()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + auto f2 = f1.unwrap(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + f2.wait(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + boost::future<void> f2 = f1.get(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f3 = f1.then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f2 = f1.unwrap(); + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value); + auto f3 = f2.then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + boost::make_ready_future().then( + TestCallback()).unwrap().then(TestCallback()).get(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + boost::future<void> f = boost::async(p1); + f.then( + TestCallback()).unwrap().then(TestCallback()).get(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f3 = f1.then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + boost::basic_thread_pool executor; + auto f1 = boost::make_ready_future().then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f3 = f1.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } +#if 1 + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + // fixme + for (int i=0; i< number_of_tests; i++) + { + boost::basic_thread_pool executor(2); + + auto f1 = boost::make_ready_future().then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + std::cout << __FILE__ << "[" << __LINE__ << "] " << int(f1.valid()) << std::endl; + auto f2 = f1.unwrap(); + std::cout << __FILE__ << "[" << __LINE__ << "] " << int(f2.valid()) << std::endl; + + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value); + auto f3 = f2.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + boost::basic_thread_pool executor; + + auto f1 = boost::make_ready_future().then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f2 = f1.unwrap(); + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value); + auto f3 = f2.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + +#endif + return 0; +} diff --git a/src/boost/libs/thread/test/test_11053.cpp b/src/boost/libs/thread/test/test_11053.cpp new file mode 100644 index 000000000..a8b6dfa97 --- /dev/null +++ b/src/boost/libs/thread/test/test_11053.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2015 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 +#include <boost/thread.hpp> +#include <boost/thread/tss.hpp> +#include <boost/shared_ptr.hpp> +#include <iostream> + +struct A +{ + void DoWork() + { + std::cout << "A: doing work\n"; + if (!m_ptr.get()) + m_ptr.reset(new WorkSpace()); + // do not very much + for (size_t i = 0; i < 10; ++i) + m_ptr->a += 10; + } + +private: + struct WorkSpace + { + int a; + WorkSpace() : a(0) {} + }; + boost::thread_specific_ptr<WorkSpace> m_ptr; +}; + +struct B +{ + void DoWork() + { + std::cout << "B: doing work\n"; + if (!m_ptr.get()) + m_ptr.reset(new A()); + m_ptr->DoWork(); + } +private: + boost::thread_specific_ptr<A> m_ptr; +}; + +struct C +{ + void DoWork() + { + std::cout << "C: doing work\n"; + if (!m_ptr.get()) + m_ptr.reset(new B()); + m_ptr->DoWork(); + } +private: + boost::thread_specific_ptr<B> m_ptr; +}; + +int main(int ac, char** av) +{ + std::cout << "test starting\n"; + boost::shared_ptr<C> p_C(new C); + boost::thread cWorker(&C::DoWork, p_C); + cWorker.join(); + std::cout << "test stopping\n"; + return 0; +} + + + diff --git a/src/boost/libs/thread/test/test_11256.cpp b/src/boost/libs/thread/test/test_11256.cpp new file mode 100644 index 000000000..13002f867 --- /dev/null +++ b/src/boost/libs/thread/test/test_11256.cpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread.hpp> +#include <boost/thread/thread_pool.hpp> +#include <cassert> + +auto createFuture() +{ + boost::promise<void> promise; + promise.set_value(); + return promise.get_future(); +} + +auto stepOne(boost::basic_thread_pool &executor) +{ + auto sendFuture = createFuture(); + auto wrappedFuture = sendFuture.then(executor, [](auto f) mutable { + return createFuture(); + }); + + return wrappedFuture.unwrap(); +} + +auto stepTwo(boost::basic_thread_pool &executor) +{ + auto future = stepOne(executor); + return future.then(executor, [](auto f) { + assert(f.is_ready()); + }); +} + +int main() +{ + boost::basic_thread_pool executor{1}; + stepTwo(executor).get(); +} diff --git a/src/boost/libs/thread/test/test_11266.cpp b/src/boost/libs/thread/test/test_11266.cpp new file mode 100644 index 000000000..0f736783a --- /dev/null +++ b/src/boost/libs/thread/test/test_11266.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2015 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> + +void func(int) { } + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + boost::packaged_task<void(int)> task{func}; + } + { + boost::packaged_task<void(int)> task{func}; + + task(0); + } + { + boost::packaged_task<void(int)> task{func}; + int x = 0; + task(x); + } +#endif +} diff --git a/src/boost/libs/thread/test/test_11499.cpp b/src/boost/libs/thread/test/test_11499.cpp new file mode 100644 index 000000000..2fe07ae88 --- /dev/null +++ b/src/boost/libs/thread/test/test_11499.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/shared_mutex.hpp> +#include <thread> +#include <mutex> +#include <shared_mutex> +#include <atomic> +#include <vector> + +using MutexT = boost::shared_mutex; +using ReaderLockT = std::lock_guard<MutexT>; +using WriterLockT = std::shared_lock<MutexT>; + +MutexT gMutex; +std::atomic<bool> running(true); + + +void myread() +{ + long reads = 0; + while (running && reads < 100000) + { + ReaderLockT lock(gMutex); + std::this_thread::yield(); + ++reads; + } +} + +int main() +{ + using namespace std; + + vector<thread> threads; + for (int i = 0; i < 256; ++i) + { + threads.emplace_back(thread(myread)); + } + +// string str; +// +// getline(std::cin, str); + running = false; + + for (auto& thread : threads) + { + thread.join(); + } + + return 0; +} + diff --git a/src/boost/libs/thread/test/test_11611.cpp b/src/boost/libs/thread/test/test_11611.cpp new file mode 100644 index 000000000..0a38b4b27 --- /dev/null +++ b/src/boost/libs/thread/test/test_11611.cpp @@ -0,0 +1,66 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 + +#include <iostream> + +#define BOOST_THREAD_PROVIDES_FUTURE +#define BOOST_THREAD_PROVIDES_EXECUTORS +#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +#if __cplusplus >= 201103L +#include <boost/thread/executors/loop_executor.hpp> +#include <boost/thread/executors/serial_executor.hpp> +#endif +#include <boost/thread/thread.hpp> +#include <boost/atomic.hpp> + +using namespace std; + +int main() +{ +#if __cplusplus >= 201103L + static std::size_t const nWorks = 100000; + boost::atomic<unsigned> execCount(0u); + boost::loop_executor ex; + + boost::thread t([&ex]() + { + ex.loop(); + }); + + { + boost::serial_executor serial(ex); + + for (size_t i = 0; i < nWorks; i++) + serial.submit([i, &execCount] { + //std::cout << i << "."; + ++execCount; + }); + + serial.close(); + } + unsigned const cnt = execCount.load(); + if (cnt != nWorks) { + // Since the serial_executor is closed, all work should have been done, + // even though the loop_executor ex is not. + std::cerr << "Only " << cnt << " of " << nWorks << " works executed!\n"; + return 1; + } + + if (ex.try_executing_one()) { + std::cerr + << "loop_executor::try_executing_one suceeded on closed executor!\n"; + return 1; + } + + ex.close(); + + t.join(); + std::cout << "end\n" << std::endl; +#endif + return 0; +} diff --git a/src/boost/libs/thread/test/test_11796.cpp b/src/boost/libs/thread/test/test_11796.cpp new file mode 100644 index 000000000..6aab1af79 --- /dev/null +++ b/src/boost/libs/thread/test/test_11796.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2015 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread.hpp> +#include <boost/chrono.hpp> +#include <iostream> + +boost::thread th; +int main() +{ + + for (auto ti = 0; ti < 1000; ti++) + { + th = boost::thread([ti]() + { + boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); + std::cout << ti << std::endl; + }); + } + std::string st; + + std::cin >> st; + +// for (int i = 0; i < 10; ++i) { +// std::cout << "." << i << std::endl; +// boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); +// } + th.join(); + return 0; +} + diff --git a/src/boost/libs/thread/test/test_11818.cpp b/src/boost/libs/thread/test/test_11818.cpp new file mode 100644 index 000000000..0d2b381de --- /dev/null +++ b/src/boost/libs/thread/test/test_11818.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <thread> + +int main() +{ + + { + boost::promise<int> promise; + boost::future<int> future = promise.get_future(); + + boost::future<int> result = + future.then + ( + boost::launch::deferred, + [](boost::future<int> && f) + { + std::cout << std::this_thread::get_id() << ": callback" << std::endl; + std::cout << "The value is: " << f.get() << std::endl; + return f.get(); + } + ); + + // We could not reach here. + std::cout << std::this_thread::get_id() << ": function" << std::endl; + + promise.set_value(0); + } + + { + boost::promise<int> promise; + boost::shared_future<int> future = promise.get_future().share(); + + boost::future<int> result = + future.then + ( + boost::launch::deferred, + [](boost::shared_future<int> && f) + { + std::cout << std::this_thread::get_id() << ": callback" << std::endl; + std::cout << "The value is: " << f.get() << std::endl; + return f.get(); + } + ); + + // We could not reach here. + std::cout << std::this_thread::get_id() << ": function" << std::endl; + + promise.set_value(0); + } + + return 0; +} diff --git a/src/boost/libs/thread/test/test_12293.cpp b/src/boost/libs/thread/test/test_12293.cpp new file mode 100644 index 000000000..0b305edc6 --- /dev/null +++ b/src/boost/libs/thread/test/test_12293.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 + +// BoostFutureTest.cpp : Defines the entry point for the console application. +// + +#include <iostream> + +// boost version 1.60.0 +// has the following set. +#define BOOST_THREAD_VERSION 4 +// #define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread/future.hpp> + + +int main() +{ +#if __cplusplus >= 201103L + + int value = 0; + int tmpValue = 0; + boost::promise<void> promise1; + boost::promise<void> promise2; + + auto future1 = promise1.get_future(); + + auto waitFuture = future1.then([&tmpValue, &promise2](boost::future<void> future){ + assert(future.is_ready()); // this works correctly and is ready. + + auto fut = boost::async(boost::launch::async, [&promise2, &tmpValue](){ + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + tmpValue = 1; + promise2.set_value(); + std::cout << "Step 2 "<< std::endl; // should print 1 but prints 0 + }); + std::cout << "Step 1 "<< std::endl; // should print 1 but prints 0 + + return promise2.get_future(); + //return ; + }).then([&value, &tmpValue](boost::future<boost::future<void>> future){ + //}).then([&value, &tmpValue](boost::future<void> future){ + // error: no matching function for call to ‘boost::future<boost::future<void> >::then(main()::<lambda(boost::future<void>)>)’ + // as expected + + assert(future.is_ready()); // this doesn't work correctly and is not ready. + + + value = tmpValue; + }); + + + promise1.set_value(); + waitFuture.wait(); + + std::cout << "value = " << value << std::endl; // should print 1 but prints 0 +#endif + return 0; +} + diff --git a/src/boost/libs/thread/test/test_12949.cpp b/src/boost/libs/thread/test/test_12949.cpp new file mode 100644 index 000000000..2b6235238 --- /dev/null +++ b/src/boost/libs/thread/test/test_12949.cpp @@ -0,0 +1,20 @@ +// Copyright (C) 2017 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 + +//#include <boost/thread/thread.hpp> +#include <boost/thread/condition_variable.hpp> + +void f() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(10)); // ** +} +int main() +{ + + return 0; +} + diff --git a/src/boost/libs/thread/test/test_13480b.cpp b/src/boost/libs/thread/test/test_13480b.cpp new file mode 100644 index 000000000..3f89145d8 --- /dev/null +++ b/src/boost/libs/thread/test/test_13480b.cpp @@ -0,0 +1,77 @@ +// comment if you want to see the boost::move issue +#define BOOST_THREAD_VERSION 3 + +#include <boost/type_traits/is_same.hpp> +#include <boost/variant/detail/apply_visitor_binary.hpp> +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/variant.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> + +#define WANT_BUILD_TO_FAIL +#ifdef WANT_BUILD_TO_FAIL +#include <boost/thread.hpp> +#endif + +class AType +{ + +}; + +class BType +{ +}; + +typedef boost::shared_ptr<AType> IATypePtr; +typedef boost::shared_ptr<BType> IBTypePtr; + +typedef boost::variant<IATypePtr, IBTypePtr> ABVar; + +struct ServiceTimeTableEvent +{ +public: + + ServiceTimeTableEvent(ABVar abType) + : m_abType{ abType } + {} + + inline ABVar const& GetABType() const { return m_abType; } + inline ABVar & GetABType() { return m_abType; } + +private: + ABVar m_abType; +}; + +class ab_are_equals + : public boost::static_visitor<bool> +{ +public: + template<typename T, typename U> + bool operator()(T, U) const + { + return false; // cannot compare different types + } + template<typename T> + bool operator()(T lhs, T rhs) const + { + return lhs == rhs; + } +}; + +int main(int argc, char* argv[]) +{ + + auto aTypePtr = IATypePtr{ new AType }; + auto bTypePtr = IBTypePtr{ new BType }; + + ABVar aType = aTypePtr; + ABVar bType = bTypePtr; + + ServiceTimeTableEvent timeTableEvent1{ aType }; + ServiceTimeTableEvent timeTableEvent2{ bType }; + + auto xx = boost::apply_visitor(ab_are_equals(), timeTableEvent1.GetABType(), timeTableEvent2.GetABType()); + xx = boost::apply_visitor(ab_are_equals(), timeTableEvent1.GetABType(), timeTableEvent1.GetABType());; + xx = boost::apply_visitor(ab_are_equals(), timeTableEvent2.GetABType(), timeTableEvent2.GetABType());; +} + + diff --git a/src/boost/libs/thread/test/test_13561.cpp b/src/boost/libs/thread/test/test_13561.cpp new file mode 100644 index 000000000..b72f593d6 --- /dev/null +++ b/src/boost/libs/thread/test/test_13561.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2018 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/detail/nullary_function.hpp> +#include <boost/system/detail/error_code.ipp> + +int main(int argc, char* argv[]) +{ + boost::detail::nullary_function<void ()> f1; + auto f2 = f1; +} + + diff --git a/src/boost/libs/thread/test/test_2309.cpp b/src/boost/libs/thread/test/test_2309.cpp new file mode 100644 index 000000000..c3208f97f --- /dev/null +++ b/src/boost/libs/thread/test/test_2309.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +//#define BOOST_TEST_MODULE Boost.Threads: 2309 +//#include <boost/test/unit_test.hpp> + +#include <iostream> + +#include <boost/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + + using namespace std; + + boost::mutex mutex_; + + void perform() + { + try + { + boost::this_thread::sleep(boost::posix_time::seconds(100)); + } + catch (boost::thread_interrupted& interrupt) + { + boost::unique_lock<boost::mutex> lock(mutex_); + cerr << "Thread " << boost::this_thread::get_id() << " got interrupted" << endl; + throw(interrupt); + } + catch (std::exception& e) + { + boost::unique_lock<boost::mutex> lock(mutex_); + cerr << "Thread " << boost::this_thread::get_id() << " caught std::exception" << e.what() << endl; + } + catch (...) + { + boost::unique_lock<boost::mutex> lock(mutex_); + cerr << "Thread " << boost::this_thread::get_id() << " caught something else" << endl; + } + } + + void ticket_2309_test() + { + try + { + boost::thread_group threads; + + for (int i = 0; i < 2; ++i) + { + threads.create_thread(perform); + } + + //boost::this_thread::sleep(1); + threads.interrupt_all(); + threads.join_all(); + } + catch (...) + { + BOOST_TEST(false && "exception raised"); + } + } + + int main() + { + + ticket_2309_test(); + } + diff --git a/src/boost/libs/thread/test/test_2501.cpp b/src/boost/libs/thread/test/test_2501.cpp new file mode 100644 index 000000000..c654e7272 --- /dev/null +++ b/src/boost/libs/thread/test/test_2501.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/locks.hpp> + +int main() { + + boost::shared_mutex mtx; boost::upgrade_lock<boost::shared_mutex> lk(mtx); + + boost::upgrade_to_unique_lock<boost::shared_mutex> lk2(lk); + + return 0; +} diff --git a/src/boost/libs/thread/test/test_2741.cpp b/src/boost/libs/thread/test/test_2741.cpp new file mode 100644 index 000000000..349d7d2ae --- /dev/null +++ b/src/boost/libs/thread/test/test_2741.cpp @@ -0,0 +1,79 @@ +// Copyright (C) 2008 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: thread attributes test suite +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> +#include <boost/bind/bind.hpp> +#include <boost/ref.hpp> +#include <boost/utility.hpp> + +#include <iostream> +#include <boost/test/unit_test.hpp> + +#define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only +#include "./util.inl" + +int test_value; +#ifdef PTHREAD_STACK_MIN +#define MY_PTHREAD_STACK PTHREAD_STACK_MIN +#else +#define MY_PTHREAD_STACK 4*0x4000 +#endif +void simple_thread() +{ + test_value = 999; +} + +BOOST_AUTO_TEST_CASE(test_native_handle) +{ + + boost::thread_attributes attrs; + + boost::thread_attributes::native_handle_type* h = attrs.native_handle(); + (void)(h); // unused +#if defined(BOOST_THREAD_PLATFORM_WIN32) + // ... window version +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) + + int k = pthread_attr_setstacksize(h, MY_PTHREAD_STACK); + std::cout << k << std::endl; + BOOST_CHECK(!pthread_attr_setstacksize(h, MY_PTHREAD_STACK)); + std::size_t res; + BOOST_CHECK(!pthread_attr_getstacksize(h, &res)); + BOOST_CHECK(res >= (MY_PTHREAD_STACK)); +#else +#error "Boost thread unavailable on this platform" +#endif + +} + +BOOST_AUTO_TEST_CASE(test_stack_size) +{ + boost::thread_attributes attrs; + + attrs.set_stack_size(0x4000); + BOOST_CHECK(attrs.get_stack_size() >= 0x4000); + +} + +void do_test_creation_with_attrs() +{ + test_value = 0; + boost::thread_attributes attrs; + attrs.set_stack_size(0x4000); + boost::thread thrd(attrs, &simple_thread); + thrd.join(); + BOOST_CHECK_EQUAL(test_value, 999); +} + +BOOST_AUTO_TEST_CASE(test_creation_with_attrs) +{ + timed_test(&do_test_creation_with_attrs, 1); +} + + diff --git a/src/boost/libs/thread/test/test_3628.cpp b/src/boost/libs/thread/test/test_3628.cpp new file mode 100644 index 000000000..02914d810 --- /dev/null +++ b/src/boost/libs/thread/test/test_3628.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#include <boost/thread/thread.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/recursive_mutex.hpp> +#include <list> +#include <iostream> + +#if defined BOOST_THREAD_USES_CHRONO + +using namespace std; + +boost::recursive_mutex theMutex; + +typedef std::list<boost::condition*> Conditions; +Conditions theConditions; + +void ThreadFuncWaiter() +{ + boost::condition con1; + //for(; ; ) + for (int j = 0; j < 10; j++) + { + { + boost::unique_lock<boost::recursive_mutex> lockMtx(theMutex); + theConditions.push_back(&con1); + + cout << "Added " << boost::this_thread::get_id() << " " << &con1 << endl; + if (con1.timed_wait(lockMtx, boost::posix_time::time_duration(0, 0, 50))) + { + cout << "Woke Up " << boost::this_thread::get_id() << " " << &con1 << endl; + } + else + { + cout << "*****Timed Out " << boost::this_thread::get_id() << " " << &con1 << endl; + exit(13); + } + + theConditions.remove(&con1); + cout << "Removed " << boost::this_thread::get_id() << " " << &con1 << endl; + cout << "Waiter " << j << endl; + + } + //Sleep(2000); + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + } +} + +void ThreadFuncNotifier() +{ + for (int j = 0; j < 70; j++) + { + { + boost::unique_lock<boost::recursive_mutex> lockMtx(theMutex); + cout << "<Notifier " << j << endl; + + unsigned int i = 0; + for (Conditions::iterator it = theConditions.begin(); it != theConditions.end() && i < 2; ++it) + { + (*it)->notify_one(); + //WORKAROUND_ lockMtx.unlock(); + //WORKAROUND_ boost::this_thread::sleep_for(boost::chrono::milliseconds(50)); + cout << "Notified One " << theConditions.size() << " " << (*it) << endl; + ++i; + //WORKAROUND_ lockMtx.lock(); + } + + cout << "Notifier> " << j << endl; + } + boost::this_thread::sleep_for(boost::chrono::milliseconds(50)); + } +} + +int main() +{ + boost::thread_group tg; + for (int i = 0; i < 12; ++i) + { + tg.create_thread(ThreadFuncWaiter); + } + + tg.create_thread(ThreadFuncNotifier); + + tg.join_all(); + + return 0; +} + + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/test_3837.cpp b/src/boost/libs/thread/test/test_3837.cpp new file mode 100644 index 000000000..fd0056f33 --- /dev/null +++ b/src/boost/libs/thread/test/test_3837.cpp @@ -0,0 +1,73 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> +#include <boost/thread.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/optional.hpp> +#include <boost/detail/lightweight_test.hpp> + +using namespace boost; +using namespace boost::chrono; + +struct dummy_class_tracks_deletions +{ + static unsigned deletions; + + dummy_class_tracks_deletions() + { + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + } + ~dummy_class_tracks_deletions() + { + ++deletions; + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + } + +}; +unsigned dummy_class_tracks_deletions::deletions=0; + + +optional<thread_specific_ptr<dummy_class_tracks_deletions> > optr; +//struct X +//{ +// thread_specific_ptr<int> f; +//} sptr; + +void other_thread() +{ + + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + optr = none; + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + optr = in_place(); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + BOOST_TEST(optr->get() == 0); + this_thread::sleep(posix_time::seconds(5)); + BOOST_TEST(optr->get() == 0); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + +} + +int main() +{ + + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + dummy_class_tracks_deletions * pi = new dummy_class_tracks_deletions; + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + optr = in_place(); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + optr->reset(pi); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + BOOST_TEST(optr->get() == pi); + thread t1(bind(&other_thread)); + this_thread::sleep(posix_time::seconds(5)); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + BOOST_TEST(optr->get() == pi); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + t1.join(); + return boost::report_errors(); + +} diff --git a/src/boost/libs/thread/test/test_4521.cpp b/src/boost/libs/thread/test/test_4521.cpp new file mode 100644 index 000000000..2b1a21bf2 --- /dev/null +++ b/src/boost/libs/thread/test/test_4521.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/future.hpp> + +int calculate_the_answer_to_life_the_universe_and_everything() +{ + return 42; +} + +int main() { +boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything); + +//boost::unique_future<int> fi = BOOST_THREAD_MAKE_RV_REF(pt.get_future()); +boost::unique_future<int> fi((BOOST_THREAD_MAKE_RV_REF(pt.get_future()))); + +boost::thread task(boost::move(pt)); // launch task on a thread + +fi.wait(); // wait for it to finish + +//assert(fi.is_ready()); +//assert(fi.has_value()); +//assert(!fi.has_exception()); +//assert(fi.get_state()==boost::future_state::ready); +//assert(fi.get()==42); +} diff --git a/src/boost/libs/thread/test/test_4648.cpp b/src/boost/libs/thread/test/test_4648.cpp new file mode 100644 index 000000000..34fb131af --- /dev/null +++ b/src/boost/libs/thread/test/test_4648.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> +#include <boost/thread.hpp> +#include <boost/current_function.hpp> + +class boostThreadLocksTest +{ +public: + boost::shared_mutex myMutex; + //boost::upgrade_lock<boost::shared_mutex> myLock; + static int firstFunction(boostThreadLocksTest *pBoostThreadLocksTest); + static int secondFunction(boostThreadLocksTest *pBoostThreadLocksTest, + boost::upgrade_lock<boost::shared_mutex>& upgr); + boostThreadLocksTest() + :myMutex() + //, myLock(myMutex,boost::defer_lock_t()) + {} +}; + +int boostThreadLocksTest::firstFunction(boostThreadLocksTest *pBoostThreadLocksTest) +{ + std::cout<<"Entering "<<boost::this_thread::get_id()<<" "<<"firstFunction"<<std::endl; + boost::upgrade_lock<boost::shared_mutex> myLock(pBoostThreadLocksTest->myMutex); + pBoostThreadLocksTest->secondFunction(pBoostThreadLocksTest, myLock); + std::cout<<"Returned From Call "<<boost::this_thread::get_id()<<" "<<"firstFunction"<<std::endl; + std::cout<<"Returning from "<<boost::this_thread::get_id()<<" "<<"firstFunction"<<std::endl; + return(0); +} +int boostThreadLocksTest::secondFunction(boostThreadLocksTest *, boost::upgrade_lock<boost::shared_mutex>& upgr) { + std::cout<<"Before Exclusive Locking "<<boost::this_thread::get_id()<<" "<<"secondFunction"<<std::endl; + boost::upgrade_to_unique_lock<boost::shared_mutex> localUniqueLock(upgr); + std::cout<<"After Exclusive Locking "<<boost::this_thread::get_id()<<" "<<"secondFunction"<<std::endl; + return(0); +} +int main() { + boostThreadLocksTest myObject; + boost::thread_group myThreadGroup; + myThreadGroup.create_thread(boost::bind(boostThreadLocksTest::firstFunction,&myObject)); + myThreadGroup.create_thread(boost::bind(boostThreadLocksTest::firstFunction,&myObject)); + myThreadGroup.create_thread(boost::bind(boostThreadLocksTest::firstFunction,&myObject)); + myThreadGroup.join_all(); + return 0; +} diff --git a/src/boost/libs/thread/test/test_4882.cpp b/src/boost/libs/thread/test/test_4882.cpp new file mode 100644 index 000000000..b1bb72539 --- /dev/null +++ b/src/boost/libs/thread/test/test_4882.cpp @@ -0,0 +1,78 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +//#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +//#define BOOST_THREAD_USES_LOG + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/no_exceptions_support.hpp> +//#include <boost/thread/detail/log.hpp> + +boost::shared_mutex mutex; + +void thread() +{ + //BOOST_THREAD_LOG << "<thrd" << BOOST_THREAD_END_LOG; + BOOST_TRY + { + for (int i =0; i<10; ++i) + { +#ifndef BOOST_THREAD_USES_CHRONO + boost::system_time timeout = boost::get_system_time() + boost::posix_time::milliseconds(50); + + if (mutex.timed_lock(timeout)) + { + //BOOST_THREAD_LOG << "<thrd" << " i="<<i << BOOST_THREAD_END_LOG; + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + mutex.unlock(); + //BOOST_THREAD_LOG << "<thrd" << " i="<<i << BOOST_THREAD_END_LOG; + } +#else + boost::chrono::system_clock::time_point timeout = boost::chrono::system_clock::now() + boost::chrono::milliseconds(50); + + //BOOST_THREAD_LOG << "<thrd" << " i="<<i << BOOST_THREAD_END_LOG; + if (mutex.try_lock_until(timeout)) + { + //BOOST_THREAD_LOG << "<thrd" << " i="<<i << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::milliseconds(10)); + mutex.unlock(); + //BOOST_THREAD_LOG << "<thrd" << " i="<<i << BOOST_THREAD_END_LOG; + } +#endif + } + } + BOOST_CATCH (boost::lock_error& ) + { + //BOOST_THREAD_LOG << "lock_error exception thrd>" << BOOST_THREAD_END_LOG; + } + BOOST_CATCH (...) + { + //BOOST_THREAD_LOG << "exception thrd>" << BOOST_THREAD_END_LOG; + } + BOOST_CATCH_END + //BOOST_THREAD_LOG << "thrd>" << BOOST_THREAD_END_LOG; +} + +int main() +{ + //BOOST_THREAD_LOG << "<main" << BOOST_THREAD_END_LOG; + const int nrThreads = 20; + boost::thread* threads[nrThreads]; + + for (int i = 0; i < nrThreads; ++i) + threads[i] = new boost::thread(&thread); + + for (int i = 0; i < nrThreads; ++i) + { + threads[i]->join(); + //BOOST_THREAD_LOG << "main" << BOOST_THREAD_END_LOG; + delete threads[i]; + //BOOST_THREAD_LOG << "main" << BOOST_THREAD_END_LOG; + } + //BOOST_THREAD_LOG << "main>" << BOOST_THREAD_END_LOG; + return 0; +} diff --git a/src/boost/libs/thread/test/test_5351.cpp b/src/boost/libs/thread/test/test_5351.cpp new file mode 100644 index 000000000..958afb31d --- /dev/null +++ b/src/boost/libs/thread/test/test_5351.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <iostream> +#include <boost/thread/thread_only.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/thread/future.hpp> + +using namespace boost::posix_time; +using namespace boost; + +int foo() +{ + this_thread::sleep(seconds(10)); + return 0; +} + + +int main() +{ + boost::packaged_task<int> pt(&foo); + boost::unique_future<int> fi = pt.get_future(); + boost::thread task(boost::move(pt)); // launch task on a thread + + task.interrupt(); + + try + { + int v = fi.get(); + } + catch (boost::thread_interrupted& exc) + { + std::cout << "OK: " << std::endl; + return 0; + } + catch (boost::exception& exc) + { + std::cout << __LINE__ << " ERROR: " << boost::diagnostic_information(exc) << std::endl; + return 1; + } + catch (...) + { + std::cout << __LINE__ << " ERROR: " << std::endl; + return 2; + } + std::cout << __LINE__ << " ERROR: " << std::endl; + return 3; +} diff --git a/src/boost/libs/thread/test/test_5502.cpp b/src/boost/libs/thread/test/test_5502.cpp new file mode 100644 index 000000000..455e79eec --- /dev/null +++ b/src/boost/libs/thread/test/test_5502.cpp @@ -0,0 +1,93 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// bm.cpp + +// g++ test.cpp -lboost_thread-mt && ./a.out + +// the ration of XXX and YYY determines +// if this works or deadlocks +int XXX = 20; +int YYY = 10; + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/shared_mutex.hpp> + +//#include <unistd.h> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +using namespace std; + +//void sleepmillis(useconds_t miliis) +void sleepmillis(int miliis) +{ + //usleep(miliis * 1000); + boost::this_thread::sleep(boost::posix_time::milliseconds(miliis)); +} + +void worker1(boost::shared_mutex * lk, int * x) +{ + (*x)++; // 1 + cout << "lock b try " << *x << endl; + while (1) + { + if (lk->timed_lock(boost::posix_time::milliseconds(XXX))) break; + sleepmillis(YYY); + } + cout << "lock b got " << *x << endl; + (*x)++; // 2 + lk->unlock(); +} + +void worker2(boost::shared_mutex * lk, int * x) +{ + cout << "lock c try" << endl; + lk->lock_shared(); + (*x)++; + cout << "lock c got" << endl; + lk->unlock_shared(); + cout << "lock c unlocked" << endl; + (*x)++; +} + +int main() +{ + + // create + boost::shared_mutex* lk = new boost::shared_mutex(); + + // read lock + cout << "lock a" << endl; + lk->lock_shared(); + + int x1 = 0; + boost::thread t1(boost::bind(worker1, lk, &x1)); + while (!x1) + ; + BOOST_TEST(x1 == 1); + sleepmillis(500); + BOOST_TEST(x1 == 1); + + int x2 = 0; + boost::thread t2(boost::bind(worker2, lk, &x2)); + t2.join(); + BOOST_TEST(x2 == 2); + + lk->unlock_shared(); + cout << "unlock a" << endl; + + for (int i = 0; i < 2000; i++) + { + if (x1 == 2) break; + sleepmillis(10); + } + + BOOST_TEST(x1 == 2); + t1.join(); + delete lk; + + return 0; +} diff --git a/src/boost/libs/thread/test/test_5542_1.cpp b/src/boost/libs/thread/test/test_5542_1.cpp new file mode 100644 index 000000000..4d088dc80 --- /dev/null +++ b/src/boost/libs/thread/test/test_5542_1.cpp @@ -0,0 +1,69 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#include <iostream> +#include <boost/thread/thread_only.hpp> + +class Worker +{ +public: + + Worker() + { + // the thread is not-a-thread until we call start() + } + + void start(int N) + { +// std::cout << "start\n"; + m_Thread = boost::thread(&Worker::processQueue, this, N); +// std::cout << "started\n"; + } + + void join() + { + m_Thread.join(); + } + + void processQueue(unsigned N) + { + unsigned ms = N * 1000; + boost::posix_time::milliseconds workTime(ms); + +// std::cout << "Worker: started, will work for " +// << ms << "ms" +// << std::endl; + + // We're busy, honest! + boost::this_thread::sleep(workTime); + +// std::cout << "Worker: completed" << std::endl; + } + +private: + + boost::thread m_Thread; +}; + +int main() +{ +// std::cout << "main: startup" << std::endl; + + Worker worker; + +// std::cout << "main: create worker" << std::endl; + + worker.start(3); + +// std::cout << "main: waiting for thread" << std::endl; + + worker.join(); + +// std::cout << "main: done" << std::endl; + + return 0; +} diff --git a/src/boost/libs/thread/test/test_5542_2.cpp b/src/boost/libs/thread/test/test_5542_2.cpp new file mode 100644 index 000000000..b0c48cf9d --- /dev/null +++ b/src/boost/libs/thread/test/test_5542_2.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#include <boost/thread/thread_only.hpp> + +void run_thread() { + return; +} + +int main() { + boost::thread t(&run_thread); + return 0; +} + diff --git a/src/boost/libs/thread/test/test_5542_3.cpp b/src/boost/libs/thread/test/test_5542_3.cpp new file mode 100644 index 000000000..4541243f3 --- /dev/null +++ b/src/boost/libs/thread/test/test_5542_3.cpp @@ -0,0 +1,37 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#include <iostream> +#include <boost/thread/thread_only.hpp> +#include <boost/date_time.hpp> + +void workerFunc() +{ + boost::posix_time::seconds workTime(3); + + std::cout << "Worker: running" << std::endl; + + // Pretend to do something useful... + boost::this_thread::sleep(workTime); + + std::cout << "Worker: finished" << std::endl; +} + +int main() +{ + std::cout << "main: startup" << std::endl; + + boost::thread workerThread(workerFunc); + + std::cout << "main: waiting for thread" << std::endl; + + workerThread.join(); + + std::cout << "main: done" << std::endl; + + return 0; +} diff --git a/src/boost/libs/thread/test/test_5891.cpp b/src/boost/libs/thread/test/test_5891.cpp new file mode 100644 index 000000000..bb1af3d57 --- /dev/null +++ b/src/boost/libs/thread/test/test_5891.cpp @@ -0,0 +1,35 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#include <iostream> +#include <boost/thread/thread_only.hpp> + +using namespace std; +using namespace boost; + + struct X { + void operator()() + { + boost::this_thread::sleep(posix_time::seconds(2)); + } + }; +int main() +{ + X run; + boost::thread myThread(run); + boost::this_thread::yield(); + if(myThread.timed_join(posix_time::seconds(5))) + { + cout << "thats ok"; + return 0; + } + else + { + cout << "too late"; + return 1; + } +} diff --git a/src/boost/libs/thread/test/test_6130.cpp b/src/boost/libs/thread/test/test_6130.cpp new file mode 100644 index 000000000..a351039bf --- /dev/null +++ b/src/boost/libs/thread/test/test_6130.cpp @@ -0,0 +1,49 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#include <boost/thread/thread_only.hpp> +#include <boost/date_time/posix_time/posix_time_io.hpp> +#include <assert.h> +#include <iostream> +#include <stdlib.h> +#if defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include <unistd.h> +#endif + +boost::mutex mtx; +boost::condition_variable cv; + +using namespace boost::posix_time; +using namespace boost::gregorian; +int main() +{ +#if defined(BOOST_THREAD_PLATFORM_PTHREAD) + + for (int i=0; i<3; ++i) + { + const time_t now_time = ::time(0); + const time_t wait_time = now_time+1; + time_t end_time; + assert(now_time < wait_time); + + boost::unique_lock<boost::mutex> lk(mtx); + //const bool res = + (void)cv.timed_wait(lk, from_time_t(wait_time)); + end_time = ::time(0); + std::cerr << "now_time =" << now_time << " \n"; + std::cerr << "end_time =" << end_time << " \n"; + std::cerr << "wait_time=" << wait_time << " \n"; + std::cerr << "now_time =" << from_time_t(now_time) << " \n"; + std::cerr << "end_time =" << from_time_t(end_time) << " \n"; + std::cerr << "wait_time=" << from_time_t(wait_time) << " \n"; + std::cerr << end_time - wait_time << " \n"; + assert(end_time >= wait_time); + std::cerr << " OK\n"; + } +#endif + return 0; +} diff --git a/src/boost/libs/thread/test/test_6170.cpp b/src/boost/libs/thread/test/test_6170.cpp new file mode 100644 index 000000000..5ddb21e61 --- /dev/null +++ b/src/boost/libs/thread/test/test_6170.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/locks.hpp> + +// Including this will cause ambiguous errors in boost::move +#include <boost/unordered_map.hpp> + +using namespace boost; + +typedef upgrade_lock<shared_mutex> auto_upgrade_lock; +typedef upgrade_to_unique_lock<shared_mutex> auto_upgrade_unique_lock; + +void testUpgrade(void) +{ + shared_mutex mtx; + auto_upgrade_lock lock(mtx); + // Do some read-only stuff + + auto_upgrade_unique_lock writeLock(lock); + // Do some write-only stuff with the upgraded lock +} + +int main() +{ + testUpgrade(); + return 0; +} diff --git a/src/boost/libs/thread/test/test_6174.cpp b/src/boost/libs/thread/test/test_6174.cpp new file mode 100644 index 000000000..bc28dcfad --- /dev/null +++ b/src/boost/libs/thread/test/test_6174.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/future.hpp> +#include <boost/config.hpp> + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +struct MovableButNonCopyable { +#if ! defined BOOST_NO_CXX11_DELETED_FUNCTIONS + MovableButNonCopyable(MovableButNonCopyable const&) = delete; + MovableButNonCopyable& operator=(MovableButNonCopyable const&) = delete; +#else +private: + MovableButNonCopyable(MovableButNonCopyable const&); + MovableButNonCopyable& operator=(MovableButNonCopyable const&); +#endif +public: + MovableButNonCopyable() {}; + MovableButNonCopyable(MovableButNonCopyable&&) {}; + MovableButNonCopyable& operator=(MovableButNonCopyable&&) + { + return *this; + }; +}; + +MovableButNonCopyable construct() +{ + return MovableButNonCopyable(); +} + +int main() +{ + boost::packaged_task<MovableButNonCopyable> pt(construct); + pt(); + return 0; +} +#else +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/test_7160.cpp b/src/boost/libs/thread/test/test_7160.cpp new file mode 100644 index 000000000..644d87fa8 --- /dev/null +++ b/src/boost/libs/thread/test/test_7160.cpp @@ -0,0 +1,36 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + +#include <iostream> +#include <boost/thread/thread_only.hpp> + +class ThreadClass +{ +public: + ThreadClass() + { + } + + void operator()() + { + return; + } +}; + +int main() +{ + boost::posix_time::ptime currentTimeUTC; + + ThreadClass tc; + boost::thread t(tc); + t.join(); //causes a runtime access violation here + + std::cout << "done" << std::endl; + //system("pause"); + + return 0; +} diff --git a/src/boost/libs/thread/test/test_7328.cpp b/src/boost/libs/thread/test/test_7328.cpp new file mode 100644 index 000000000..0c0cca03a --- /dev/null +++ b/src/boost/libs/thread/test/test_7328.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <iostream> +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +//using namespace boost; +using namespace boost::chrono; + +bool interrupted = false; +void f() +{ + try + { + std::cout << "Starting sleep in thread" << std::endl; + for (;;) + { + boost::this_thread::sleep_for(seconds(60)); + } + } + catch (const boost::thread_interrupted&) + { + interrupted = true; + std::cout << "Thread interrupted." << std::endl; + } +} + +int main() +{ + boost::thread t(f); + t.interrupt(); + t.join(); + std::cout << "Joined with thread." << std::endl; + BOOST_TEST(interrupted); + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/test_7571.cpp b/src/boost/libs/thread/test/test_7571.cpp new file mode 100644 index 000000000..a336795f4 --- /dev/null +++ b/src/boost/libs/thread/test/test_7571.cpp @@ -0,0 +1,93 @@ +// Copyright (C) 2012 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#include <boost/date_time.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread_only.hpp> +#include <iostream> + +// Number should be big enough to allow context switch between threads, otherwise the bug doesn't show. +static int MAX_COUNTS; + +class ItemKeeper { + +public: + ItemKeeper() { } + + void doSomething() { + boost::unique_lock<boost::mutex> scoped_lock(mutex); + int counts = MAX_COUNTS; + while (counts--); + } + +private: + boost::mutex mutex; +}; + +ItemKeeper itemKeeper; + +int MAX_ITERATIONS(5); + +void threadFunc(int invokerID, bool& exceptionOccurred) { + try { + for (int i = 0; i < MAX_ITERATIONS; i++) { + std::cout << "Thread " << invokerID << ", iteration " << i << std::endl; + itemKeeper.doSomething(); + } + } catch (...) { + exceptionOccurred = true; + } +} + + +int main(int argc, char* argv[]) { + if (argc < 2) { + MAX_COUNTS = 5000000; + } else { + std::string valueStr(argv[1]); + bool has_only_digits = (valueStr.find_first_not_of( "0123456789" ) == std::string::npos); + if (has_only_digits) { + std::istringstream aStream(valueStr); + aStream >> MAX_COUNTS; + } else { + std::cerr << "Argument should be an integer\n"; + return 1; + } + } + + bool exceptionOccurred1(false); + bool exceptionOccurred2(false); + + boost::thread thread1(threadFunc, 1, boost::ref(exceptionOccurred1)); + boost::thread thread2(threadFunc, 2, boost::ref(exceptionOccurred2)); + + boost::posix_time::time_duration timeout = boost::posix_time::milliseconds(10000*100); + + bool deadlockOccured(false); + //thread1.join(); + //thread2.join(); + + if (!thread1.timed_join(timeout)) { + deadlockOccured = true; + thread1.interrupt(); + } + if (!thread2.timed_join(timeout)) { + deadlockOccured = true; + thread2.interrupt(); + } + + if (deadlockOccured) { + std::cout << "Deadlock occurred\n"; + return 1; + } + if (exceptionOccurred1 || exceptionOccurred2) { + std::cout << "Exception occurred\n"; + return 1; + } + return 0; +} + diff --git a/src/boost/libs/thread/test/test_7665.cpp b/src/boost/libs/thread/test/test_7665.cpp new file mode 100644 index 000000000..7244a7d34 --- /dev/null +++ b/src/boost/libs/thread/test/test_7665.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_USES_LOG + +#include <iostream> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/detail/log.hpp> + +void thread() +{ + BOOST_THREAD_LOG << "<thrd" << BOOST_THREAD_END_LOG; + try { + boost::this_thread::sleep_for(boost::chrono::seconds(30)); + } catch (...) + { + BOOST_THREAD_LOG << "thrd exception" << BOOST_THREAD_END_LOG; + throw; + } + //while (1) ; // Never quit + BOOST_THREAD_LOG << "thrd>" << BOOST_THREAD_END_LOG; +} + +boost::thread example(thread); + +int main() +{ + BOOST_THREAD_LOG << "<main" << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::seconds(30)); + BOOST_THREAD_LOG << "main" << BOOST_THREAD_END_LOG; + //while (1) ; // Never quit + example.join(); + BOOST_THREAD_LOG << "main>" << BOOST_THREAD_END_LOG; + return 0; +} + diff --git a/src/boost/libs/thread/test/test_7666.cpp b/src/boost/libs/thread/test/test_7666.cpp new file mode 100644 index 000000000..1ec71dff8 --- /dev/null +++ b/src/boost/libs/thread/test/test_7666.cpp @@ -0,0 +1,23 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_CHRONO_VERSION 2 +#define BOOST_THREAD_VERSION 2 + +#include <boost/thread/thread_only.hpp> + +void myFunc() +{ + boost::this_thread::sleep(boost::posix_time::seconds(5)); +} + +int main(int, char **) +{ + boost::thread p(myFunc); + + p.join(); + + return 0; +} diff --git a/src/boost/libs/thread/test/test_7720.cpp b/src/boost/libs/thread/test/test_7720.cpp new file mode 100644 index 000000000..4dfe95a73 --- /dev/null +++ b/src/boost/libs/thread/test/test_7720.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +//////////////////////////////////////////// + +//#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#include <boost/thread/thread_only.hpp> +#include <boost/thread/shared_mutex.hpp> +using namespace boost; + +shared_mutex mtx; + +const int max_count = 100; +void f() +{ + int count =max_count; + while (count--) + { + upgrade_lock<shared_mutex> lock(mtx); + } +} + +void g() +{ + int count =max_count; + while (count--) + { + shared_lock<shared_mutex> lock(mtx); + } +} + +void h() +{ + int count =max_count; + while (count--) + { + unique_lock<shared_mutex> lock(mtx); + } +} + +int main() +{ + thread t0(f); + thread t1(g); + thread t2(h); + + t0.join(); + t1.join(); + t2.join(); + + return 0; +} + + diff --git a/src/boost/libs/thread/test/test_7755.cpp b/src/boost/libs/thread/test/test_7755.cpp new file mode 100644 index 000000000..5551a6bb9 --- /dev/null +++ b/src/boost/libs/thread/test/test_7755.cpp @@ -0,0 +1,94 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +//////////////////////////////////////////// + +//#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#include <iostream> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/shared_mutex.hpp> +// shared_mutex_deadlock.cpp : Defines the entry point for the console application. +// + + +boost::shared_mutex mutex; + +void thread2_func() +{ + int i (0); + for (;;) + { + if (mutex.timed_lock(boost::posix_time::milliseconds(500))) + { + std::cout << "Unique lock acquired" << std::endl + << "Test successful" << std::endl; + mutex.unlock(); + break; + } + ++i; + if (i == 100) + { + std::cout << "Test failed. App is deadlocked" << std::endl; + break; + } + boost::this_thread::sleep(boost::posix_time::seconds(1)); + } +} + +void thread3_func() +{ + boost::shared_lock<boost::shared_mutex> lock (mutex); + std::cout << "Shared lock acquired" << std::endl + << "Test successful" << std::endl; +} + +void thread3_func_workaround() +{ + for (;;) + { + if (mutex.timed_lock_shared(boost::posix_time::milliseconds(200))) + { + std::cout << "Shared lock acquired" << std::endl + << "Test successful" << std::endl; + mutex.unlock_shared(); + break; + } + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + } +} + +int main() +{ + std::cout << "Starting" << std::endl; + + // 1 - lock the mutex + boost::shared_lock<boost::shared_mutex> lock (mutex); + + // 2 - start thread#2 + boost::thread thread2(&thread2_func); + + // 3 - sleep + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + std::cout << "Thread#2 is waiting" << std::endl; + + // - start thread3 + boost::thread thread3(&thread3_func); + //boost::thread thread3(&thread3_func_workaround); + + std::cout << "Thread#3 is started and blocked. It never will waked" << std::endl; + + thread3.join(); // will never return + + lock.unlock(); // release shared ownership. thread#2 will take unique ownership + + thread2.join(); + + std::cout << "Finished" << std::endl; + return 0; +} + + + diff --git a/src/boost/libs/thread/test/test_8455.cpp b/src/boost/libs/thread/test/test_8455.cpp new file mode 100644 index 000000000..bbc4e5673 --- /dev/null +++ b/src/boost/libs/thread/test/test_8455.cpp @@ -0,0 +1,23 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/mutex.hpp> +boost::mutex mut; +void boostMutexImp1() +{ + boost::mutex::scoped_lock lock(mut); + mut.unlock(); // A: with this X blocks + //lock.unlock(); // No influence if used also if before A +} +void boostMutexImp2() +{ + boost::mutex::scoped_lock lock(mut); // X: blocks with A +} +int main() +{ + boostMutexImp1(); + boostMutexImp2(); + return 0; +} diff --git a/src/boost/libs/thread/test/test_8508.cpp b/src/boost/libs/thread/test/test_8508.cpp new file mode 100644 index 000000000..f53d1487d --- /dev/null +++ b/src/boost/libs/thread/test/test_8508.cpp @@ -0,0 +1,20 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +//#define BOOST_THREAD_VERSION 2 + +#include <boost/thread/thread.hpp> + +void thread_main() +{ +} + +int main(void) +{ + boost::thread t(thread_main); + t.join(); + return 0; +} + diff --git a/src/boost/libs/thread/test/test_8557.cpp b/src/boost/libs/thread/test/test_8557.cpp new file mode 100644 index 000000000..b8efee5a1 --- /dev/null +++ b/src/boost/libs/thread/test/test_8557.cpp @@ -0,0 +1,140 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// B + +#include <malloc.h> +#include <boost/thread/thread.hpp> + +#include <boost/thread/mutex.hpp> + +#include <boost/bind/bind.hpp> + +#include <iostream> + + static void + display_mallinfo() + { + struct mallinfo mi; + + mi = mallinfo(); + + printf("Total non-mmapped bytes (arena): %d\n", mi.arena); + printf("# of free chunks (ordblks): %d\n", mi.ordblks); + printf("# of free fastbin blocks (smblks): %d\n", mi.smblks); + printf("# of mapped regions (hblks): %d\n", mi.hblks); + printf("Bytes in mapped regions (hblkhd): %d\n", mi.hblkhd); + printf("Max. total allocated space (usmblks): %d\n", mi.usmblks); + printf("Free bytes held in fastbins (fsmblks): %d\n", mi.fsmblks); + printf("Total allocated space (uordblks): %d\n", mi.uordblks); + printf("Total free space (fordblks): %d\n", mi.fordblks); + printf("Topmost releasable block (keepcost): %d\n", mi.keepcost); + } + +boost::mutex io_mutex; + +void count() { + + for (int i = 0; i < 10; ++i) { + + boost::mutex::scoped_lock lock(io_mutex); + + //boost::this_thread::sleep( boost::posix_time::milliseconds( 100 ) ); + + } + +} +void* count2(void*) { + + for (int i = 0; i < 10; ++i) { + + boost::mutex::scoped_lock lock(io_mutex); + + boost::this_thread::sleep( boost::posix_time::milliseconds( 100 ) ); + + } + return 0; +} + +int main() { + printf("\n============== sizeof(boost::thread) ============== %d\n", sizeof(boost::thread)); + printf("\n============== sizeof(boost::detail::thread_data_base) ============== %d\n", sizeof(boost::detail::thread_data_base)); + printf("\n============== sizeof(boost::detail::thread_data<>) ============== %d\n", sizeof(boost::detail::thread_data<void(*)()>)); + printf("\n============== Before thread creation ==============\n"); + display_mallinfo(); + { + boost::thread thrd1(&count); + + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + + boost::thread thrd2(&count); + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + boost::thread thrd3(&count); + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + + thrd1.join(); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + + thrd2.join(); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + thrd3.join(); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + } + printf("\n============== After thread destruction ==============\n"); + display_mallinfo(); + + { + pthread_attr_t attr; + pthread_attr_init(&attr); + + pthread_t thrd1; + pthread_create(&thrd1, &attr, &count2, 0); + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + + pthread_t thrd2; + pthread_create(&thrd2, &attr, &count2, 0); + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + + pthread_t thrd3; + pthread_create(&thrd3, &attr, &count2, 0); + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + + pthread_attr_destroy(&attr); + printf("\n============== After thread attr destroy ==============\n"); + display_mallinfo(); + + void* res; + pthread_join(thrd3, &res); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + + pthread_join(thrd2, &res); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + pthread_join(thrd1, &res); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + + + + //pthread_destroy(&thrd1); + //pthread_destroy(&thrd2); + //pthread_destroy(&thrd3); + } + printf("\n============== After thread destruction ==============\n"); + display_mallinfo(); + + return 1; + +} diff --git a/src/boost/libs/thread/test/test_8586.cpp b/src/boost/libs/thread/test/test_8586.cpp new file mode 100644 index 000000000..926f8b398 --- /dev/null +++ b/src/boost/libs/thread/test/test_8586.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/thread.hpp> +#include <iostream> + +void hello_world() +{ + std::cout << "Hello from thread!" << std::endl; +} + +int main() +{ + boost::thread my_thread(&hello_world); + my_thread.join(); +} diff --git a/src/boost/libs/thread/test/test_8596.cpp b/src/boost/libs/thread/test/test_8596.cpp new file mode 100644 index 000000000..d8af66e87 --- /dev/null +++ b/src/boost/libs/thread/test/test_8596.cpp @@ -0,0 +1,61 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 + +#include <iostream> +#include <functional> +//#include <future> + +#include <boost/thread.hpp> +#include <boost/shared_ptr.hpp> + +int f() +{ + return 42; +} + +boost::packaged_task<int()>* schedule(boost::function<int ()> const& fn) +{ + // Normally, the pointer to the packaged task is stored in a queue + // for execution on a separate thread, and the schedule function + // would return just a future<T> + + boost::function<int ()> copy(fn); + boost::packaged_task<int()>* result = new boost::packaged_task<int()>(copy); + return result; +} + +struct MyFunc +{ + MyFunc(MyFunc const&) = delete; + MyFunc& operator=(MyFunc const&) = delete; + MyFunc() {}; + MyFunc(MyFunc &&) {}; + MyFunc& operator=(MyFunc &&) { return *this;}; + void operator()()const {} +}; + + +int main() +{ + boost::packaged_task<int()>* p(schedule(f)); + (*p)(); + + boost::future<int> fut = p->get_future(); + std::cout << "The answer to the ultimate question: " << fut.get() << std::endl; + + { + boost::function<void()> f; + MyFunc mf; + + boost::packaged_task<void()> t1(f); + boost::packaged_task<void()> t2(boost::move(mf)); + } + + return 0; +} + + diff --git a/src/boost/libs/thread/test/test_8600.cpp b/src/boost/libs/thread/test/test_8600.cpp new file mode 100644 index 000000000..224e41fa6 --- /dev/null +++ b/src/boost/libs/thread/test/test_8600.cpp @@ -0,0 +1,140 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/assert.hpp> +#include <boost/static_assert.hpp> +#include <vector> +#include <utility> +#include <type_traits> +#if 1 + +struct B { + int v; + B(int i) : v(i) {} +}; + +struct D: B { + D(int i) : B(i) {} +}; + +void fb(B const&) {} +void fd(D const&) {} + +BOOST_STATIC_ASSERT(sizeof(B)==sizeof(D)); + +template <class T, class Allocator=std::allocator<T> > +class new_vector; +template <class T, class Allocator> +class new_vector : public std::vector<T,Allocator> +{ + typedef std::vector<T,Allocator> base_type; +public: + new_vector() : base_type() {} + new_vector(unsigned s) : base_type(s) {} +}; + +template <class Allocator > +class new_vector<bool, Allocator> +{ + //std::vector<char,typename Allocator::template rebind<char>::other > v; + int i; +public: +}; + +template <class T, class A> +typename std::enable_if<!std::is_same<T, bool>::value, + new_vector<T,A>& +>::type +new_vector_cast(std::vector<T,A> & v) { + return reinterpret_cast<new_vector<T,A>&>(v); +} + +BOOST_STATIC_ASSERT(sizeof(std::vector<int>)==sizeof(new_vector<int>)); +BOOST_STATIC_ASSERT(sizeof(std::vector<bool>)!=sizeof(new_vector<bool>)); + +void fb(std::vector<int> const&) {} +void fd(new_vector<int> const&) {} + +int main() { + { + std::vector<int> b(1); + b[0] = 1; + new_vector<int> d = new_vector_cast(b); + BOOST_ASSERT(b[0] == d[0]); + } + { + //std::vector<bool> b; + //new_vector<bool> d = new_vector_cast(b); // compile fail + } + { + std::vector<int> b(1); + b[0] = 1; + fd(new_vector_cast(b)); + } + { + new_vector<int> d(1); + d[0] = 1; + std::vector<int> b = d; + BOOST_ASSERT(b[0] == d[0]); + } + { + //new_vector<bool> d; + //std::vector<bool> b = d; // compile fail + } + { + new_vector<int> d(1); + d[0] = 1; + fd(d); + } + return 0; +} + + +#else +int main() { + { + B b(1); + D d = reinterpret_cast<D&>(b); + BOOST_ASSERT(b.v == d.v); + } + { + B b(1); + fd(reinterpret_cast<D&>(b)); + } + { + D d(2); + B b = d; + BOOST_ASSERT(b.v == d.v); + } + { + D d(2); + fd(d); + } + return 0; +} + +#define BOOST_THREAD_VERSION 4 + +#include <iostream> +#include <boost/thread.hpp> + +int calculate_the_answer_to_life_the_universe_and_everything() +{ +return 42; +} + +int main() +{ +boost::packaged_task<int()> pt(calculate_the_answer_to_life_the_universe_and_everything); +boost::shared_future<int> fi1 = boost::shared_future<int>(pt.get_future()); +boost::shared_future<int> fi2 = fi1; + +boost::thread task(boost::move(pt)); // launch task on a thread + +boost::wait_for_any(fi1, fi2); +std::cout << "Wait for any returned\n"; +return (0); +} +#endif diff --git a/src/boost/libs/thread/test/test_8674.cpp b/src/boost/libs/thread/test/test_8674.cpp new file mode 100644 index 000000000..87a6524d8 --- /dev/null +++ b/src/boost/libs/thread/test/test_8674.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> + +#define USE_STD 0 +#define USE_BOOST 1 + +#define USED_THREAD_API USE_BOOST +//#define USED_THREAD_API USE_STD + +#if USED_THREAD_API == USE_BOOST + +# define BOOST_THREAD_VERSION 4 +# include <boost/thread/future.hpp> + + using boost::future; + using boost::async; + +#endif +#if USED_THREAD_API == USE_STD +# include <future> + using std::future; + using std::async; +#endif + + + +future<void> do_something() +{ + auto result = async( []{ std::cout<< "A\n"; } ); + std::cout << "B\n"; + return result; // error here +} + +int main() +{ + do_something().wait(); + std::cout << "Hello, World!" << std::endl; + return 0; +} diff --git a/src/boost/libs/thread/test/test_8943.cpp b/src/boost/libs/thread/test/test_8943.cpp new file mode 100644 index 000000000..99cf70de1 --- /dev/null +++ b/src/boost/libs/thread/test/test_8943.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/detail/lightweight_test.hpp> + +#if defined(WIN32) +#include <tchar.h> +#endif + +#include <cstdlib> +#include <iostream> +#include <boost/thread/once.hpp> + +namespace { + +class foo +{ +public: + void operator()() const + { + std::cout << "foo" << std::endl; + } +}; // class foo + +} + +#if defined(WIN32) +int _tmain(int /*argc*/, _TCHAR* /*argv*/[]) +#else +int main(int /*argc*/, char* /*argv*/[]) +#endif +{ + try + { + boost::once_flag once_flag = BOOST_ONCE_INIT; + boost::call_once(once_flag, foo()); + return EXIT_SUCCESS; + } + catch (...) + { + std::cerr << "Unknown exception" << std::endl; + BOOST_TEST(false); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_8960.cpp b/src/boost/libs/thread/test/test_8960.cpp new file mode 100644 index 000000000..84cce77e4 --- /dev/null +++ b/src/boost/libs/thread/test/test_8960.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/thread.hpp> +#include <iostream> + +#include <iostream> + +#include <boost/thread.hpp> +#include <boost/thread/locks.hpp> +#include <boost/chrono.hpp> +//#include <boost/bind/bind.hpp> +#include <boost/detail/lightweight_test.hpp> + + +void do_thread() +{ + + try + { + boost::condition_variable c1; + boost::mutex m1; + boost::unique_lock<boost::mutex> l1(m1); + + c1.wait_for(l1, boost::chrono::seconds(1)); + } + catch (std::runtime_error& ex) + { + std::cout << "EXCEPTION ! " << ex.what() << std::endl; + BOOST_TEST(false); + + } + catch (...) + { + std::cout << "EXCEPTION ! " << std::endl; + BOOST_TEST(false); + } + +} + +int main() +{ + + boost::thread th1(&do_thread); + th1.join(); + + //std::string s1; + //std::cin >> s1; + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_9079_a.cpp b/src/boost/libs/thread/test/test_9079_a.cpp new file mode 100644 index 000000000..3e8ca03fd --- /dev/null +++ b/src/boost/libs/thread/test/test_9079_a.cpp @@ -0,0 +1,57 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// A + +//#include <boost/log/trivial.hpp> +#include <boost/chrono.hpp> +#include <boost/thread.hpp> +#include <boost/thread/condition_variable.hpp> + +//#if !defined(BOOST_NO_CXX11_ALIGNAS) +//#error +//# define BOOST_ALIGNMENT2(x) alignas(x) +//#elif defined(_MSC_VER) +//#error +//# define BOOST_ALIGNMENT2(x) __declspec(align(x)) +//#elif defined(__GNUC__) +//#error +//# define BOOST_ALIGNMENT(x) __attribute__ ((__aligned__(x))) +//#else +//#error +//# define BOOST_NO_ALIGNMENT2 +//# define BOOST_ALIGNMENT2(x) +//#endif + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point TimePoint; + +inline TimePoint real_time_now() +{ + return Clock::now(); +} + +int main() +{ + using namespace boost::chrono; + + boost::condition_variable m_task_spawn_condition; + + boost::mutex main_thread_mutex; + boost::unique_lock < boost::mutex > main_thread_lock(main_thread_mutex); + + //BOOST_LOG_TRIVIAL(info) << "[TaskScheduler::run_and_wait] Scheduling loop - BEGIN"; + + //for (;;) + { + static const milliseconds TIME_BACK = milliseconds(1); + m_task_spawn_condition.wait_until( + main_thread_lock, + real_time_now() - TIME_BACK); // wait forever + m_task_spawn_condition.wait_for( main_thread_lock, - TIME_BACK ); // same problem + //BOOST_LOG_TRIVIAL(trace) << "TICK"; + } + +} diff --git a/src/boost/libs/thread/test/test_9079_b.cpp b/src/boost/libs/thread/test/test_9079_b.cpp new file mode 100644 index 000000000..90abd206f --- /dev/null +++ b/src/boost/libs/thread/test/test_9079_b.cpp @@ -0,0 +1,86 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// B + +#include <boost/atomic.hpp> +//#include <boost/log/trivial.hpp> +#include <boost/chrono.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/thread.hpp> +#include <boost/thread/condition_variable.hpp> + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point TimePoint; + +inline TimePoint real_time_now() +{ + return Clock::now(); +} + +class Foo { + boost::atomic<bool> m_is_exiting; + TimePoint m_next_tick_time; + +public: + + bool is_exiting() const + { + return m_is_exiting; + } + + TimePoint spawn_tasks() // note that in my app, this call takes more time than here + { + using namespace boost::chrono; + const TimePoint now = real_time_now(); + + if (m_next_tick_time < now) { + m_next_tick_time = now + seconds(1); + //BOOST_LOG_TRIVIAL(info) << "TICK!"; + } + + return m_next_tick_time; + } + +}; + +int main() +{ + using namespace boost::chrono; + static const milliseconds MIN_TIME_TASKS_SPAWN_FREQUENCY = milliseconds(1); + //microseconds(1); // THE SHORTER THE QUICKER TO REPRODUCE THE BUG + + boost::condition_variable m_task_spawn_condition; + Foo foo; + + boost::mutex main_thread_mutex; + boost::unique_lock < boost::mutex > main_thread_lock(main_thread_mutex); + + //BOOST_LOG_TRIVIAL(info) << "[TaskScheduler::run_and_wait] Scheduling loop - BEGIN"; + + int i =11; + while (i--) + { + const TimePoint next_task_spawn_time = foo.spawn_tasks(); + + const TimePoint now = real_time_now(); + const TimePoint next_minimum_spawn_time = now + MIN_TIME_TASKS_SPAWN_FREQUENCY; + const TimePoint next_spawn_time = next_task_spawn_time > TimePoint() + && next_task_spawn_time < next_minimum_spawn_time + ? next_task_spawn_time : next_minimum_spawn_time; + + const TimePoint::duration wait_time = next_spawn_time - now; + if (wait_time > wait_time.zero()) { + // BOOST_LOG_TRIVIAL(trace) << "WAIT TIME: " << wait_time; // UNCOMMENT THIS: MAKES IT WORKS. WAT?????? + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + std::cout << next_spawn_time << std::endl; + m_task_spawn_condition.wait_until( + main_thread_lock, + next_spawn_time); // DON'T WORK: WILL WAIT IF next_spawn_time is too close! + } + + } + +} diff --git a/src/boost/libs/thread/test/test_9192.cpp b/src/boost/libs/thread/test/test_9192.cpp new file mode 100644 index 000000000..c7aad7dd8 --- /dev/null +++ b/src/boost/libs/thread/test/test_9192.cpp @@ -0,0 +1,145 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/interprocess/shared_memory_object.hpp> +#include <boost/interprocess/mapped_region.hpp> +#include <boost/thread.hpp> + +using namespace boost::interprocess; + +struct item +{ + int i; +}; + +struct queue +{ + void put( const item& item ) + { + boost::unique_lock<boost::mutex> lock(mutex); + while ( item_in ) + cond_full.wait(lock); + + item_ = item; + item_in = true; + cond_empty.notify_one(); + } + + void print() + { + boost::unique_lock<boost::mutex> lock(mutex); + while ( !item_in ) + cond_empty.wait(lock); + + item_in = false; + std::cout << item_.i << std::endl; + cond_full.notify_one(); + } + + +private: + //Mutex to protect access to the queue + boost::mutex mutex; + + //Condition to wait when the queue is empty + boost::condition_variable cond_empty; + + //Condition to wait when the queue is full + boost::condition_variable cond_full; + + bool item_in; + + //Items to fill + item item_; +}; + +void *addr; + +void printThread() +{ + //Erase previous shared memory and schedule erasure on exit + struct shm_remove + { + shm_remove() { shared_memory_object::remove("MySharedMemory"); } + ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); } + } remover; + + //Create a shared memory object. + shared_memory_object shm(create_only,"MySharedMemory",read_write); + + try + { +// //Set size +// shm.truncate(sizeof(queue)); +// +// //Map the whole shared memory in this process +// mapped_region region(shm,read_write); +// +// //Get the address of the mapped region +// void *addr = region.get_address(); + + //Construct the shared structure in memory + queue *q = new (addr) queue; + + do + { + q->print(); + } while ( true ); + } +// catch(interprocess_exception &ex) +// { +// std::cout << ex.what() << std::endl; +// } + catch(boost::thread_interrupted&) + { + std::cout << "interrupted" << std::endl; + } + catch(...) + { + std::cout << "exception" << std::endl; + } +} + +int main() +{ + addr = new queue(); + boost::thread t(printThread); + + // give the thread time to create the shm + boost::this_thread::sleep( boost::posix_time::milliseconds( 1000 ) ); + +// //Create a shared memory object. +// shared_memory_object shm(open_only,"MySharedMemory",read_write); + + try + { +// //Map the whole shared memory in this process +// mapped_region region(shm,read_write); +// +// //Get the address of the mapped region +// void *addr = region.get_address(); + + //Obtain a pointer to the shared structure + queue *q = static_cast<queue*>(addr); + + item i; + i.i = 42; + q->put( i ); + + ++i.i; + q->put( i ); + + // give the printThread time to "process" the item + boost::this_thread::sleep( boost::posix_time::milliseconds( 1000 ) ); + + t.interrupt(); + t.join(); + } + catch(...) + { + std::cout << "exception" << std::endl; + return -1; + } +} diff --git a/src/boost/libs/thread/test/test_9303.cpp b/src/boost/libs/thread/test/test_9303.cpp new file mode 100644 index 000000000..af8be567d --- /dev/null +++ b/src/boost/libs/thread/test/test_9303.cpp @@ -0,0 +1,177 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 + #include <iostream> + #include <fstream> + #include <stdio.h> + #include <boost/function.hpp> + #include <boost/make_shared.hpp> + #include <boost/shared_ptr.hpp> + #include <boost/bind/bind.hpp> + #include <boost/asio.hpp> + #include <boost/thread.hpp> + #include <boost/thread/future.hpp> + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + #define EXAMPLE_1 + #define EXAMPLE_2 + #define EXAMPLE_3 + #define EXAMPLE_4 + #define EXAMPLE_5 + #define EXAMPLE_6 + #define EXAMPLE_7 +#else + #define EXAMPLE_1 + #define EXAMPLE_2 + //#define EXAMPLE_3 + //#define EXAMPLE_4 + //#define EXAMPLE_5 + //#define EXAMPLE_6 + //#define EXAMPLE_7 +#endif + + // Test functions + + int int_no_params() + { + return 42; + } + + int int_with_params(int i) + { + return i; + } + + std::string string_no_params() + { + return std::string("forty two"); + } + + std::string string_with_params(std::string& ans) + { + return ans; + } + + int main(int /*argc*/, char ** /*argv[]*/) + { + std::string ans("forty two"); + + #if defined EXAMPLE_1 + //! Compiles and produces correct result. + { + boost::packaged_task<int()> example(int_no_params); + boost::future<int> f = example.get_future(); + boost::thread task(boost::move(example)); + int answer = f.get(); + std::cout << "Answer to life and whatnot, in English: " << answer << std::endl; + task.join(); + } + #endif + + #if defined EXAMPLE_2 + //! Compiles and produces correct result. + { + boost::packaged_task<std::string()> example(string_no_params); + boost::future<std::string> f = example.get_future(); + boost::thread task(boost::move(example)); + std::string answer = f.get(); + std::cout << "string_no_params: " << answer << std::endl; + task.join(); + } + + #endif + + #if defined EXAMPLE_3 + //! Doesn't compile in C++03. + //! error: variable âboost::packaged_task<std::basic_string<char>(std::basic_string<char>&)> exampleâ has initializer but incomplete type + + { + boost::packaged_task<std::string(std::string&)> example(string_with_params); + boost::future<std::string> f = example.get_future(); + example(ans); + std::string answer = f.get(); + std::cout << "string_with_params: " << answer << std::endl; + } + + #endif + + #if defined EXAMPLE_4 + //! Doesn't compile in C++11 +// In file included from test_9303.cpp:10: +// In file included from ../../../boost/thread.hpp:13: +// In file included from ../../../boost/thread/thread.hpp:12: +// In file included from ../../../boost/thread/thread_only.hpp:22: +// ../../../boost/thread/detail/thread.hpp:76:15: error: no matching function for call to 'invoke' +// invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...); +// ^~~~~~ + + { + boost::packaged_task<std::string(std::string&)> example(string_with_params); + boost::future<std::string> f = example.get_future(); + boost::thread task(boost::move(example), boost::ref(ans)); + std::string answer = f.get(); + std::cout << "string_with_params: " << answer << std::endl; + task.join(); + } + #endif + + #if defined EXAMPLE_5 + //! Doesn't compile in C++03, C++11 only. + //! error: extended initializer lists only available with -std=c++11 or -std=gnu++11 [-Werror] + { + boost::packaged_task<std::string(std::string&)> example + { boost::bind(&string_with_params, ans) }; + boost::future<std::string> f = example.get_future(); + boost::thread task(boost::move(example), boost::ref(ans)); + std::string answer = f.get(); + std::cout << "string_with_params: " << answer << std::endl; + task.join(); + } + #endif + + #if defined EXAMPLE_6 + //! Doesn't compile in C++03, C++11 only. + // packagedTestTest.cpp:94:43: error: invalid use of incomplete type ‘class boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>’ + // packagedTestTest.cpp:95:37: error: incomplete type ‘task_t {aka boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>}’ used in nested name specifier + // boost/thread/future.hpp:1320:11: error: declaration of ‘class boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>’ + { + //typedef boost::packaged_task<std::string(std::string&)> task_t; + typedef boost::packaged_task<std::string()> task_t; + boost::shared_ptr<task_t> example = boost::make_shared<task_t>(boost::bind(&string_with_params, boost::ref(ans))); + boost::future<std::string> f = example->get_future(); + boost::thread task(boost::bind(&task_t::operator(), example)); + std::string answer = f.get(); + std::cout << "string_with_params: " << answer << std::endl; + task.join(); + } + #endif + + #if defined EXAMPLE_7 + //! Doesn't compile in C++03, C++11 only. + // packagedTestTest.cpp:94:43: error: invalid use of incomplete type ‘class boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>’ + // packagedTestTest.cpp:95:37: error: incomplete type ‘task_t {aka boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>}’ used in nested name specifier + // boost/thread/future.hpp:1320:11: error: declaration of ‘class boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>’ + { + boost::asio::io_service io_service; + boost::thread_group threads; + boost::asio::io_service::work work(io_service); + + for (int i = 0; i < 3; ++i) + { + threads.create_thread(boost::bind(&boost::asio::io_service::run, + &io_service)); + } + typedef boost::packaged_task<std::string()> task_t; + boost::shared_ptr<task_t> example = boost::make_shared<task_t>(boost::bind(&string_with_params, ans)); + boost::future<std::string> f = example->get_future(); + io_service.post(boost::bind(&task_t::operator(), example)); + std::string answer = f.get(); + std::cout << "string_with_params: " << answer << std::endl; + threads.join_all(); + } + #endif + return 0; + } diff --git a/src/boost/libs/thread/test/test_9319.cpp b/src/boost/libs/thread/test/test_9319.cpp new file mode 100644 index 000000000..5dafe4d49 --- /dev/null +++ b/src/boost/libs/thread/test/test_9319.cpp @@ -0,0 +1,60 @@ +// Copyright (C) 2013 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// futtest.cpp +#include <iostream> +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/bind/bind.hpp> +#include <boost/chrono.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/scoped_ptr.hpp> + +typedef boost::shared_ptr< boost::promise<int> > IntPromise; + +void foo(IntPromise p) +{ + std::cout << "foo" << std::endl; + p->set_value(123); // This line locks the future's mutex, then calls the continuation with the mutex already locked. +} + +void bar(boost::future<int> fooResult) +{ + try { + std::cout << "bar" << std::endl; + int i = fooResult.get(); // Code hangs on this line (Due to future already being locked by the set_value call) + std::cout << "i: " << i << std::endl; + } catch(...) { + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + } +} + +int main() +{ + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + try { + IntPromise p(new boost::promise<int>()); + boost::thread t(boost::bind(foo, p)); + boost::future<int> f1 = p->get_future(); + f1.then(boost::launch::deferred, &bar); + t.join(); + } catch(...) { + return 1; + } + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + try { + IntPromise p(new boost::promise<int>()); + boost::thread t(boost::bind(foo, p)); + boost::future<int> f1 = p->get_future(); + f1.then(boost::launch::async, &bar); + t.join(); + } catch(...) { + return 2; + } + std::cout << __FILE__ << ":" << __LINE__ << std::endl; +} + diff --git a/src/boost/libs/thread/test/test_9711.cpp b/src/boost/libs/thread/test/test_9711.cpp new file mode 100644 index 000000000..d8fd8e3e8 --- /dev/null +++ b/src/boost/libs/thread/test/test_9711.cpp @@ -0,0 +1,44 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_PROVIDES_FUTURE +#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include <boost/thread/future.hpp> + + +int main() +{ +#if ! defined BOOST_NO_CXX11_LAMBDAS && ! (defined BOOST_MSVC && _MSC_VER < 1700) + boost::promise<int> prom; + boost::future<int> futr = prom.get_future(); + + int callCount = 0; + + boost::future<void> futr2 = futr.then(boost::launch::deferred, + [&] (boost::future<int> f) { + callCount++; + assert(f.valid()); + assert(f.is_ready()); + assert(17 == f.get()); + }); + + assert(futr2.valid()); + assert(!futr2.is_ready()); + assert(0 == callCount); + + prom.set_value(17); + assert(0 == callCount); + + futr2.get(); + assert(1 == callCount); + +#endif + return 0; +} diff --git a/src/boost/libs/thread/test/test_9856.cpp b/src/boost/libs/thread/test/test_9856.cpp new file mode 100644 index 000000000..b7dcc6e37 --- /dev/null +++ b/src/boost/libs/thread/test/test_9856.cpp @@ -0,0 +1,29 @@ +#include "boost/atomic.hpp" +#include "boost/thread.hpp" +#include <iostream> + +using namespace boost; + +int main() { + atomic<size_t> total(0), failures(0); + +#pragma omp parallel shared(total, failures) num_threads(1000) + { + mutex mtx; + condition_variable cond; + unique_lock<mutex> lk(mtx); + for (int i = 0; i < 500; i++) { + ++total; + if (cv_status::timeout != cond.wait_for(lk, chrono::milliseconds(10))) + ++failures; + } + } + if(failures) + std::cout << "There were " << failures << " failures out of " << total << " timed waits." << std::endl; + if((100*failures)/total>40) + { + std::cerr << "This exceeds 10%, so failing the test." << std::endl; + return 1; + } + return 0; +} diff --git a/src/boost/libs/thread/test/test_barrier.cpp b/src/boost/libs/thread/test/test_barrier.cpp new file mode 100644 index 000000000..5baf19cd4 --- /dev/null +++ b/src/boost/libs/thread/test/test_barrier.cpp @@ -0,0 +1,69 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// (C) Copyright 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <vector> + +namespace { + +// Shared variables for generation barrier test +const int N_THREADS=3; +boost::barrier gen_barrier(N_THREADS); +boost::mutex mutex; +long global_parameter; + +void barrier_thread() +{ + for (int i = 0; i < 5; ++i) + { + if (gen_barrier.wait()) + { + boost::unique_lock<boost::mutex> lock(mutex); + global_parameter++; + } + } +} + +} // namespace + +void test_barrier() +{ + boost::thread_group g; + global_parameter = 0; + + try + { + for (int i = 0; i < N_THREADS; ++i) + g.create_thread(&barrier_thread); + g.join_all(); + } + catch(...) + { + BOOST_TEST(false); + g.interrupt_all(); + g.join_all(); + //throw; + } + + BOOST_TEST(global_parameter==5); + +} + +int main() +{ + + test_barrier(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/test_barrier_size_fct.cpp b/src/boost/libs/thread/test/test_barrier_size_fct.cpp new file mode 100644 index 000000000..2671af848 --- /dev/null +++ b/src/boost/libs/thread/test/test_barrier_size_fct.cpp @@ -0,0 +1,69 @@ +// (C) Copyright 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <vector> + +namespace { + + +// Shared variables for generation barrier test +long global_parameter; +const int N_THREADS=3; + +unsigned int size_fct() { + global_parameter++; + return N_THREADS; +} + +boost::barrier gen_barrier(N_THREADS, &size_fct); + +void barrier_thread() +{ + for (int i = 0; i < 5; ++i) + { + gen_barrier.count_down_and_wait(); + } +} + +} // namespace + +void test_barrier() +{ + boost::thread_group g; + global_parameter = 0; + + try + { + for (int i = 0; i < N_THREADS; ++i) + g.create_thread(&barrier_thread); + g.join_all(); + } + catch(...) + { + BOOST_TEST(false); + g.interrupt_all(); + g.join_all(); + //throw; + } + + BOOST_TEST(global_parameter==5); + +} + +int main() +{ + + test_barrier(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/test_barrier_void_fct.cpp b/src/boost/libs/thread/test/test_barrier_void_fct.cpp new file mode 100644 index 000000000..77a65e581 --- /dev/null +++ b/src/boost/libs/thread/test/test_barrier_void_fct.cpp @@ -0,0 +1,68 @@ +// (C) Copyright 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <vector> + +namespace { + + +// Shared variables for generation barrier test +long global_parameter; + +void void_fct() { + global_parameter++; +} + +const int N_THREADS=3; +boost::barrier gen_barrier(N_THREADS, &void_fct); + +void barrier_thread() +{ + for (int i = 0; i < 5; ++i) + { + gen_barrier.count_down_and_wait(); + } +} + +} // namespace + +void test_barrier() +{ + boost::thread_group g; + global_parameter = 0; + + try + { + for (int i = 0; i < N_THREADS; ++i) + g.create_thread(&barrier_thread); + g.join_all(); + } + catch(...) + { + BOOST_TEST(false); + g.interrupt_all(); + g.join_all(); + //throw; + } + + BOOST_TEST(global_parameter==5); + +} + +int main() +{ + + test_barrier(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/test_completion_latch.cpp b/src/boost/libs/thread/test/test_completion_latch.cpp new file mode 100644 index 000000000..bef883654 --- /dev/null +++ b/src/boost/libs/thread/test/test_completion_latch.cpp @@ -0,0 +1,108 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2013 Vicente J. Botet Escriba + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/completion_latch.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <vector> + +namespace +{ + + // Shared variables for generation completion_latch test + const int N_THREADS = 10; + boost::completion_latch gen_latch(N_THREADS); + boost::mutex mutex; + long global_parameter; + + void latch_thread() + { + { + boost::unique_lock<boost::mutex> lock(mutex); + global_parameter++; + } + gen_latch.count_down(); + //do something else + } + +} // namespace + +void test_global_parameter() +{ + boost::unique_lock<boost::mutex> lock(mutex); + BOOST_TEST_EQ(global_parameter, N_THREADS); +} + +void reset_gen_latch() +{ + { + boost::unique_lock<boost::mutex> lock(mutex); + BOOST_TEST_EQ(global_parameter, N_THREADS); + } + gen_latch.reset(N_THREADS); +} + +void test_completion_latch_reset() +{ + boost::thread_group g; + boost::thread_group g2; + + gen_latch.then(&reset_gen_latch); + + { + global_parameter = 0; + try + { + for (int i = 0; i < N_THREADS; ++i) + g.create_thread(&latch_thread); + + if (!gen_latch.try_wait()) + if (gen_latch.wait_for(boost::chrono::milliseconds(100)) == boost::cv_status::timeout) + if (gen_latch.wait_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(100)) == boost::cv_status::timeout) + gen_latch.wait(); // All the threads have been updated the global_parameter + g.join_all(); + } + catch (...) + { + BOOST_TEST(false); + g.interrupt_all(); + g.join_all(); + //throw; + } + } + gen_latch.then(&test_global_parameter); + { + global_parameter = 0; + try + { + for (int i = 0; i < N_THREADS; ++i) + g2.create_thread(&latch_thread); + + if (!gen_latch.try_wait()) + gen_latch.wait(); // All the threads have been updated the global_parameter + + g2.join_all(); + } + catch (...) + { + BOOST_TEST(false); + g2.interrupt_all(); + g2.join_all(); + //throw; + } + } +} + +int main() +{ + test_completion_latch_reset(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/test_condition.cpp b/src/boost/libs/thread/test/test_condition.cpp new file mode 100644 index 000000000..210860b71 --- /dev/null +++ b/src/boost/libs/thread/test/test_condition.cpp @@ -0,0 +1,187 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +#define BOOST_TEST_MODULE Boost.Threads: condition test suite +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/condition.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> + +#include <boost/config.hpp> +#include <boost/test/unit_test.hpp> + +#include "./util.inl" + +struct condition_test_data +{ + condition_test_data() : notified(0), awoken(0) { } + + boost::mutex mutex; + boost::condition_variable condition; + int notified; + int awoken; +}; + +void condition_test_thread(condition_test_data* data) +{ + boost::unique_lock<boost::mutex> lock(data->mutex); + BOOST_CHECK(lock ? true : false); + while (!(data->notified > 0)) + data->condition.wait(lock); + BOOST_CHECK(lock ? true : false); + data->awoken++; +} + +struct cond_predicate +{ + cond_predicate(int& var, int val) : _var(var), _val(val) { } +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + cond_predicate(cond_predicate const&) = default; +#endif + + bool operator()() { return _var == _val; } + + int& _var; + int _val; + +private: + void operator=(cond_predicate&); +}; + +void condition_test_waits(condition_test_data* data) +{ + boost::unique_lock<boost::mutex> lock(data->mutex); + BOOST_CHECK(lock ? true : false); + + // Test wait. + while (data->notified != 1) + data->condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data->notified, 1); + data->awoken++; + data->condition.notify_one(); + + // Test predicate wait. + data->condition.wait(lock, cond_predicate(data->notified, 2)); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data->notified, 2); + data->awoken++; + data->condition.notify_one(); + + // Test timed_wait. + boost::xtime xt = delay(10); + while (data->notified != 3) + data->condition.timed_wait(lock, xt); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data->notified, 3); + data->awoken++; + data->condition.notify_one(); + + // Test predicate timed_wait. + xt = delay(10); + cond_predicate pred(data->notified, 4); + BOOST_CHECK(data->condition.timed_wait(lock, xt, pred)); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK(pred()); + BOOST_CHECK_EQUAL(data->notified, 4); + data->awoken++; + data->condition.notify_one(); + + // Test predicate timed_wait with relative timeout + cond_predicate pred_rel(data->notified, 5); + BOOST_CHECK(data->condition.timed_wait(lock, boost::posix_time::seconds(10), pred_rel)); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK(pred_rel()); + BOOST_CHECK_EQUAL(data->notified, 5); + data->awoken++; + data->condition.notify_one(); +} + +void do_test_condition_waits() +{ + condition_test_data data; + + boost::thread thread(bind(&condition_test_waits, &data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + BOOST_CHECK(lock ? true : false); + + boost::thread::sleep(delay(1)); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 1) + data.condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data.awoken, 1); + + boost::thread::sleep(delay(1)); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 2) + data.condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data.awoken, 2); + + boost::thread::sleep(delay(1)); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 3) + data.condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data.awoken, 3); + + boost::thread::sleep(delay(1)); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 4) + data.condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data.awoken, 4); + + + boost::thread::sleep(delay(1)); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 5) + data.condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data.awoken, 5); + } + + thread.join(); + BOOST_CHECK_EQUAL(data.awoken, 5); +} + +BOOST_AUTO_TEST_CASE(test_condition_waits) +{ + // We should have already tested notify_one here, so + // a timed test with the default execution_monitor::use_condition + // should be OK, and gives the fastest performance + timed_test(&do_test_condition_waits, 12); +} + +void do_test_condition_wait_is_a_interruption_point() +{ + condition_test_data data; + + boost::thread thread(bind(&condition_test_thread, &data)); + + thread.interrupt(); + thread.join(); + BOOST_CHECK_EQUAL(data.awoken,0); +} + + +BOOST_AUTO_TEST_CASE(test_condition_wait_is_a_interruption_point) +{ + timed_test(&do_test_condition_wait_is_a_interruption_point, 1); +} + diff --git a/src/boost/libs/thread/test/test_condition_notify_all.cpp b/src/boost/libs/thread/test/test_condition_notify_all.cpp new file mode 100644 index 000000000..17c84d5d5 --- /dev/null +++ b/src/boost/libs/thread/test/test_condition_notify_all.cpp @@ -0,0 +1,216 @@ +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_all test suite +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread_only.hpp> + +#include <boost/test/unit_test.hpp> + +#include "./util.inl" +#include "./condition_test_common.hpp" + +unsigned const number_of_test_threads=5; + +void do_test_condition_notify_all_wakes_from_wait() +{ + wait_for_flag data; + + boost::thread_group group; + + try + { + for(unsigned i=0;i<number_of_test_threads;++i) + { + group.create_thread(bind(&wait_for_flag::wait_without_predicate, data)); + } + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_all(); + } + + group.join_all(); + BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); + } + catch(...) + { + group.join_all(); + throw; + } +} + +void do_test_condition_notify_all_wakes_from_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread_group group; + + try + { + for(unsigned i=0;i<number_of_test_threads;++i) + { + group.create_thread(bind(&wait_for_flag::wait_with_predicate, data)); + } + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_all(); + } + + group.join_all(); + BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); + } + catch(...) + { + group.join_all(); + throw; + } +} + +void do_test_condition_notify_all_wakes_from_timed_wait() +{ + wait_for_flag data; + + boost::thread_group group; + + try + { + for(unsigned i=0;i<number_of_test_threads;++i) + { + group.create_thread(bind(&wait_for_flag::timed_wait_without_predicate, data)); + } + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_all(); + } + + group.join_all(); + BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); + } + catch(...) + { + group.join_all(); + throw; + } +} + +void do_test_condition_notify_all_wakes_from_timed_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread_group group; + + try + { + for(unsigned i=0;i<number_of_test_threads;++i) + { + group.create_thread(bind(&wait_for_flag::timed_wait_with_predicate, data)); + } + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_all(); + } + + group.join_all(); + BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); + } + catch(...) + { + group.join_all(); + throw; + } +} + +void do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread_group group; + + try + { + for(unsigned i=0;i<number_of_test_threads;++i) + { + group.create_thread(bind(&wait_for_flag::relative_timed_wait_with_predicate, data)); + } + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_all(); + } + + group.join_all(); + BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); + } + catch(...) + { + group.join_all(); + throw; + } +} + +namespace +{ + boost::mutex multiple_wake_mutex; + boost::condition_variable multiple_wake_cond; + unsigned multiple_wake_count=0; + + void wait_for_condvar_and_increase_count() + { + boost::unique_lock<boost::mutex> lk(multiple_wake_mutex); + multiple_wake_cond.wait(lk); + ++multiple_wake_count; + } + +} + + +void do_test_notify_all_following_notify_one_wakes_all_threads() +{ + boost::thread thread1(&wait_for_condvar_and_increase_count); + boost::thread thread2(&wait_for_condvar_and_increase_count); + + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + multiple_wake_cond.notify_one(); + + boost::thread thread3(&wait_for_condvar_and_increase_count); + + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + multiple_wake_cond.notify_one(); + multiple_wake_cond.notify_all(); + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + + { + boost::unique_lock<boost::mutex> lk(multiple_wake_mutex); + BOOST_CHECK(multiple_wake_count==3); + } + + thread1.join(); + thread2.join(); + thread3.join(); +} + +BOOST_AUTO_TEST_CASE(test_condition_notify_all) +{ + timed_test(&do_test_condition_notify_all_wakes_from_wait, timeout_seconds); + timed_test(&do_test_condition_notify_all_wakes_from_wait_with_predicate, timeout_seconds); + timed_test(&do_test_condition_notify_all_wakes_from_timed_wait, timeout_seconds); + timed_test(&do_test_condition_notify_all_wakes_from_timed_wait_with_predicate, timeout_seconds); + timed_test(&do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate, timeout_seconds); + timed_test(&do_test_notify_all_following_notify_one_wakes_all_threads, timeout_seconds); +} + + + diff --git a/src/boost/libs/thread/test/test_condition_notify_one.cpp b/src/boost/libs/thread/test/test_condition_notify_one.cpp new file mode 100644 index 000000000..00aff6268 --- /dev/null +++ b/src/boost/libs/thread/test/test_condition_notify_one.cpp @@ -0,0 +1,148 @@ +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_one test suite + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread_only.hpp> + +#include <boost/test/unit_test.hpp> + +#include "./util.inl" +#include "./condition_test_common.hpp" + +void do_test_condition_notify_one_wakes_from_wait() +{ + wait_for_flag data; + + boost::thread thread(bind(&wait_for_flag::wait_without_predicate, data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_one(); + } + + thread.join(); + BOOST_CHECK(data.woken); +} + +void do_test_condition_notify_one_wakes_from_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread thread(bind(&wait_for_flag::wait_with_predicate, data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_one(); + } + + thread.join(); + BOOST_CHECK(data.woken); +} + +void do_test_condition_notify_one_wakes_from_timed_wait() +{ + wait_for_flag data; + + boost::thread thread(bind(&wait_for_flag::timed_wait_without_predicate, data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_one(); + } + + thread.join(); + BOOST_CHECK(data.woken); +} + +void do_test_condition_notify_one_wakes_from_timed_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread thread(bind(&wait_for_flag::timed_wait_with_predicate, data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_one(); + } + + thread.join(); + BOOST_CHECK(data.woken); +} + +void do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread thread(bind(&wait_for_flag::relative_timed_wait_with_predicate, data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_one(); + } + + thread.join(); + BOOST_CHECK(data.woken); +} + +namespace +{ + boost::mutex multiple_wake_mutex; + boost::condition_variable multiple_wake_cond; + unsigned multiple_wake_count=0; + + void wait_for_condvar_and_increase_count() + { + boost::unique_lock<boost::mutex> lk(multiple_wake_mutex); + multiple_wake_cond.wait(lk); + ++multiple_wake_count; + } + +} + + +void do_test_multiple_notify_one_calls_wakes_multiple_threads() +{ + boost::thread thread1(&wait_for_condvar_and_increase_count); + boost::thread thread2(&wait_for_condvar_and_increase_count); + + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + multiple_wake_cond.notify_one(); + + boost::thread thread3(&wait_for_condvar_and_increase_count); + + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + multiple_wake_cond.notify_one(); + multiple_wake_cond.notify_one(); + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + + { + boost::unique_lock<boost::mutex> lk(multiple_wake_mutex); + BOOST_CHECK(multiple_wake_count==3); + } + + thread1.join(); + thread2.join(); + thread3.join(); +} + +BOOST_AUTO_TEST_CASE(test_condition_notify_one) +{ + timed_test(&do_test_condition_notify_one_wakes_from_wait, timeout_seconds, execution_monitor::use_mutex); + timed_test(&do_test_condition_notify_one_wakes_from_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex); + timed_test(&do_test_condition_notify_one_wakes_from_timed_wait, timeout_seconds, execution_monitor::use_mutex); + timed_test(&do_test_condition_notify_one_wakes_from_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex); + timed_test(&do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex); + timed_test(&do_test_multiple_notify_one_calls_wakes_multiple_threads, timeout_seconds, execution_monitor::use_mutex); +} diff --git a/src/boost/libs/thread/test/test_condition_timed_wait_times_out.cpp b/src/boost/libs/thread/test/test_condition_timed_wait_times_out.cpp new file mode 100644 index 000000000..8e19cd7bf --- /dev/null +++ b/src/boost/libs/thread/test/test_condition_timed_wait_times_out.cpp @@ -0,0 +1,169 @@ +// Copyright (C) 2007-8 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#define BOOST_TEST_MODULE Boost.Threads: condition_variable test suite + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/condition.hpp> +#include <boost/thread/thread_only.hpp> + +#include <boost/test/unit_test.hpp> +#include "./util.inl" + +bool fake_predicate() +{ + return false; +} + +unsigned const timeout_seconds=2; +unsigned const timeout_grace=1; +boost::posix_time::milliseconds const timeout_resolution(100); + + +void do_test_timed_wait_times_out() +{ + boost::condition_variable cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+delay; + + while(cond.timed_wait(lock,timeout)) {} + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_timed_wait_with_predicate_times_out() +{ + boost::condition_variable cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+delay; + + bool const res=cond.timed_wait(lock,timeout,fake_predicate); + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK(!res); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_relative_timed_wait_with_predicate_times_out() +{ + boost::condition_variable cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + + bool const res=cond.timed_wait(lock,delay,fake_predicate); + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK(!res); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_timed_wait_relative_times_out() +{ + boost::condition_variable cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + + while(cond.timed_wait(lock,delay)) {} + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_cv_any_timed_wait_times_out() +{ + boost::condition_variable_any cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+delay; + + while(cond.timed_wait(lock,timeout)) {} + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_cv_any_timed_wait_with_predicate_times_out() +{ + boost::condition_variable_any cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+delay; + + bool const res=cond.timed_wait(lock,timeout,fake_predicate); + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK(!res); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_cv_any_relative_timed_wait_with_predicate_times_out() +{ + boost::condition_variable_any cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + + bool const res=cond.timed_wait(lock,delay,fake_predicate); + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK(!res); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_cv_any_timed_wait_relative_times_out() +{ + boost::condition_variable_any cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + + while(cond.timed_wait(lock,delay)) {} + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + + +BOOST_AUTO_TEST_CASE(test_timed_wait_times_out) +{ + timed_test(&do_test_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_relative_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_cv_any_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_cv_any_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_cv_any_relative_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_cv_any_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); +} + + diff --git a/src/boost/libs/thread/test/test_futures.cpp b/src/boost/libs/thread/test/test_futures.cpp new file mode 100644 index 000000000..61515169d --- /dev/null +++ b/src/boost/libs/thread/test/test_futures.cpp @@ -0,0 +1,1236 @@ +// (C) Copyright 2008-10 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: futures test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/future.hpp> +#include <utility> +#include <memory> +#include <string> +#include <iostream> +#include <boost/thread/detail/log.hpp> + +#include <boost/test/unit_test.hpp> + +#ifdef BOOST_MSVC +# pragma warning(disable: 4267) // conversion from ... to ..., possible loss of data +#endif + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template<typename T> + typename boost::remove_reference<T>::type&& cast_to_rval(T&& t) + { + return static_cast<typename boost::remove_reference<T>::type&&>(t); + } +#else +#if defined BOOST_THREAD_USES_MOVE + template<typename T> + boost::rv<T>& cast_to_rval(T& t) + { + return boost::move(t); + } +#else + template<typename T> + boost::detail::thread_move_t<T> cast_to_rval(T& t) + { + return boost::move(t); + } +#endif +#endif + +struct X +{ +public: + int i; + + BOOST_THREAD_MOVABLE_ONLY(X) + X(): + i(42) + {} + X(BOOST_THREAD_RV_REF(X) other): + i(BOOST_THREAD_RV(other).i) + { + BOOST_THREAD_RV(other).i=0; + } + X& operator=(BOOST_THREAD_RV_REF(X) other) + { + i=BOOST_THREAD_RV(other).i; + BOOST_THREAD_RV(other).i=0; + return *this; + } + ~X() + {} +}; +namespace boost { + BOOST_THREAD_DCL_MOVABLE(X) +} + +int make_int() +{ + return 42; +} + +int throw_runtime_error() +{ + throw std::runtime_error("42"); +} + +void set_promise_thread(boost::promise<int>* p) +{ + p->set_value(42); +} + +struct my_exception +{}; + +void set_promise_exception_thread(boost::promise<int>* p) +{ + p->set_exception(boost::copy_exception(my_exception())); +} + + +BOOST_AUTO_TEST_CASE(test_store_value_from_thread) +{ + BOOST_DETAIL_THREAD_LOG; + try { + boost::promise<int> pi2; + BOOST_DETAIL_THREAD_LOG; + boost::unique_future<int> fi2(BOOST_THREAD_MAKE_RV_REF(pi2.get_future())); + BOOST_DETAIL_THREAD_LOG; + boost::thread(set_promise_thread,&pi2); + BOOST_DETAIL_THREAD_LOG; + int j=fi2.get(); + BOOST_DETAIL_THREAD_LOG; + BOOST_CHECK(j==42); + BOOST_DETAIL_THREAD_LOG; + BOOST_CHECK(fi2.is_ready()); + BOOST_DETAIL_THREAD_LOG; + BOOST_CHECK(fi2.has_value()); + BOOST_DETAIL_THREAD_LOG; + BOOST_CHECK(!fi2.has_exception()); + BOOST_DETAIL_THREAD_LOG; + BOOST_CHECK(fi2.get_state()==boost::future_state::ready); + BOOST_DETAIL_THREAD_LOG; + } + catch (...) + { + BOOST_CHECK(false&&"Exception thrown"); + } +} + +BOOST_AUTO_TEST_CASE(test_store_exception) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi3; + boost::unique_future<int> fi3(BOOST_THREAD_MAKE_RV_REF(pi3.get_future())); + boost::thread(set_promise_exception_thread,&pi3); + try + { + fi3.get(); + BOOST_CHECK(false); + } + catch(my_exception) + { + BOOST_CHECK(true); + } + + BOOST_CHECK(fi3.is_ready()); + BOOST_CHECK(!fi3.has_value()); + BOOST_CHECK(fi3.has_exception()); + BOOST_CHECK(fi3.get_state()==boost::future_state::ready); +} + +BOOST_AUTO_TEST_CASE(test_initial_state) +{ + BOOST_DETAIL_THREAD_LOG; + boost::unique_future<int> fi; + BOOST_CHECK(!fi.is_ready()); + BOOST_CHECK(!fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); + int i; + try + { + i=fi.get(); + (void)i; + BOOST_CHECK(false); + } + catch(boost::future_uninitialized) + { + BOOST_CHECK(true); + } +} + +BOOST_AUTO_TEST_CASE(test_waiting_future) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi; + boost::unique_future<int> fi; + fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); + + int i=0; + BOOST_CHECK(!fi.is_ready()); + BOOST_CHECK(!fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::waiting); + BOOST_CHECK(i==0); +} + +BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi; + BOOST_THREAD_MAKE_RV_REF(pi.get_future()); + + try + { + pi.get_future(); + BOOST_CHECK(false); + } + catch(boost::future_already_retrieved&) + { + BOOST_CHECK(true); + } +} + +BOOST_AUTO_TEST_CASE(test_set_value_updates_future_state) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi; + boost::unique_future<int> fi; + fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); + + pi.set_value(42); + + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); +} + +BOOST_AUTO_TEST_CASE(test_set_value_can_be_retrieved) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi; + boost::unique_future<int> fi; + fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); + + pi.set_value(42); + + int i=0; + BOOST_CHECK(i=fi.get()); + BOOST_CHECK(i==42); + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); +} + +BOOST_AUTO_TEST_CASE(test_set_value_can_be_moved) +{ + BOOST_DETAIL_THREAD_LOG; +// boost::promise<int> pi; +// boost::unique_future<int> fi; +// fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); + +// pi.set_value(42); + +// int i=0; +// BOOST_CHECK(i=fi.get()); +// BOOST_CHECK(i==42); +// BOOST_CHECK(fi.is_ready()); +// BOOST_CHECK(fi.has_value()); +// BOOST_CHECK(!fi.has_exception()); +// BOOST_CHECK(fi.get_state()==boost::future_state::ready); +} + +BOOST_AUTO_TEST_CASE(test_future_from_packaged_task_is_waiting) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + int i=0; + BOOST_CHECK(!fi.is_ready()); + BOOST_CHECK(!fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::waiting); + BOOST_CHECK(i==0); +} + +BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_populates_future) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt(); + + int i=0; + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); + BOOST_CHECK(i=fi.get()); + BOOST_CHECK(i==42); +} + +BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_twice_throws) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + + pt(); + try + { + pt(); + BOOST_CHECK(false); + } + catch(boost::task_already_started) + { + BOOST_CHECK(true); + } +} + + +BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice_from_task) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + pt.get_future(); + try + { + pt.get_future(); + BOOST_CHECK(false); + } + catch(boost::future_already_retrieved) + { + BOOST_CHECK(true); + } +} + +BOOST_AUTO_TEST_CASE(test_task_stores_exception_if_function_throws) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(throw_runtime_error); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt(); + + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(!fi.has_value()); + BOOST_CHECK(fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); + try + { + fi.get(); + BOOST_CHECK(false); + } + catch(std::exception&) + { + BOOST_CHECK(true); + } + catch(...) + { + BOOST_CHECK(!"Unknown exception thrown"); + } + +} + +BOOST_AUTO_TEST_CASE(test_void_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<void> p; + boost::unique_future<void> f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); + p.set_value(); + BOOST_CHECK(f.is_ready()); + BOOST_CHECK(f.has_value()); + BOOST_CHECK(!f.has_exception()); + BOOST_CHECK(f.get_state()==boost::future_state::ready); + f.get(); +} + +BOOST_AUTO_TEST_CASE(test_reference_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int&> p; + boost::unique_future<int&> f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); + int i=42; + p.set_value(i); + BOOST_CHECK(f.is_ready()); + BOOST_CHECK(f.has_value()); + BOOST_CHECK(!f.has_exception()); + BOOST_CHECK(f.get_state()==boost::future_state::ready); + BOOST_CHECK(&f.get()==&i); +} + +void do_nothing() +{} + +BOOST_AUTO_TEST_CASE(test_task_returning_void) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<void> pt(do_nothing); + boost::unique_future<void> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt(); + + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); +} + +int global_ref_target=0; + +int& return_ref() +{ + return global_ref_target; +} + +BOOST_AUTO_TEST_CASE(test_task_returning_reference) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int&> pt(return_ref); + boost::unique_future<int&> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt(); + + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); + int& i=fi.get(); + BOOST_CHECK(&i==&global_ref_target); +} + +BOOST_AUTO_TEST_CASE(test_shared_future) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi=pt.get_future(); + + boost::shared_future<int> sf(::cast_to_rval(fi)); + BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); + + pt(); + + int i=0; + BOOST_CHECK(sf.is_ready()); + BOOST_CHECK(sf.has_value()); + BOOST_CHECK(!sf.has_exception()); + BOOST_CHECK(sf.get_state()==boost::future_state::ready); + BOOST_CHECK(i=sf.get()); + BOOST_CHECK(i==42); +} + +BOOST_AUTO_TEST_CASE(test_copies_of_shared_future_become_ready_together) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + boost::shared_future<int> sf(::cast_to_rval(fi)); + boost::shared_future<int> sf2(sf); + boost::shared_future<int> sf3; + sf3=sf; + BOOST_CHECK(sf.get_state()==boost::future_state::waiting); + BOOST_CHECK(sf2.get_state()==boost::future_state::waiting); + BOOST_CHECK(sf3.get_state()==boost::future_state::waiting); + + pt(); + + int i=0; + BOOST_CHECK(sf.is_ready()); + BOOST_CHECK(sf.has_value()); + BOOST_CHECK(!sf.has_exception()); + BOOST_CHECK(sf.get_state()==boost::future_state::ready); + BOOST_CHECK(i=sf.get()); + BOOST_CHECK(i==42); + i=0; + BOOST_CHECK(sf2.is_ready()); + BOOST_CHECK(sf2.has_value()); + BOOST_CHECK(!sf2.has_exception()); + BOOST_CHECK(sf2.get_state()==boost::future_state::ready); + BOOST_CHECK(i=sf2.get()); + BOOST_CHECK(i==42); + i=0; + BOOST_CHECK(sf3.is_ready()); + BOOST_CHECK(sf3.has_value()); + BOOST_CHECK(!sf3.has_exception()); + BOOST_CHECK(sf3.get_state()==boost::future_state::ready); + BOOST_CHECK(i=sf3.get()); + BOOST_CHECK(i==42); +} + +BOOST_AUTO_TEST_CASE(test_shared_future_can_be_move_assigned_from_unique_future) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + boost::shared_future<int> sf; + sf=::cast_to_rval(fi); + BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); + + BOOST_CHECK(!sf.is_ready()); + BOOST_CHECK(!sf.has_value()); + BOOST_CHECK(!sf.has_exception()); + BOOST_CHECK(sf.get_state()==boost::future_state::waiting); +} + +BOOST_AUTO_TEST_CASE(test_shared_future_void) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<void> pt(do_nothing); + boost::unique_future<void> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + boost::shared_future<void> sf(::cast_to_rval(fi)); + BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); + + pt(); + + BOOST_CHECK(sf.is_ready()); + BOOST_CHECK(sf.has_value()); + BOOST_CHECK(!sf.has_exception()); + BOOST_CHECK(sf.get_state()==boost::future_state::ready); + sf.get(); +} + +BOOST_AUTO_TEST_CASE(test_shared_future_ref) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int&> p; + boost::shared_future<int&> f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); + int i=42; + p.set_value(i); + BOOST_CHECK(f.is_ready()); + BOOST_CHECK(f.has_value()); + BOOST_CHECK(!f.has_exception()); + BOOST_CHECK(f.get_state()==boost::future_state::ready); + BOOST_CHECK(&f.get()==&i); +} + +BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi; + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + + boost::promise<int> pi2(::cast_to_rval(pi)); + boost::unique_future<int> fi2(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + + pi2.set_value(3); + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(!fi2.is_ready()); + BOOST_CHECK(fi.get()==3); + pi.set_value(42); + BOOST_CHECK(fi2.is_ready()); + BOOST_CHECK(fi2.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_void_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<void> pi; + boost::unique_future<void> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + + boost::promise<void> pi2(::cast_to_rval(pi)); + boost::unique_future<void> fi2(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + + pi2.set_value(); + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(!fi2.is_ready()); + pi.set_value(); + BOOST_CHECK(fi2.is_ready()); +} + +BOOST_AUTO_TEST_CASE(test_unique_future_for_move_only_udt) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<X> pt; + boost::unique_future<X> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt.set_value(X()); + X res(fi.get()); + BOOST_CHECK(res.i==42); +} + +BOOST_AUTO_TEST_CASE(test_unique_future_for_string) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<std::string> pt; + boost::unique_future<std::string> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt.set_value(std::string("hello")); + std::string res(fi.get()); + BOOST_CHECK(res=="hello"); + + boost::promise<std::string> pt2; + fi=BOOST_THREAD_MAKE_RV_REF(pt2.get_future()); + + std::string const s="goodbye"; + + pt2.set_value(s); + res=fi.get(); + BOOST_CHECK(res=="goodbye"); + + boost::promise<std::string> pt3; + fi=BOOST_THREAD_MAKE_RV_REF(pt3.get_future()); + + std::string s2="foo"; + + pt3.set_value(s2); + res=fi.get(); + BOOST_CHECK(res=="foo"); +} + +boost::mutex callback_mutex; +unsigned callback_called=0; + +void wait_callback(boost::promise<int>& pi) +{ + boost::lock_guard<boost::mutex> lk(callback_mutex); + ++callback_called; + try + { + pi.set_value(42); + } + catch(...) + { + } +} + +void do_nothing_callback(boost::promise<int>& /*pi*/) +{ + boost::lock_guard<boost::mutex> lk(callback_mutex); + ++callback_called; +} + +BOOST_AUTO_TEST_CASE(test_wait_callback) +{ + BOOST_DETAIL_THREAD_LOG; + callback_called=0; + boost::promise<int> pi; + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + pi.set_wait_callback(wait_callback); + fi.wait(); + BOOST_CHECK(callback_called); + BOOST_CHECK(fi.get()==42); + fi.wait(); + fi.wait(); + BOOST_CHECK(callback_called==1); +} + +BOOST_AUTO_TEST_CASE(test_wait_callback_with_timed_wait) +{ + BOOST_DETAIL_THREAD_LOG; + callback_called=0; + boost::promise<int> pi; + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + pi.set_wait_callback(do_nothing_callback); + bool success=fi.timed_wait(boost::posix_time::milliseconds(10)); + BOOST_CHECK(callback_called); + BOOST_CHECK(!success); + success=fi.timed_wait(boost::posix_time::milliseconds(10)); + BOOST_CHECK(!success); + success=fi.timed_wait(boost::posix_time::milliseconds(10)); + BOOST_CHECK(!success); + BOOST_CHECK(callback_called==3); + pi.set_value(42); + success=fi.timed_wait(boost::posix_time::milliseconds(10)); + BOOST_CHECK(success); + BOOST_CHECK(callback_called==3); + BOOST_CHECK(fi.get()==42); + BOOST_CHECK(callback_called==3); +} + + +void wait_callback_for_task(boost::packaged_task<int>& pt) +{ + BOOST_DETAIL_THREAD_LOG; + boost::lock_guard<boost::mutex> lk(callback_mutex); + ++callback_called; + try + { + pt(); + } + catch(...) + { + } +} + + +BOOST_AUTO_TEST_CASE(test_wait_callback_for_packaged_task) +{ + BOOST_DETAIL_THREAD_LOG; + callback_called=0; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + pt.set_wait_callback(wait_callback_for_task); + fi.wait(); + BOOST_CHECK(callback_called); + BOOST_CHECK(fi.get()==42); + fi.wait(); + fi.wait(); + BOOST_CHECK(callback_called==1); +} + +BOOST_AUTO_TEST_CASE(test_packaged_task_can_be_moved) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + BOOST_CHECK(!fi.is_ready()); + + boost::packaged_task<int> pt2(::cast_to_rval(pt)); + + BOOST_CHECK(!fi.is_ready()); + try + { + pt(); + BOOST_CHECK(!"Can invoke moved task!"); + } + catch(boost::task_moved&) + { + } + + BOOST_CHECK(!fi.is_ready()); + + pt2(); + + BOOST_CHECK(fi.is_ready()); +} + +BOOST_AUTO_TEST_CASE(test_destroying_a_promise_stores_broken_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::unique_future<int> f; + + { + boost::promise<int> p; + f=BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + BOOST_CHECK(f.is_ready()); + BOOST_CHECK(f.has_exception()); + try + { + f.get(); + } + catch(boost::broken_promise&) + { + } +} + +BOOST_AUTO_TEST_CASE(test_destroying_a_packaged_task_stores_broken_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::unique_future<int> f; + + { + boost::packaged_task<int> p(make_int); + f=BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + BOOST_CHECK(f.is_ready()); + BOOST_CHECK(f.has_exception()); + try + { + f.get(); + } + catch(boost::broken_promise&) + { + } +} + +int make_int_slowly() +{ + boost::this_thread::sleep(boost::posix_time::seconds(1)); + return 42; +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_1) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + + boost::thread(::cast_to_rval(pt)); + + unsigned const future=boost::wait_for_any(f1,f2); + + BOOST_CHECK(future==0); + BOOST_CHECK(f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(f1.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_2) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + + boost::thread(::cast_to_rval(pt2)); + + unsigned const future=boost::wait_for_any(f1,f2); + + BOOST_CHECK(future==1); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(f2.is_ready()); + BOOST_CHECK(f2.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_1) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + + boost::thread(::cast_to_rval(pt)); + + unsigned const future=boost::wait_for_any(f1,f2,f3); + + BOOST_CHECK(future==0); + BOOST_CHECK(f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(f1.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_2) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + + boost::thread(::cast_to_rval(pt2)); + + unsigned const future=boost::wait_for_any(f1,f2,f3); + + BOOST_CHECK(future==1); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(f2.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_3) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + + boost::thread(::cast_to_rval(pt3)); + + unsigned const future=boost::wait_for_any(f1,f2,f3); + + BOOST_CHECK(future==2); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(f3.is_ready()); + BOOST_CHECK(f3.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_1) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + + boost::thread(::cast_to_rval(pt)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4); + + BOOST_CHECK(future==0); + BOOST_CHECK(f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(f1.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_2) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + + boost::thread(::cast_to_rval(pt2)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4); + + BOOST_CHECK(future==1); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(f2.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_3) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + + boost::thread(::cast_to_rval(pt3)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4); + + BOOST_CHECK(future==2); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(f3.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_4) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + + boost::thread(::cast_to_rval(pt4)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4); + + BOOST_CHECK(future==3); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(f4.is_ready()); + BOOST_CHECK(f4.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_1) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + boost::packaged_task<int> pt5(make_int_slowly); + boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); + + boost::thread(::cast_to_rval(pt)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); + + BOOST_CHECK(future==0); + BOOST_CHECK(f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(!f5.is_ready()); + BOOST_CHECK(f1.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_2) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + boost::packaged_task<int> pt5(make_int_slowly); + boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); + + boost::thread(::cast_to_rval(pt2)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); + + BOOST_CHECK(future==1); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(!f5.is_ready()); + BOOST_CHECK(f2.get()==42); +} +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_3) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + boost::packaged_task<int> pt5(make_int_slowly); + boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); + + boost::thread(::cast_to_rval(pt3)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); + + BOOST_CHECK(future==2); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(!f5.is_ready()); + BOOST_CHECK(f3.get()==42); +} +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_4) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + boost::packaged_task<int> pt5(make_int_slowly); + boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); + + boost::thread(::cast_to_rval(pt4)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); + + BOOST_CHECK(future==3); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(f4.is_ready()); + BOOST_CHECK(!f5.is_ready()); + BOOST_CHECK(f4.get()==42); +} +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_5) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + boost::packaged_task<int> pt5(make_int_slowly); + boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); + + boost::thread(::cast_to_rval(pt5)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); + + BOOST_CHECK(future==4); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(f5.is_ready()); + BOOST_CHECK(f5.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_invokes_callbacks) +{ + BOOST_DETAIL_THREAD_LOG; + callback_called=0; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> fi2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + pt.set_wait_callback(wait_callback_for_task); + + boost::thread(::cast_to_rval(pt)); + + boost::wait_for_any(fi,fi2); + BOOST_CHECK(callback_called==1); + BOOST_CHECK(fi.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_any_from_range) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=10; + for(unsigned i=0;i<count;++i) + { + boost::packaged_task<int> tasks[count]; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + tasks[j]=boost::packaged_task<int>(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(tasks[j].get_future()); + } + boost::thread(::cast_to_rval(tasks[i])); + + BOOST_CHECK(boost::wait_for_any(futures,futures)==futures); + + boost::unique_future<int>* const future=boost::wait_for_any(futures,futures+count); + + BOOST_CHECK(future==(futures+i)); + for(unsigned j=0;j<count;++j) + { + if(j!=i) + { + BOOST_CHECK(!futures[j].is_ready()); + } + else + { + BOOST_CHECK(futures[j].is_ready()); + } + } + BOOST_CHECK(futures[i].get()==42); + } +} + +BOOST_AUTO_TEST_CASE(test_wait_for_all_from_range) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=10; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + boost::packaged_task<int> task(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); + boost::thread(::cast_to_rval(task)); + } + + boost::wait_for_all(futures,futures+count); + + for(unsigned j=0;j<count;++j) + { + BOOST_CHECK(futures[j].is_ready()); + } +} + +BOOST_AUTO_TEST_CASE(test_wait_for_all_two_futures) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=2; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + boost::packaged_task<int> task(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); + boost::thread(::cast_to_rval(task)); + } + + boost::wait_for_all(futures[0],futures[1]); + + for(unsigned j=0;j<count;++j) + { + BOOST_CHECK(futures[j].is_ready()); + } +} + +BOOST_AUTO_TEST_CASE(test_wait_for_all_three_futures) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=3; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + boost::packaged_task<int> task(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); + boost::thread(::cast_to_rval(task)); + } + + boost::wait_for_all(futures[0],futures[1],futures[2]); + + for(unsigned j=0;j<count;++j) + { + BOOST_CHECK(futures[j].is_ready()); + } +} + +BOOST_AUTO_TEST_CASE(test_wait_for_all_four_futures) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=4; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + boost::packaged_task<int> task(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); + boost::thread(::cast_to_rval(task)); + } + + boost::wait_for_all(futures[0],futures[1],futures[2],futures[3]); + + for(unsigned j=0;j<count;++j) + { + BOOST_CHECK(futures[j].is_ready()); + } +} + +BOOST_AUTO_TEST_CASE(test_wait_for_all_five_futures) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=5; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + boost::packaged_task<int> task(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); + boost::thread(::cast_to_rval(task)); + } + + boost::wait_for_all(futures[0],futures[1],futures[2],futures[3],futures[4]); + + for(unsigned j=0;j<count;++j) + { + BOOST_CHECK(futures[j].is_ready()); + } +} diff --git a/src/boost/libs/thread/test/test_generic_locks.cpp b/src/boost/libs/thread/test/test_generic_locks.cpp new file mode 100644 index 000000000..0a9befcf9 --- /dev/null +++ b/src/boost/libs/thread/test/test_generic_locks.cpp @@ -0,0 +1,578 @@ +// (C) Copyright 2008 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#define BOOST_TEST_MODULE Boost.Threads: generic locks test suite + +#include <boost/test/unit_test.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/condition_variable.hpp> +#include <iterator> +#include <cstddef> + +BOOST_AUTO_TEST_CASE(test_lock_two_uncontended) +{ + boost::mutex m1,m2; + + boost::unique_lock<boost::mutex> l1(m1,boost::defer_lock), + l2(m2,boost::defer_lock); + + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); + + boost::lock(l1,l2); + + BOOST_CHECK(l1.owns_lock()); + BOOST_CHECK(l2.owns_lock()); +} + +struct wait_data +{ + boost::mutex m; + bool flag; + boost::condition_variable cond; + + wait_data(): + flag(false) + {} + + void wait() + { + boost::unique_lock<boost::mutex> l(m); + while(!flag) + { + cond.wait(l); + } + } + + template<typename Duration> + bool timed_wait(Duration d) + { + boost::system_time const target=boost::get_system_time()+d; + + boost::unique_lock<boost::mutex> l(m); + while(!flag) + { + if(!cond.timed_wait(l,target)) + { + return flag; + } + } + return true; + } + + void signal() + { + boost::unique_lock<boost::mutex> l(m); + flag=true; + cond.notify_all(); + } +}; + + +void lock_mutexes_slowly(boost::mutex* m1,boost::mutex* m2,wait_data* locked,wait_data* quit) +{ + boost::lock_guard<boost::mutex> l1(*m1); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard<boost::mutex> l2(*m2); + locked->signal(); + quit->wait(); +} + +void lock_pair(boost::mutex* m1,boost::mutex* m2) +{ + boost::lock(*m1,*m2); + boost::unique_lock<boost::mutex> l1(*m1,boost::adopt_lock), + l2(*m2,boost::adopt_lock); +} + +BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_order) +{ + boost::mutex m1,m2; + wait_data locked; + wait_data release; + + boost::thread t(lock_mutexes_slowly,&m1,&m2,&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_pair,&m1,&m2); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(1))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(1))); + + t.join(); +} + +BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_opposite_order) +{ + boost::mutex m1,m2; + wait_data locked; + wait_data release; + + boost::thread t(lock_mutexes_slowly,&m1,&m2,&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_pair,&m2,&m1); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(1))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(1))); + + t.join(); +} + +BOOST_AUTO_TEST_CASE(test_lock_five_uncontended) +{ + boost::mutex m1,m2,m3,m4,m5; + + boost::unique_lock<boost::mutex> l1(m1,boost::defer_lock), + l2(m2,boost::defer_lock), + l3(m3,boost::defer_lock), + l4(m4,boost::defer_lock), + l5(m5,boost::defer_lock); + + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); + BOOST_CHECK(!l3.owns_lock()); + BOOST_CHECK(!l4.owns_lock()); + BOOST_CHECK(!l5.owns_lock()); + + boost::lock(l1,l2,l3,l4,l5); + + BOOST_CHECK(l1.owns_lock()); + BOOST_CHECK(l2.owns_lock()); + BOOST_CHECK(l3.owns_lock()); + BOOST_CHECK(l4.owns_lock()); + BOOST_CHECK(l5.owns_lock()); +} + +void lock_five_mutexes_slowly(boost::mutex* m1,boost::mutex* m2,boost::mutex* m3,boost::mutex* m4,boost::mutex* m5, + wait_data* locked,wait_data* quit) +{ + boost::lock_guard<boost::mutex> l1(*m1); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard<boost::mutex> l2(*m2); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard<boost::mutex> l3(*m3); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard<boost::mutex> l4(*m4); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard<boost::mutex> l5(*m5); + locked->signal(); + quit->wait(); +} + +void lock_five(boost::mutex* m1,boost::mutex* m2,boost::mutex* m3,boost::mutex* m4,boost::mutex* m5) +{ + boost::lock(*m1,*m2,*m3,*m4,*m5); + m1->unlock(); + m2->unlock(); + m3->unlock(); + m4->unlock(); + m5->unlock(); +} + +BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_order) +{ + boost::mutex m1,m2,m3,m4,m5; + wait_data locked; + wait_data release; + + boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_five,&m1,&m2,&m3,&m4,&m5); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3))); + + t.join(); +} + +BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_different_order) +{ + boost::mutex m1,m2,m3,m4,m5; + wait_data locked; + wait_data release; + + boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_five,&m5,&m1,&m4,&m2,&m3); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3))); + + t.join(); +} + +void lock_n(boost::mutex* mutexes,unsigned count) +{ + boost::lock(mutexes,mutexes+count); + for(unsigned i=0;i<count;++i) + { + mutexes[i].unlock(); + } +} + + +BOOST_AUTO_TEST_CASE(test_lock_ten_other_thread_locks_in_different_order) +{ + unsigned const num_mutexes=10; + + boost::mutex mutexes[num_mutexes]; + wait_data locked; + wait_data release; + + boost::thread t(lock_five_mutexes_slowly,&mutexes[6],&mutexes[3],&mutexes[8],&mutexes[0],&mutexes[2],&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_n,mutexes,num_mutexes); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3))); + + t.join(); +} + +struct dummy_mutex +{ + bool is_locked; + + dummy_mutex(): + is_locked(false) + {} + + void lock() + { + is_locked=true; + } + + bool try_lock() + { + if(is_locked) + { + return false; + } + is_locked=true; + return true; + } + + void unlock() + { + is_locked=false; + } +}; + +namespace boost +{ + template<> + struct is_mutex_type<dummy_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +} + + + +BOOST_AUTO_TEST_CASE(test_lock_five_in_range) +{ + unsigned const num_mutexes=5; + dummy_mutex mutexes[num_mutexes]; + + boost::lock(mutexes,mutexes+num_mutexes); + + for(unsigned i=0;i<num_mutexes;++i) + { + BOOST_CHECK(mutexes[i].is_locked); + } +} + +class dummy_iterator +{ +private: + dummy_mutex* p; +public: + typedef std::forward_iterator_tag iterator_category; + typedef dummy_mutex value_type; + typedef std::ptrdiff_t difference_type; + typedef dummy_mutex* pointer; + typedef dummy_mutex& reference; + + explicit dummy_iterator(dummy_mutex* p_): + p(p_) + {} + + bool operator==(dummy_iterator const& other) const + { + return p==other.p; + } + + bool operator!=(dummy_iterator const& other) const + { + return p!=other.p; + } + + bool operator<(dummy_iterator const& other) const + { + return p<other.p; + } + + dummy_mutex& operator*() const + { + return *p; + } + + dummy_mutex* operator->() const + { + return p; + } + + dummy_iterator operator++(int) + { + dummy_iterator temp(*this); + ++p; + return temp; + } + + dummy_iterator& operator++() + { + ++p; + return *this; + } + +}; + + +BOOST_AUTO_TEST_CASE(test_lock_five_in_range_custom_iterator) +{ + unsigned const num_mutexes=5; + dummy_mutex mutexes[num_mutexes]; + + boost::lock(dummy_iterator(mutexes),dummy_iterator(mutexes+num_mutexes)); + + for(unsigned i=0;i<num_mutexes;++i) + { + BOOST_CHECK(mutexes[i].is_locked); + } +} + +class dummy_mutex2: + public dummy_mutex +{}; + + +BOOST_AUTO_TEST_CASE(test_lock_ten_in_range_inherited_mutex) +{ + unsigned const num_mutexes=10; + dummy_mutex2 mutexes[num_mutexes]; + + boost::lock(mutexes,mutexes+num_mutexes); + + for(unsigned i=0;i<num_mutexes;++i) + { + BOOST_CHECK(mutexes[i].is_locked); + } +} + +BOOST_AUTO_TEST_CASE(test_try_lock_two_uncontended) +{ + dummy_mutex m1,m2; + + int const res=boost::try_lock(m1,m2); + + BOOST_CHECK(res==-1); + BOOST_CHECK(m1.is_locked); + BOOST_CHECK(m2.is_locked); +} +BOOST_AUTO_TEST_CASE(test_try_lock_two_first_locked) +{ + dummy_mutex m1,m2; + m1.lock(); + + boost::unique_lock<dummy_mutex> l1(m1,boost::defer_lock), + l2(m2,boost::defer_lock); + + int const res=boost::try_lock(l1,l2); + + BOOST_CHECK(res==0); + BOOST_CHECK(m1.is_locked); + BOOST_CHECK(!m2.is_locked); + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); +} +BOOST_AUTO_TEST_CASE(test_try_lock_two_second_locked) +{ + dummy_mutex m1,m2; + m2.lock(); + + boost::unique_lock<dummy_mutex> l1(m1,boost::defer_lock), + l2(m2,boost::defer_lock); + + int const res=boost::try_lock(l1,l2); + + BOOST_CHECK(res==1); + BOOST_CHECK(!m1.is_locked); + BOOST_CHECK(m2.is_locked); + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); +} + +BOOST_AUTO_TEST_CASE(test_try_lock_three) +{ + int const num_mutexes=3; + + for(int i=-1;i<num_mutexes;++i) + { + dummy_mutex mutexes[num_mutexes]; + + if(i>=0) + { + mutexes[i].lock(); + } + boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock), + l2(mutexes[1],boost::defer_lock), + l3(mutexes[2],boost::defer_lock); + + int const res=boost::try_lock(l1,l2,l3); + + BOOST_CHECK(res==i); + for(int j=0;j<num_mutexes;++j) + { + if((i==j) || (i==-1)) + { + BOOST_CHECK(mutexes[j].is_locked); + } + else + { + BOOST_CHECK(!mutexes[j].is_locked); + } + } + if(i==-1) + { + BOOST_CHECK(l1.owns_lock()); + BOOST_CHECK(l2.owns_lock()); + BOOST_CHECK(l3.owns_lock()); + } + else + { + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); + BOOST_CHECK(!l3.owns_lock()); + } + } +} + +BOOST_AUTO_TEST_CASE(test_try_lock_four) +{ + int const num_mutexes=4; + + for(int i=-1;i<num_mutexes;++i) + { + dummy_mutex mutexes[num_mutexes]; + + if(i>=0) + { + mutexes[i].lock(); + } + boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock), + l2(mutexes[1],boost::defer_lock), + l3(mutexes[2],boost::defer_lock), + l4(mutexes[3],boost::defer_lock); + + int const res=boost::try_lock(l1,l2,l3,l4); + + BOOST_CHECK(res==i); + for(int j=0;j<num_mutexes;++j) + { + if((i==j) || (i==-1)) + { + BOOST_CHECK(mutexes[j].is_locked); + } + else + { + BOOST_CHECK(!mutexes[j].is_locked); + } + } + if(i==-1) + { + BOOST_CHECK(l1.owns_lock()); + BOOST_CHECK(l2.owns_lock()); + BOOST_CHECK(l3.owns_lock()); + BOOST_CHECK(l4.owns_lock()); + } + else + { + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); + BOOST_CHECK(!l3.owns_lock()); + BOOST_CHECK(!l4.owns_lock()); + } + } +} + +BOOST_AUTO_TEST_CASE(test_try_lock_five) +{ + int const num_mutexes=5; + + for(int i=-1;i<num_mutexes;++i) + { + dummy_mutex mutexes[num_mutexes]; + + if(i>=0) + { + mutexes[i].lock(); + } + boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock), + l2(mutexes[1],boost::defer_lock), + l3(mutexes[2],boost::defer_lock), + l4(mutexes[3],boost::defer_lock), + l5(mutexes[4],boost::defer_lock); + + int const res=boost::try_lock(l1,l2,l3,l4,l5); + + BOOST_CHECK(res==i); + for(int j=0;j<num_mutexes;++j) + { + if((i==j) || (i==-1)) + { + BOOST_CHECK(mutexes[j].is_locked); + } + else + { + BOOST_CHECK(!mutexes[j].is_locked); + } + } + if(i==-1) + { + BOOST_CHECK(l1.owns_lock()); + BOOST_CHECK(l2.owns_lock()); + BOOST_CHECK(l3.owns_lock()); + BOOST_CHECK(l4.owns_lock()); + BOOST_CHECK(l5.owns_lock()); + } + else + { + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); + BOOST_CHECK(!l3.owns_lock()); + BOOST_CHECK(!l4.owns_lock()); + BOOST_CHECK(!l5.owns_lock()); + } + } +} + diff --git a/src/boost/libs/thread/test/test_hardware_concurrency.cpp b/src/boost/libs/thread/test/test_hardware_concurrency.cpp new file mode 100644 index 000000000..1d4376c27 --- /dev/null +++ b/src/boost/libs/thread/test/test_hardware_concurrency.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE Boost.Threads: hardware_concurrency test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/thread/mutex.hpp> + +BOOST_AUTO_TEST_CASE(test_hardware_concurrency_is_non_zero) +{ + BOOST_CHECK(boost::thread::hardware_concurrency()!=0); +} + + diff --git a/src/boost/libs/thread/test/test_latch.cpp b/src/boost/libs/thread/test/test_latch.cpp new file mode 100644 index 000000000..e2972c9b1 --- /dev/null +++ b/src/boost/libs/thread/test/test_latch.cpp @@ -0,0 +1,70 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2013 Vicente J. Botet Escriba + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/latch.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <vector> + +namespace +{ + + // Shared variables for generation latch test + const int N_THREADS = 10; + boost::latch gen_latch(N_THREADS); + boost::mutex mutex; + long global_parameter; + + void latch_thread() + { + { + boost::unique_lock<boost::mutex> lock(mutex); + global_parameter++; + } + gen_latch.count_down(); + //do something else + } + +} // namespace + +void test_latch() +{ + boost::thread_group g; + global_parameter = 0; + + try + { + for (int i = 0; i < N_THREADS; ++i) + g.create_thread(&latch_thread); + + if (! gen_latch.try_wait()) + if (gen_latch.wait_for(boost::chrono::milliseconds(100)) == boost::cv_status::timeout) + if (gen_latch.wait_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(100)) == boost::cv_status::timeout) + gen_latch.wait(); // All the threads have been updated the global_parameter + BOOST_TEST_EQ(global_parameter, N_THREADS); + + g.join_all(); + } + catch (...) + { + BOOST_TEST(false); + g.interrupt_all(); + g.join_all(); + //throw; + } + +} + +int main() +{ + test_latch(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/test_lock_concept.cpp b/src/boost/libs/thread/test/test_lock_concept.cpp new file mode 100644 index 000000000..ba7de5cd6 --- /dev/null +++ b/src/boost/libs/thread/test/test_lock_concept.cpp @@ -0,0 +1,600 @@ +// (C) Copyright 2006-8 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: lock_concept test suite + +#include <boost/test/unit_test.hpp> +#include <boost/test/test_case_template.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/condition_variable.hpp> + +template<typename Mutex,typename Lock> +struct test_initially_locked +{ + void operator()() const + { + Mutex m; + Lock lock(m); + + BOOST_CHECK(lock); + BOOST_CHECK(lock.owns_lock()); + } +}; + +template<typename Mutex,typename Lock> +struct test_initially_unlocked_if_other_thread_has_lock +{ + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_initially_unlocked_if_other_thread_has_lock(): + done(false),locked(false) + {} + + void locking_thread() + { + Lock lock(m); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + bool is_done() const + { + return done; + } + + + void operator()() + { + Lock lock(m); + + typedef test_initially_unlocked_if_other_thread_has_lock<Mutex,Lock> this_type; + + boost::thread t(&this_type::locking_thread,this); + + try + { + { + boost::unique_lock<boost::mutex> lk(done_mutex); + BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2), + boost::bind(&this_type::is_done,this))); + BOOST_CHECK(!locked); + } + + lock.unlock(); + t.join(); + } + catch(...) + { + lock.unlock(); + t.join(); + throw; + } + } +}; + +template<typename Mutex,typename Lock> +struct test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock +{ + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock(): + done(false),locked(false) + {} + + void locking_thread() + { + Lock lock(m,boost::try_to_lock); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + bool is_done() const + { + return done; + } + + + void operator()() + { + boost::unique_lock<Mutex> lock(m); + + typedef test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,Lock> this_type; + + boost::thread t(&this_type::locking_thread,this); + + try + { + { + boost::unique_lock<boost::mutex> lk(done_mutex); + BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2), + boost::bind(&this_type::is_done,this))); + BOOST_CHECK(!locked); + } + + lock.unlock(); + t.join(); + } + catch(...) + { + lock.unlock(); + t.join(); + throw; + } + } +}; + +template<typename Mutex,typename Lock> +struct test_initially_locked_if_other_thread_has_shared_lock +{ + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_initially_locked_if_other_thread_has_shared_lock(): + done(false),locked(false) + {} + + void locking_thread() + { + Lock lock(m); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + bool is_done() const + { + return done; + } + + + void operator()() + { + boost::shared_lock<Mutex> lock(m); + + typedef test_initially_locked_if_other_thread_has_shared_lock<Mutex,Lock> this_type; + + boost::thread t(&this_type::locking_thread,this); + + try + { + { + boost::unique_lock<boost::mutex> lk(done_mutex); + BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2), + boost::bind(&this_type::is_done,this))); + BOOST_CHECK(locked); + } + + lock.unlock(); + t.join(); + } + catch(...) + { + lock.unlock(); + t.join(); + throw; + } + } +}; + +template<typename Mutex,typename Lock> +struct test_initially_unlocked_with_defer_lock_parameter +{ + void operator()() const + { + Mutex m; + Lock lock(m,boost::defer_lock); + + BOOST_CHECK(!lock); + BOOST_CHECK(!lock.owns_lock()); + } +}; + +template<typename Mutex,typename Lock> +struct test_initially_locked_with_adopt_lock_parameter +{ + void operator()() const + { + Mutex m; + m.lock(); + Lock lock(m,boost::adopt_lock); + + BOOST_CHECK(lock); + BOOST_CHECK(lock.owns_lock()); + } +}; +template<typename Mutex,typename Lock> +struct test_initially_lock_shared_with_adopt_lock_parameter +{ + void operator()() const + { + Mutex m; + m.lock_shared(); + Lock lock(m,boost::adopt_lock); + + BOOST_CHECK(lock); + BOOST_CHECK(lock.owns_lock()); + } +}; + + +template<typename Mutex,typename Lock> +struct test_unlocked_after_unlock_called +{ + void operator()() const + { + Mutex m; + Lock lock(m); + lock.unlock(); + BOOST_CHECK(!lock); + BOOST_CHECK(!lock.owns_lock()); + } +}; + +template<typename Mutex,typename Lock> +struct test_locked_after_lock_called +{ + void operator()() const + { + Mutex m; + Lock lock(m,boost::defer_lock); + lock.lock(); + BOOST_CHECK(lock); + BOOST_CHECK(lock.owns_lock()); + } +}; + +template<typename Mutex,typename Lock> +struct test_locked_after_try_lock_called +{ + void operator()() const + { + Mutex m; + Lock lock(m,boost::defer_lock); + lock.try_lock(); + BOOST_CHECK(lock); + BOOST_CHECK(lock.owns_lock()); + } +}; + +template<typename Mutex,typename Lock> +struct test_unlocked_after_try_lock_if_other_thread_has_lock +{ + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_unlocked_after_try_lock_if_other_thread_has_lock(): + done(false),locked(false) + {} + + void locking_thread() + { + Lock lock(m,boost::defer_lock); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + bool is_done() const + { + return done; + } + + + void operator()() + { + Lock lock(m); + + typedef test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock> this_type; + + boost::thread t(&this_type::locking_thread,this); + + try + { + { + boost::unique_lock<boost::mutex> lk(done_mutex); + BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2), + boost::bind(&this_type::is_done,this))); + BOOST_CHECK(!locked); + } + + lock.unlock(); + t.join(); + } + catch(...) + { + lock.unlock(); + t.join(); + throw; + } + } +}; + +template<typename Mutex,typename Lock> +struct test_throws_if_lock_called_when_already_locked +{ + void operator()() const + { + Mutex m; + Lock lock(m); + + BOOST_CHECK_THROW( lock.lock(), boost::lock_error ); + } +}; + +template<typename Mutex,typename Lock> +struct test_throws_if_try_lock_called_when_already_locked +{ + void operator()() const + { + Mutex m; + Lock lock(m); + + BOOST_CHECK_THROW( lock.try_lock(), boost::lock_error ); + } +}; + +template<typename Mutex,typename Lock> +struct test_throws_if_unlock_called_when_already_unlocked +{ + void operator()() const + { + Mutex m; + Lock lock(m); + lock.unlock(); + + BOOST_CHECK_THROW( lock.unlock(), boost::lock_error ); + } +}; +template<typename Lock> +struct test_default_constructed_has_no_mutex_and_unlocked +{ + void operator()() const + { + Lock l; + BOOST_CHECK(!l.mutex()); + BOOST_CHECK(!l.owns_lock()); + } +}; + + +template<typename Mutex,typename Lock> +struct test_locks_can_be_swapped +{ + void operator()() const + { + Mutex m1; + Mutex m2; + Mutex m3; + + Lock l1(m1); + Lock l2(m2); + + BOOST_CHECK_EQUAL(l1.mutex(),&m1); + BOOST_CHECK_EQUAL(l2.mutex(),&m2); + + l1.swap(l2); + + BOOST_CHECK_EQUAL(l1.mutex(),&m2); + BOOST_CHECK_EQUAL(l2.mutex(),&m1); + + swap(l1,l2); + + BOOST_CHECK_EQUAL(l1.mutex(),&m1); + BOOST_CHECK_EQUAL(l2.mutex(),&m2); + +#if 0 + l1.swap(Lock(m3)); + + BOOST_CHECK_EQUAL(l1.mutex(),&m3); +#endif + + } +}; + +template<typename Mutex,typename Lock> +void test_lock_is_scoped_lock_concept_for_mutex() +{ + test_default_constructed_has_no_mutex_and_unlocked<Lock>()(); + test_initially_locked<Mutex,Lock>()(); + test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()(); + test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()(); + test_unlocked_after_unlock_called<Mutex,Lock>()(); + test_locked_after_lock_called<Mutex,Lock>()(); + test_throws_if_lock_called_when_already_locked<Mutex,Lock>()(); + test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()(); + test_locks_can_be_swapped<Mutex,Lock>()(); + test_locked_after_try_lock_called<Mutex,Lock>()(); + test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()(); + test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()(); +} + +typedef boost::mpl::vector<boost::mutex,boost::timed_mutex, + boost::recursive_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock; + +BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_lock_concept,Mutex,mutex_types_with_scoped_lock) +{ + typedef typename Mutex::scoped_lock Lock; + + test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>(); +} + +typedef boost::mpl::vector<boost::mutex,boost::timed_mutex, + boost::recursive_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types; + +BOOST_AUTO_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,Mutex,all_mutex_types) +{ + typedef boost::unique_lock<Mutex> Lock; + + test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>(); +} + +typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex, + boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock; + +BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,Mutex,mutex_types_with_scoped_try_lock) +{ + typedef typename Mutex::scoped_try_lock Lock; + + test_default_constructed_has_no_mutex_and_unlocked<Lock>()(); + test_initially_locked<Mutex,Lock>()(); + test_initially_unlocked_if_other_thread_has_lock<Mutex,Lock>()(); + test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()(); + test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()(); + test_unlocked_after_unlock_called<Mutex,Lock>()(); + test_locked_after_lock_called<Mutex,Lock>()(); + test_locked_after_try_lock_called<Mutex,Lock>()(); + test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()(); + test_throws_if_lock_called_when_already_locked<Mutex,Lock>()(); + test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()(); + test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()(); + test_locks_can_be_swapped<Mutex,Lock>()(); +} + +struct dummy_shared_mutex +{ + bool locked; + bool shared_locked; + bool shared_unlocked; + bool shared_timed_locked_relative; + bool shared_timed_locked_absolute; + bool timed_locked_relative; + bool timed_locked_absolute; + + dummy_shared_mutex(): + locked(false),shared_locked(false),shared_unlocked(false), + shared_timed_locked_relative(false), + shared_timed_locked_absolute(false), + timed_locked_relative(false), + timed_locked_absolute(false) + {} + + void lock() + { + locked=true; + } + + void lock_shared() + { + shared_locked=true; + } + + void unlock() + {} + + void unlock_shared() + { + shared_unlocked=true; + } + + bool timed_lock_shared(boost::system_time) + { + shared_timed_locked_absolute=true; + return false; + } + template<typename Duration> + bool timed_lock_shared(Duration) + { + shared_timed_locked_relative=true; + return false; + } + bool timed_lock(boost::system_time) + { + timed_locked_absolute=true; + return false; + } + template<typename Duration> + bool timed_lock(Duration) + { + timed_locked_relative=true; + return false; + } + +}; + + +BOOST_AUTO_TEST_CASE(test_shared_lock) +{ + typedef boost::shared_mutex Mutex; + typedef boost::shared_lock<Mutex> Lock; + + test_default_constructed_has_no_mutex_and_unlocked<Lock>()(); + test_initially_locked<Mutex,Lock>()(); + test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,Lock>()(); + test_initially_locked_if_other_thread_has_shared_lock<Mutex,Lock>()(); + test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()(); + test_initially_lock_shared_with_adopt_lock_parameter<Mutex,Lock>()(); + test_unlocked_after_unlock_called<Mutex,Lock>()(); + test_locked_after_lock_called<Mutex,Lock>()(); + test_locked_after_try_lock_called<Mutex,Lock>()(); + test_throws_if_lock_called_when_already_locked<Mutex,Lock>()(); + test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()(); + test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()(); + test_locks_can_be_swapped<Mutex,Lock>()(); + + dummy_shared_mutex dummy; + boost::shared_lock<dummy_shared_mutex> lk(dummy); + BOOST_CHECK(dummy.shared_locked); + lk.unlock(); + BOOST_CHECK(dummy.shared_unlocked); + lk.timed_lock(boost::posix_time::milliseconds(5)); + BOOST_CHECK(dummy.shared_timed_locked_relative); + lk.timed_lock(boost::get_system_time()); + BOOST_CHECK(dummy.shared_timed_locked_absolute); +} + +//boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) +//{ +// boost::unit_test::test_suite* test = +// BOOST_TEST_SUITE("Boost.Threads: lock concept test suite"); +// +// typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex, +// boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock; +// +// test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types_with_scoped_lock)); +// +// typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex, +// boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock; +// +// test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,mutex_types_with_scoped_try_lock)); +// +// typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex, +// boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types; +// +// test->add(BOOST_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,all_mutex_types)); +// test->add(BOOST_TEST_CASE(&test_shared_lock)); +// +// return test; +//} + diff --git a/src/boost/libs/thread/test/test_ml.cpp b/src/boost/libs/thread/test/test_ml.cpp new file mode 100644 index 000000000..61b7eff56 --- /dev/null +++ b/src/boost/libs/thread/test/test_ml.cpp @@ -0,0 +1,201 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/config.hpp> +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +#include <boost/detail/lightweight_test.hpp> +#include <boost/thread/future.hpp> +#include <boost/utility/result_of.hpp> +#include <functional> + +struct async_func { + virtual ~async_func() { } + virtual void run() =0; + }; + +template <typename Ret> +class async_func_pt : public async_func { + boost::packaged_task<Ret> f; +public: + void run() { + std::cout << __FILE__ << ":" << __LINE__ << std::endl; +f(); } + async_func_pt (boost::packaged_task<Ret>&& f) : f(boost::move(f)) {} + ~async_func_pt() { } + boost::unique_future<Ret> get_future() { return f.get_future(); } + }; + +void async_core (async_func* p) { + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + p->run(); +} + + + + +template <typename F> +boost::unique_future<typename boost::result_of< F() >::type> +async (F&& f) + { + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + typedef typename boost::result_of< F() >::type RetType; + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + async_func_pt<RetType>* p= new async_func_pt<RetType> (boost::packaged_task<RetType>(boost::forward<F>(f))); + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + boost::unique_future<RetType> future_result= p->get_future(); + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + async_core (p); + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + return boost::move(future_result); + } + +template <typename F, typename A1> +boost::unique_future<typename boost::result_of< F(A1) >::type> +async (F&& f, A1&& a1) + { + std::cout << __FILE__ << ":" << __LINE__ << std::endl; +// This should be all it needs. But get a funny error deep inside Boost. +// problem overloading with && ? + return async (boost::bind(f,a1)); + } + + +int calculate_the_answer_to_life_the_universe_and_everything() +{ + return 42; +} + + +size_t foo (const std::string& s) + { + return s.size(); + } + + + +void test1() +{ +// this one works + // most fundimental form: + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + boost::unique_future<int> fi= async (&calculate_the_answer_to_life_the_universe_and_everything); + int i= fi.get(); + BOOST_TEST (i== 42); + + +// This one chokes at compile time + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + boost::unique_future<size_t> fut_1= async (&foo, "Life"); + + BOOST_TEST (fut_1.get()== 4); +} + +int main() +{ + test1(); + return boost::report_errors(); + +} + +#else +int main() +{ + return 0; +} + +#endif +/* + * + "/Users/viboes/clang/llvmCore-3.0-rc1.install/bin/clang++" + -o "../../../bin.v2/libs/thread/test/test_ml.test/clang-darwin-3.0x/debug/threading-multi/test_ml" + "../../../bin.v2/libs/thread/test/test_ml.test/clang-darwin-3.0x/debug/threading-multi/test_ml.o" + "../../../bin.v2/libs/test/build/clang-darwin-3.0x/debug/link-static/threading-multi/libboost_unit_test_framework.a" + "../../../bin.v2/libs/thread/build/clang-darwin-3.0x/debug/threading-multi/libboost_thread.dylib" + "../../../bin.v2/libs/chrono/build/clang-darwin-3.0x/debug/threading-multi/libboost_chrono.dylib" + "../../../bin.v2/libs/system/build/clang-darwin-3.0x/debug/threading-multi/libboost_system.dylib" -g +*/ + + +/* + * + * #include <boost/test/unit_test.hpp> +#include <boost/thread/future.hpp> +#include <boost/utility/result_of.hpp> +#include <functional> + +struct async_func { + virtual ~async_func() { } + virtual void run() =0; + }; + +template <typename Ret> +class async_func_pt : public async_func { + boost::packaged_task<Ret> f; +public: + void run() override { f(); } + async_func_pt (boost::packaged_task<Ret>&& f) : f(std::move(f)) {} + ~async_func_pt() { } + boost::unique_future<Ret> get_future() { return f.get_future(); } + }; + +void async_core (async_func* p); + + + + +template <typename F> +boost::unique_future<typename boost::result_of< F() >::type> +async (F&& f) + { + typedef typename boost::result_of< F() >::type RetType; + async_func_pt<RetType>* p= new async_func_pt<RetType> (boost::packaged_task<RetType>(f)); + boost::unique_future<RetType> future_result= p->get_future(); + async_core (p); + return std::move(future_result); + } + +template <typename F, typename A1> +boost::unique_future<typename boost::result_of< F(A1) >::type> +async (F&& f, A1&& a1) + { +// This should be all it needs. But get a funny error deep inside Boost. +// problem overloading with && ? + return async (std::tr1::bind(f,a1)); + } + +BOOST_AUTO_TEST_SUITE(thread_pool_tests) + +int calculate_the_answer_to_life_the_universe_and_everything() +{ + return 42; +} + + +size_t foo (const std::string& s) + { + return s.size(); + } + + + +BOOST_AUTO_TEST_CASE( async_test ) +{ +// this one works + // most fundimental form: + boost::unique_future<int> fi= async (&calculate_the_answer_to_life_the_universe_and_everything); + int i= fi.get(); + BOOST_CHECK_EQUAL (i, 42); + + +// This one chokes at compile time + boost::unique_future<size_t> fut_1= async (&foo, "Life"); + + BOOST_CHECK_EQUAL (fut_1.get(), 4); +} + + +BOOST_AUTO_TEST_SUITE_END() + */ diff --git a/src/boost/libs/thread/test/test_ml2.cpp b/src/boost/libs/thread/test/test_ml2.cpp new file mode 100644 index 000000000..86ff65738 --- /dev/null +++ b/src/boost/libs/thread/test/test_ml2.cpp @@ -0,0 +1,60 @@ +// Copyright (C) 2010 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 4 + +#include <cassert> +#include <vector> +#include <future> +#include <functional> +#include <boost/thread/future.hpp> + + +int TRUC = 42; +int main() +{ + std::vector< std::function<void()> > work_queue; + + auto do_some_work = [&]()-> boost::future<int*> + { + auto promise = std::make_shared<boost::promise<int*>>(); +#if 0 + work_queue.push_back( [=] + { + promise->set_value( &TRUC ); + }); +#else + auto inner = [=]() + { + promise->set_value( &TRUC ); + }; + work_queue.push_back(inner); + +#endif + + return promise->get_future(); + + }; + + auto ft_value = do_some_work(); + + while( !work_queue.empty() ) + { +#if 0 + auto work = work_queue.back(); +#else + std::function<void()> work; + work = work_queue.back(); +#endif + work_queue.pop_back(); + work(); + } + + auto value = ft_value.get(); + assert( value == &TRUC ); + return 0; +} + + diff --git a/src/boost/libs/thread/test/test_move_function.cpp b/src/boost/libs/thread/test/test_move_function.cpp new file mode 100644 index 000000000..6922fbe64 --- /dev/null +++ b/src/boost/libs/thread/test/test_move_function.cpp @@ -0,0 +1,134 @@ +// Copyright (C) 2007-8 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: move function test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/shared_ptr.hpp> + +void do_nothing() +{} + +BOOST_AUTO_TEST_CASE(test_thread_move_from_lvalue_on_construction) +{ + boost::thread src(&do_nothing); + boost::thread::id src_id=src.get_id(); + boost::thread dest(boost::move(src)); + boost::thread::id dest_id=dest.get_id(); + BOOST_CHECK(src_id==dest_id); + BOOST_CHECK(src.get_id()==boost::thread::id()); + dest.join(); +} + +BOOST_AUTO_TEST_CASE(test_thread_move_from_lvalue_on_assignment) +{ + boost::thread src(&do_nothing); + boost::thread::id src_id=src.get_id(); + boost::thread dest; + dest=boost::move(src); + boost::thread::id dest_id=dest.get_id(); + BOOST_CHECK(src_id==dest_id); + BOOST_CHECK(src.get_id()==boost::thread::id()); + dest.join(); +} + +boost::thread start_thread() +{ + return boost::thread(&do_nothing); +} + +BOOST_AUTO_TEST_CASE(test_thread_move_from_rvalue_on_construction) +{ + boost::thread x(start_thread()); + BOOST_CHECK(x.get_id()!=boost::thread::id()); + x.join(); +} + +BOOST_AUTO_TEST_CASE(test_thread_move_from_rvalue_using_explicit_move) +{ + //boost::thread x(boost::move(start_thread())); + boost::thread x=start_thread(); + BOOST_CHECK(x.get_id()!=boost::thread::id()); + x.join(); +} + +BOOST_AUTO_TEST_CASE(test_unique_lock_move_from_lvalue_on_construction) +{ + boost::mutex m; + boost::unique_lock<boost::mutex> l(m); + BOOST_CHECK(l.owns_lock()); + BOOST_CHECK(l.mutex()==&m); + + boost::unique_lock<boost::mutex> l2(boost::move(l)); + BOOST_CHECK(!l.owns_lock()); + BOOST_CHECK(!l.mutex()); + BOOST_CHECK(l2.owns_lock()); + BOOST_CHECK(l2.mutex()==&m); +} + +boost::unique_lock<boost::mutex> get_lock(boost::mutex& m) +{ + return boost::unique_lock<boost::mutex>(m); +} + + +BOOST_AUTO_TEST_CASE(test_unique_lock_move_from_rvalue_on_construction) +{ + boost::mutex m; + boost::unique_lock<boost::mutex> l(get_lock(m)); + BOOST_CHECK(l.owns_lock()); + BOOST_CHECK(l.mutex()==&m); +} + +namespace user_test_ns +{ + template<typename T> + T move(T& t) + { + return t.move(); + } + + bool move_called=false; + + struct nc: + public boost::shared_ptr<int> + { +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + nc() {} + nc(nc&&) + { + move_called=true; + } +#endif + nc move() + { + move_called=true; + return nc(); + } + }; +} + +namespace boost +{ + BOOST_THREAD_DCL_MOVABLE(user_test_ns::nc) +} + +BOOST_AUTO_TEST_CASE(test_move_for_user_defined_type_unaffected) +{ + user_test_ns::nc src; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + user_test_ns::nc dest=boost::move(src); +#else + user_test_ns::nc dest=move(src); +#endif + BOOST_CHECK(user_test_ns::move_called); +} + + + + diff --git a/src/boost/libs/thread/test/test_mutex.cpp b/src/boost/libs/thread/test/test_mutex.cpp new file mode 100644 index 000000000..e6ac24e27 --- /dev/null +++ b/src/boost/libs/thread/test/test_mutex.cpp @@ -0,0 +1,341 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: mutex test suite + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread_time.hpp> +#include <boost/thread/condition.hpp> + +#define BOOST_TEST_MODULE Boost.Threads: mutex test suite + +#include <boost/test/unit_test.hpp> + +#define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only +#include "./util.inl" + +template <typename M> +struct test_lock +{ + typedef M mutex_type; + typedef typename M::scoped_lock lock_type; + + void operator()() + { + mutex_type mutex; + boost::condition condition; + + // Test the lock's constructors. + { + lock_type lock(mutex, boost::defer_lock); + BOOST_CHECK(!lock); + } + lock_type lock(mutex); + BOOST_CHECK(lock ? true : false); + + // Construct and initialize an xtime for a fast time out. + boost::xtime xt = delay(0, 100); + + // Test the lock and the mutex with condition variables. + // No one is going to notify this condition variable. We expect to + // time out. + BOOST_CHECK(!condition.timed_wait(lock, xt)); + BOOST_CHECK(lock ? true : false); + + // Test the lock and unlock methods. + lock.unlock(); + BOOST_CHECK(!lock); + lock.lock(); + BOOST_CHECK(lock ? true : false); + } +}; + +template <typename M> +struct test_trylock +{ + typedef M mutex_type; + typedef typename M::scoped_try_lock try_lock_type; + + void operator()() + { + mutex_type mutex; + boost::condition condition; + + // Test the lock's constructors. + { + try_lock_type lock(mutex); + BOOST_CHECK(lock ? true : false); + } + { + try_lock_type lock(mutex, boost::defer_lock); + BOOST_CHECK(!lock); + } + try_lock_type lock(mutex); + BOOST_CHECK(lock ? true : false); + + // Construct and initialize an xtime for a fast time out. + boost::xtime xt = delay(0, 100); + + // Test the lock and the mutex with condition variables. + // No one is going to notify this condition variable. We expect to + // time out. + BOOST_CHECK(!condition.timed_wait(lock, xt)); + BOOST_CHECK(lock ? true : false); + + // Test the lock, unlock and trylock methods. + lock.unlock(); + BOOST_CHECK(!lock); + lock.lock(); + BOOST_CHECK(lock ? true : false); + lock.unlock(); + BOOST_CHECK(!lock); + BOOST_CHECK(lock.try_lock()); + BOOST_CHECK(lock ? true : false); + } +}; + +template<typename Mutex> +struct test_lock_times_out_if_other_thread_has_lock +{ + typedef boost::unique_lock<Mutex> Lock; + + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_lock_times_out_if_other_thread_has_lock(): + done(false),locked(false) + {} + + void locking_thread() + { + Lock lock(m,boost::defer_lock); + lock.timed_lock(boost::posix_time::milliseconds(50)); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + void locking_thread_through_constructor() + { + Lock lock(m,boost::posix_time::milliseconds(50)); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + bool is_done() const + { + return done; + } + + typedef test_lock_times_out_if_other_thread_has_lock<Mutex> this_type; + + void do_test(void (this_type::*test_func)()) + { + Lock lock(m); + + locked=false; + done=false; + + boost::thread t(test_func,this); + + try + { + { + boost::unique_lock<boost::mutex> lk(done_mutex); + BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2), + boost::bind(&this_type::is_done,this))); + BOOST_CHECK(!locked); + } + + lock.unlock(); + t.join(); + } + catch(...) + { + lock.unlock(); + t.join(); + throw; + } + } + + + void operator()() + { + do_test(&this_type::locking_thread); + do_test(&this_type::locking_thread_through_constructor); + } +}; + +template <typename M> +struct test_timedlock +{ + typedef M mutex_type; + typedef typename M::scoped_timed_lock timed_lock_type; + + static bool fake_predicate() + { + return false; + } + + void operator()() + { + test_lock_times_out_if_other_thread_has_lock<mutex_type>()(); + + mutex_type mutex; + boost::condition condition; + + // Test the lock's constructors. + { + // Construct and initialize an xtime for a fast time out. + boost::system_time xt = boost::get_system_time()+boost::posix_time::milliseconds(100); + + timed_lock_type lock(mutex, xt); + BOOST_CHECK(lock ? true : false); + } + { + timed_lock_type lock(mutex, boost::defer_lock); + BOOST_CHECK(!lock); + } + timed_lock_type lock(mutex); + BOOST_CHECK(lock ? true : false); + + // Construct and initialize an xtime for a fast time out. + boost::system_time timeout = boost::get_system_time()+boost::posix_time::milliseconds(100); + + // Test the lock and the mutex with condition variables. + // No one is going to notify this condition variable. We expect to + // time out. + BOOST_CHECK(!condition.timed_wait(lock, timeout, fake_predicate)); + BOOST_CHECK(lock ? true : false); + + boost::system_time now=boost::get_system_time(); + boost::posix_time::milliseconds const timeout_resolution(20); + BOOST_CHECK((timeout-timeout_resolution)<now); + + // Test the lock, unlock and timedlock methods. + lock.unlock(); + BOOST_CHECK(!lock); + lock.lock(); + BOOST_CHECK(lock ? true : false); + lock.unlock(); + BOOST_CHECK(!lock); + boost::system_time target = boost::get_system_time()+boost::posix_time::milliseconds(100); + BOOST_CHECK(lock.timed_lock(target)); + BOOST_CHECK(lock ? true : false); + lock.unlock(); + BOOST_CHECK(!lock); + + BOOST_CHECK(mutex.timed_lock(boost::posix_time::milliseconds(100))); + mutex.unlock(); + + BOOST_CHECK(lock.timed_lock(boost::posix_time::milliseconds(100))); + BOOST_CHECK(lock ? true : false); + lock.unlock(); + BOOST_CHECK(!lock); + + } +}; + +template <typename M> +struct test_recursive_lock +{ + typedef M mutex_type; + typedef typename M::scoped_lock lock_type; + + void operator()() + { + mutex_type mx; + lock_type lock1(mx); + lock_type lock2(mx); + } +}; + + +void do_test_mutex() +{ + test_lock<boost::mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_mutex) +{ + timed_test(&do_test_mutex, 3); +} + +void do_test_try_mutex() +{ + test_lock<boost::try_mutex>()(); + test_trylock<boost::try_mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_try_mutex) +{ + timed_test(&do_test_try_mutex, 3); +} + +void do_test_timed_mutex() +{ + test_lock<boost::timed_mutex>()(); + test_trylock<boost::timed_mutex>()(); + test_timedlock<boost::timed_mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_timed_mutex) +{ + timed_test(&do_test_timed_mutex, 3); +} + +void do_test_recursive_mutex() +{ + test_lock<boost::recursive_mutex>()(); + test_recursive_lock<boost::recursive_mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_recursive_mutex) +{ + timed_test(&do_test_recursive_mutex, 3); +} + +void do_test_recursive_try_mutex() +{ + test_lock<boost::recursive_try_mutex>()(); + test_trylock<boost::recursive_try_mutex>()(); + test_recursive_lock<boost::recursive_try_mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_recursive_try_mutex) +{ + timed_test(&do_test_recursive_try_mutex, 3); +} + +void do_test_recursive_timed_mutex() +{ + test_lock<boost::recursive_timed_mutex>()(); + test_trylock<boost::recursive_timed_mutex>()(); + test_timedlock<boost::recursive_timed_mutex>()(); + test_recursive_lock<boost::recursive_timed_mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_recursive_timed_mutex) +{ + timed_test(&do_test_recursive_timed_mutex, 3); +} + + + diff --git a/src/boost/libs/thread/test/test_once.cpp b/src/boost/libs/thread/test/test_once.cpp new file mode 100644 index 000000000..3103f1c23 --- /dev/null +++ b/src/boost/libs/thread/test/test_once.cpp @@ -0,0 +1,192 @@ +// (C) Copyright 2006-7 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +#define BOOST_TEST_MODULE Boost.Threads: once test suite + +#include <boost/test/unit_test.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/once.hpp> +#include <iostream> + +#include <boost/thread/detail/log.hpp> + +boost::once_flag flag=BOOST_ONCE_INIT; +int var_to_init=0; +boost::mutex m; + +void initialize_variable() +{ + // ensure that if multiple threads get in here, they are serialized, so we can see the effect + boost::unique_lock<boost::mutex> lock(m); + ++var_to_init; +} + + +void call_once_thread() +{ + unsigned const loop_count=100; + int my_once_value=0; + for(unsigned i=0;i<loop_count;++i) + { + boost::call_once(flag, &initialize_variable); + my_once_value=var_to_init; + if(my_once_value!=1) + { + break; + } + } + boost::unique_lock<boost::mutex> lock(m); + BOOST_CHECK_EQUAL(my_once_value, 1); +} + +BOOST_AUTO_TEST_CASE(test_call_once) +{ + BOOST_DETAIL_THREAD_LOG; + + unsigned const num_threads=20; + boost::thread_group group; + + try + { + for(unsigned i=0;i<num_threads;++i) + { + group.create_thread(&call_once_thread); + } + group.join_all(); + } + catch(...) + { + group.interrupt_all(); + group.join_all(); + throw; + } + + BOOST_CHECK_EQUAL(var_to_init,1); +} + +int var_to_init_with_functor=0; + +struct increment_value +{ + int* value; + explicit increment_value(int* value_): + value(value_) + {} + + void operator()() const + { + boost::unique_lock<boost::mutex> lock(m); + ++(*value); + } +}; + +void call_once_with_functor() +{ + unsigned const loop_count=100; + int my_once_value=0; + static boost::once_flag functor_flag=BOOST_ONCE_INIT; + for(unsigned i=0;i<loop_count;++i) + { + boost::call_once(functor_flag, increment_value(&var_to_init_with_functor)); + my_once_value=var_to_init_with_functor; + if(my_once_value!=1) + { + break; + } + } + boost::unique_lock<boost::mutex> lock(m); + BOOST_CHECK_EQUAL(my_once_value, 1); +} + +BOOST_AUTO_TEST_CASE(test_call_once_arbitrary_functor) +{ + BOOST_DETAIL_THREAD_LOG; + + unsigned const num_threads=20; + boost::thread_group group; + + try + { + for(unsigned i=0;i<num_threads;++i) + { + group.create_thread(&call_once_with_functor); + } + group.join_all(); + } + catch(...) + { + group.interrupt_all(); + group.join_all(); + throw; + } + + BOOST_CHECK_EQUAL(var_to_init_with_functor,1); +} + + +struct throw_before_third_pass +{ + struct my_exception + {}; + + static unsigned pass_counter; + + void operator()() const + { + boost::unique_lock<boost::mutex> lock(m); + ++pass_counter; + if(pass_counter<3) + { + throw my_exception(); + } + } +}; + +unsigned throw_before_third_pass::pass_counter=0; +unsigned exception_counter=0; + +void call_once_with_exception() +{ + static boost::once_flag functor_flag=BOOST_ONCE_INIT; + try + { + boost::call_once(functor_flag, throw_before_third_pass()); + } + catch(throw_before_third_pass::my_exception) + { + boost::unique_lock<boost::mutex> lock(m); + ++exception_counter; + } +} + +BOOST_AUTO_TEST_CASE(test_call_once_retried_on_exception) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const num_threads=20; + boost::thread_group group; + + try + { + for(unsigned i=0;i<num_threads;++i) + { + group.create_thread(&call_once_with_exception); + } + group.join_all(); + } + catch(...) + { + group.interrupt_all(); + group.join_all(); + throw; + } + + BOOST_CHECK_EQUAL(throw_before_third_pass::pass_counter,3u); + BOOST_CHECK_EQUAL(exception_counter,2u); +} + + diff --git a/src/boost/libs/thread/test/test_physical_concurrency.cpp b/src/boost/libs/thread/test/test_physical_concurrency.cpp new file mode 100644 index 000000000..5c635751f --- /dev/null +++ b/src/boost/libs/thread/test/test_physical_concurrency.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2007 Anthony Williams +// Copyright (C) 2013 Tim Blechmann +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE Boost.Threads: physical_concurrency test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/thread/mutex.hpp> + +BOOST_AUTO_TEST_CASE(test_physical_concurrency_is_non_zero) +{ +#if defined(__MINGW32__) && !defined(__MINGW64__) +// This matches the condition in win32/thread.cpp, even though +// that's probably wrong on MinGW-w64 in 32 bit mode +#else + BOOST_CHECK(boost::thread::physical_concurrency()!=0); +#endif +} + + + + diff --git a/src/boost/libs/thread/test/test_scheduled_tp.cpp b/src/boost/libs/thread/test/test_scheduled_tp.cpp new file mode 100644 index 000000000..8684ffd4f --- /dev/null +++ b/src/boost/libs/thread/test/test_scheduled_tp.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/bind/bind.hpp> +#include <boost/chrono.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/function.hpp> +#include <boost/thread/executors/scheduled_thread_pool.hpp> +#include <iostream> + +#include <boost/core/lightweight_test.hpp> + +using namespace boost::chrono; + +typedef boost::scheduled_thread_pool scheduled_tp; + +void fn(int x) +{ + std::cout << x << std::endl; +} + +void func(steady_clock::time_point pushed, steady_clock::duration dur) +{ + BOOST_TEST(pushed + dur < steady_clock::now()); +} +void func2(scheduled_tp* tp, steady_clock::duration d) +{ + boost::function<void()> fn = boost::bind(func,steady_clock::now(),d); + tp->submit_after(fn, d); +} + + + +void test_timing(const int n) +{ + //This function should take n seconds to execute. + boost::scheduled_thread_pool se(4); + + for(int i = 1; i <= n; i++) + { + se.submit_after(boost::bind(fn,i), milliseconds(i*100)); + } + boost::this_thread::sleep_for(boost::chrono::seconds(10)); + //dtor is called here so all task will have to be executed before we return +} + +void test_deque_timing() +{ + boost::scheduled_thread_pool se(4); + for(int i = 0; i < 10; i++) + { + steady_clock::duration d = milliseconds(i*100); + boost::function<void()> fn = boost::bind(func,steady_clock::now(),d); + se.submit_after(fn,d); + } +} + +void test_deque_multi(const int n) +{ + scheduled_tp se(4); + boost::thread_group tg; + for(int i = 0; i < n; i++) + { + steady_clock::duration d = milliseconds(i*100); + //boost::function<void()> fn = boost::bind(func,steady_clock::now(),d); + //tg.create_thread(boost::bind(boost::mem_fn(&scheduled_tp::submit_after), &se, fn, d)); + tg.create_thread(boost::bind(func2, &se, d)); + } + tg.join_all(); + //dtor is called here so execution will block until all the closures + //have been completed. +} + +int main() +{ + steady_clock::time_point start = steady_clock::now(); + test_timing(5); + steady_clock::duration diff = steady_clock::now() - start; + BOOST_TEST(diff > milliseconds(500)); + test_deque_timing(); + test_deque_multi(4); + test_deque_multi(8); + test_deque_multi(16); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_scheduler.cpp b/src/boost/libs/thread/test/test_scheduler.cpp new file mode 100644 index 000000000..5847ff010 --- /dev/null +++ b/src/boost/libs/thread/test/test_scheduler.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread/executors/scheduler.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <iostream> + +#include <boost/core/lightweight_test.hpp> + +using namespace boost::chrono; + + +typedef boost::executors::basic_thread_pool thread_pool; + +void fn(int x) +{ + //std::cout << "[" << __LINE__ << "] " << steady_clock::now() << std::endl; + std::cout << x << std::endl; +} + +void test_scheduler(const int n, boost::scheduler<>& sch) +{ + for(int i = 1; i <= n; i++) + { + sch.submit_after(boost::bind(fn,i), seconds(i)); + sch.submit_after(boost::bind(fn,i), milliseconds(i*100)); + } +} + +void test_after(const int n, boost::scheduler<>& sch) +{ + for(int i = 1; i <= n; i++) + { + sch.after(seconds(i)).submit(boost::bind(fn,i)); + sch.after(milliseconds(i*100)).submit(boost::bind(fn,i)); + } +} + +void test_at(const int n, boost::scheduler<>& sch) +{ + for(int i = 1; i <= n; i++) + { + sch.at(steady_clock::now()+seconds(i)).submit(boost::bind(fn,i)); + sch.at(steady_clock::now()+milliseconds(i*100)).submit(boost::bind(fn,i)); + } +} + +void test_on(const int n, boost::scheduler<>& sch, thread_pool& tp) +{ + for(int i = 1; i <= n; i++) + { + sch.on(tp).after(seconds(i)).submit(boost::bind(fn,i)); + sch.on(tp).after(milliseconds(i*100)).submit(boost::bind(fn,i)); + } +} + +int main() +{ + thread_pool tp(4); + boost::scheduler<> sch; + test_scheduler(5, sch); + test_after(5, sch); + test_at(5, sch); + test_on(5, sch, tp); + boost::this_thread::sleep_for(boost::chrono::seconds(10)); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_scheduling_adaptor.cpp b/src/boost/libs/thread/test/test_scheduling_adaptor.cpp new file mode 100644 index 000000000..38c073bda --- /dev/null +++ b/src/boost/libs/thread/test/test_scheduling_adaptor.cpp @@ -0,0 +1,54 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/function.hpp> +#include <boost/thread/executors/executor.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executors/scheduling_adaptor.hpp> +#include <boost/chrono/chrono_io.hpp> + +#include <boost/core/lightweight_test.hpp> + +using namespace boost::chrono; + + +typedef boost::executors::basic_thread_pool thread_pool; + +void fn(int x) +{ + //std::cout << "[" << __LINE__ << "] " << steady_clock::now() << std::endl; + std::cout << x << std::endl; +} + +void test_timing(const int n) +{ + thread_pool tp(4); + boost::scheduling_adaptor<thread_pool> sa(tp); + for(int i = 1; i <= n; i++) + { + sa.submit_after(boost::bind(fn,i),seconds(i)); + sa.submit_after(boost::bind(fn,i), milliseconds(i*100)); + } + boost::this_thread::sleep_for(boost::chrono::seconds(10)); +} + +int main() +{ + steady_clock::time_point start = steady_clock::now(); + test_timing(5); + steady_clock::duration diff = steady_clock::now() - start; + BOOST_TEST(diff > seconds(5)); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_shared_mutex.cpp b/src/boost/libs/thread/test/test_shared_mutex.cpp new file mode 100644 index 000000000..17bd9a6a1 --- /dev/null +++ b/src/boost/libs/thread/test/test_shared_mutex.cpp @@ -0,0 +1,281 @@ +// (C) Copyright 2006-7 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +#define BOOST_TEST_MODULE Boost.Threads: shared_mutex test suite + +#include <boost/test/unit_test.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/xtime.hpp> +#include "./util.inl" +#include "./shared_mutex_locking_thread.hpp" +#include <iostream> + +#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \ + { \ + boost::unique_lock<boost::mutex> lock(mutex_name); \ + BOOST_CHECK_EQUAL(value,expected_value); \ + } + +BOOST_AUTO_TEST_CASE(test_multiple_readers) +{ + std::cout << __LINE__ << std::endl; + unsigned const number_of_threads=10; + + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + try + { + for(unsigned i=0;i<number_of_threads;++i) + { + pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + } + + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<number_of_threads) + { + unblocked_condition.wait(lk); + } + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads); + + finish_lock.unlock(); + + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,number_of_threads); +} + +BOOST_AUTO_TEST_CASE(test_only_one_writer_permitted) +{ + std::cout << __LINE__ << std::endl; + unsigned const number_of_threads=10; + + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + try + { + for(unsigned i=0;i<number_of_threads;++i) + { + pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + } + + boost::thread::sleep(delay(2)); + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U); + + finish_lock.unlock(); + + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u); +} + +BOOST_AUTO_TEST_CASE(test_reader_blocks_writer) +{ + std::cout << __LINE__ << std::endl; + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + try + { + + pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<1) + { + unblocked_condition.wait(lk); + } + } + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U); + pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U); + + finish_lock.unlock(); + + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,2U); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u); +} + +BOOST_AUTO_TEST_CASE(test_unlocking_writer_unblocks_all_readers) +{ + std::cout << __LINE__ << std::endl; + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + boost::unique_lock<boost::shared_mutex> write_lock(rw_mutex); + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + unsigned const reader_count=10; + + try + { + for(unsigned i=0;i<reader_count;++i) + { + pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + } + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,0U); + + write_lock.unlock(); + + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<reader_count) + { + unblocked_condition.wait(lk); + } + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count); + + finish_lock.unlock(); + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count); +} + +BOOST_AUTO_TEST_CASE(test_unlocking_last_reader_only_unblocks_one_writer) +{ + std::cout << __LINE__ << std::endl; + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_readers=0; + unsigned max_simultaneous_readers=0; + unsigned simultaneous_running_writers=0; + unsigned max_simultaneous_writers=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_reading_mutex; + boost::unique_lock<boost::mutex> finish_reading_lock(finish_reading_mutex); + boost::mutex finish_writing_mutex; + boost::unique_lock<boost::mutex> finish_writing_lock(finish_writing_mutex); + + unsigned const reader_count=10; + unsigned const writer_count=10; + + try + { + for(unsigned i=0;i<reader_count;++i) + { + pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_reading_mutex,simultaneous_running_readers,max_simultaneous_readers)); + } + boost::thread::sleep(delay(1)); + for(unsigned i=0;i<writer_count;++i) + { + pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_writing_mutex,simultaneous_running_writers,max_simultaneous_writers)); + } + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<reader_count) + { + unblocked_condition.wait(lk); + } + } + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count); + + finish_reading_lock.unlock(); + + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<(reader_count+1)) + { + unblocked_condition.wait(lk); + } + } + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1); + + finish_writing_lock.unlock(); + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+writer_count); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_readers,reader_count); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_writers,1u); +} diff --git a/src/boost/libs/thread/test/test_shared_mutex_part_2.cpp b/src/boost/libs/thread/test/test_shared_mutex_part_2.cpp new file mode 100644 index 000000000..d395b2e78 --- /dev/null +++ b/src/boost/libs/thread/test/test_shared_mutex_part_2.cpp @@ -0,0 +1,294 @@ +// (C) Copyright 2006-7 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: shared_mutex_part2 test suite + +#include <boost/config.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/xtime.hpp> +#include "./util.inl" +#include "./shared_mutex_locking_thread.hpp" + +#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \ + { \ + boost::unique_lock<boost::mutex> lock(mutex_name); \ + BOOST_CHECK_EQUAL(value,expected_value); \ + } + +class simple_upgrade_thread +{ + boost::shared_mutex& rwm; + boost::mutex& finish_mutex; + boost::mutex& unblocked_mutex; + unsigned& unblocked_count; + + void operator=(simple_upgrade_thread&); + +public: + simple_upgrade_thread(boost::shared_mutex& rwm_, + boost::mutex& finish_mutex_, + boost::mutex& unblocked_mutex_, + unsigned& unblocked_count_): + rwm(rwm_),finish_mutex(finish_mutex_), + unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_) + {} + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + simple_upgrade_thread(simple_upgrade_thread const&) = default; +#endif + + void operator()() + { + boost::upgrade_lock<boost::shared_mutex> lk(rwm); + + { + boost::unique_lock<boost::mutex> ulk(unblocked_mutex); + ++unblocked_count; + } + + boost::unique_lock<boost::mutex> flk(finish_mutex); + } +}; + + +BOOST_AUTO_TEST_CASE(test_only_one_upgrade_lock_permitted) +{ + unsigned const number_of_threads=2; + + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + try + { + for(unsigned i=0;i<number_of_threads;++i) + { + pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + } + + boost::thread::sleep(delay(1)); + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U); + + finish_lock.unlock(); + + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u); +} + +BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_if_currently_locked_shared) +{ + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + unsigned const reader_count=10; + + try + { + for(unsigned i=0;i<reader_count;++i) + { + pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + } + boost::thread::sleep(delay(1)); + pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<(reader_count+1)) + { + unblocked_condition.wait(lk); + } + } + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1); + + finish_lock.unlock(); + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count+1); +} + +BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_to_unique_if_currently_locked_upgrade) +{ + boost::shared_mutex mtx; + boost::upgrade_lock<boost::shared_mutex> l(mtx); + boost::upgrade_to_unique_lock<boost::shared_mutex> ul(l); + BOOST_CHECK(ul.owns_lock()); +} + +BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_shared_returns_false) +{ + + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + bool const try_succeeded=rw_mutex.try_lock_shared(); + BOOST_CHECK(!try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_upgrade_returns_false) +{ + + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + bool const try_succeeded=rw_mutex.try_lock_upgrade(); + BOOST_CHECK(!try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_upgrade(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_shared_returns_true) +{ + boost::shared_mutex rw_mutex; + bool const try_succeeded=rw_mutex.try_lock_shared(); + BOOST_CHECK(try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_shared(); + } +} + +BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_upgrade_returns_true) +{ + boost::shared_mutex rw_mutex; + bool const try_succeeded=rw_mutex.try_lock_upgrade(); + BOOST_CHECK(try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_upgrade(); + } +} + +BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_shared_returns_true) +{ + + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + bool const try_succeeded=rw_mutex.try_lock_shared(); + BOOST_CHECK(try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_upgrade_returns_true) +{ + + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + bool const try_succeeded=rw_mutex.try_lock_upgrade(); + BOOST_CHECK(try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_upgrade(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false) +{ + + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_upgrade_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + bool const try_succeeded=rw_mutex.try_lock_upgrade(); + BOOST_CHECK(!try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_upgrade(); + } + + finish_lock.unlock(); + writer.join(); +} + + diff --git a/src/boost/libs/thread/test/test_shared_mutex_timed_locks.cpp b/src/boost/libs/thread/test/test_shared_mutex_timed_locks.cpp new file mode 100644 index 000000000..c29c4260c --- /dev/null +++ b/src/boost/libs/thread/test/test_shared_mutex_timed_locks.cpp @@ -0,0 +1,255 @@ +// (C) Copyright 2006-7 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: shared_mutex_timed_locks test suite + +#include <boost/test/unit_test.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> +#include "./util.inl" +#include "./shared_mutex_locking_thread.hpp" + +#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \ + { \ + boost::unique_lock<boost::mutex> lock(mutex_name); \ + BOOST_CHECK_EQUAL(value,expected_value); \ + } + + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_times_out_if_write_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock_shared(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_no_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout); + BOOST_CHECK(boost::get_system_time()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock_shared(wait_duration); + BOOST_CHECK(boost::get_system_time()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout); + BOOST_CHECK(boost::get_system_time()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock_shared(wait_duration); + BOOST_CHECK(boost::get_system_time()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + reader.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_write_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_succeeds_if_no_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock(timeout); + BOOST_CHECK(boost::get_system_time()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock(wait_duration); + BOOST_CHECK(boost::get_system_time()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + finish_lock.unlock(); + reader.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + bool timed_lock_succeeded=rw_mutex.timed_lock(timeout); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::posix_time::milliseconds const wait_duration(500); + timed_lock_succeeded=rw_mutex.timed_lock_shared(wait_duration); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + reader.join(); +} + diff --git a/src/boost/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp b/src/boost/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp new file mode 100644 index 000000000..f746f50a9 --- /dev/null +++ b/src/boost/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp @@ -0,0 +1,259 @@ +// (C) Copyright 2006-7 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: shared_mutex_locks_chrono test suite + +#include <boost/test/unit_test.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/shared_mutex.hpp> +#include "./util.inl" +#include "./shared_mutex_locking_thread.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \ + { \ + boost::unique_lock<boost::mutex> lock(mutex_name); \ + BOOST_CHECK_EQUAL(value,expected_value); \ + } + + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_times_out_if_write_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + boost::chrono::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_no_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(timeout); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(timeout); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + reader.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_write_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + boost::chrono::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_for(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_succeeds_if_no_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_for(wait_duration); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + boost::chrono::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_for(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + finish_lock.unlock(); + reader.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::chrono::milliseconds const wait_duration(500); + timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + reader.join(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + + diff --git a/src/boost/libs/thread/test/test_thread.cpp b/src/boost/libs/thread/test/test_thread.cpp new file mode 100644 index 000000000..ab9ddba0d --- /dev/null +++ b/src/boost/libs/thread/test/test_thread.cpp @@ -0,0 +1,222 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> +#include <boost/bind/bind.hpp> +#include <boost/ref.hpp> +#include <boost/utility.hpp> + +#define BOOST_TEST_MODULE Boost.Threads: thread test suite + +#include <boost/test/unit_test.hpp> + +#define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only +#include "./util.inl" + +int test_value; + +void simple_thread() +{ + test_value = 999; +} + +void comparison_thread(boost::thread::id parent) +{ + boost::thread::id const my_id=boost::this_thread::get_id(); + + BOOST_CHECK(my_id != parent); + boost::thread::id const my_id2=boost::this_thread::get_id(); + BOOST_CHECK(my_id == my_id2); + + boost::thread::id const no_thread_id=boost::thread::id(); + BOOST_CHECK(my_id != no_thread_id); +} + +BOOST_AUTO_TEST_CASE(test_sleep) +{ + boost::xtime xt = delay(3); + boost::thread::sleep(xt); + + // Ensure it's in a range instead of checking actual equality due to time + // lapse + BOOST_CHECK(boost::threads::test::in_range(xt, 2)); +} + +void do_test_creation() +{ + test_value = 0; + boost::thread thrd(&simple_thread); + thrd.join(); + BOOST_CHECK_EQUAL(test_value, 999); +} + +BOOST_AUTO_TEST_CASE(test_creation) +{ + timed_test(&do_test_creation, 1); +} + +void do_test_id_comparison() +{ + boost::thread::id const self=boost::this_thread::get_id(); + boost::thread thrd(boost::bind(&comparison_thread, self)); + thrd.join(); +} + +BOOST_AUTO_TEST_CASE(test_id_comparison) +{ + timed_test(&do_test_id_comparison, 1); +} + +void interruption_point_thread(boost::mutex* m,bool* failed) +{ + boost::unique_lock<boost::mutex> lk(*m); + boost::this_thread::interruption_point(); + *failed=true; +} + +void do_test_thread_interrupts_at_interruption_point() +{ + boost::mutex m; + bool failed=false; + boost::unique_lock<boost::mutex> lk(m); + boost::thread thrd(boost::bind(&interruption_point_thread,&m,&failed)); + thrd.interrupt(); + lk.unlock(); + thrd.join(); + BOOST_CHECK(!failed); +} + +BOOST_AUTO_TEST_CASE(test_thread_interrupts_at_interruption_point) +{ + timed_test(&do_test_thread_interrupts_at_interruption_point, 1); +} + +void disabled_interruption_point_thread(boost::mutex* m,bool* failed) +{ + boost::unique_lock<boost::mutex> lk(*m); + boost::this_thread::disable_interruption dc; + boost::this_thread::interruption_point(); + *failed=false; +} + +void do_test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point() +{ + boost::mutex m; + bool failed=true; + boost::unique_lock<boost::mutex> lk(m); + boost::thread thrd(boost::bind(&disabled_interruption_point_thread,&m,&failed)); + thrd.interrupt(); + lk.unlock(); + thrd.join(); + BOOST_CHECK(!failed); +} + +BOOST_AUTO_TEST_CASE(test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point) +{ + timed_test(&do_test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point, 1); +} + +struct non_copyable_functor: + boost::noncopyable +{ + unsigned value; + + non_copyable_functor(): boost::noncopyable(), + value(0) + {} + + void operator()() + { + value=999; + } +}; + +void do_test_creation_through_reference_wrapper() +{ + non_copyable_functor f; + + boost::thread thrd(boost::ref(f)); + thrd.join(); + BOOST_CHECK_EQUAL(f.value, 999u); +} + +BOOST_AUTO_TEST_CASE(test_creation_through_reference_wrapper) +{ + timed_test(&do_test_creation_through_reference_wrapper, 1); +} + +struct long_running_thread +{ + boost::condition_variable cond; + boost::mutex mut; + bool done; + + long_running_thread(): + done(false) + {} + + void operator()() + { + boost::unique_lock<boost::mutex> lk(mut); + while(!done) + { + cond.wait(lk); + } + } +}; + +void do_test_timed_join() +{ + long_running_thread f; + boost::thread thrd(boost::ref(f)); + BOOST_CHECK(thrd.joinable()); + boost::system_time xt=delay(3); + bool const joined=thrd.timed_join(xt); + BOOST_CHECK(boost::threads::test::in_range(boost::get_xtime(xt), 2)); + BOOST_CHECK(!joined); + BOOST_CHECK(thrd.joinable()); + { + boost::unique_lock<boost::mutex> lk(f.mut); + f.done=true; + f.cond.notify_one(); + } + + xt=delay(3); + bool const joined2=thrd.timed_join(xt); + boost::system_time const now=boost::get_system_time(); + BOOST_CHECK(xt>now); + BOOST_CHECK(joined2); + BOOST_CHECK(!thrd.joinable()); +} + +BOOST_AUTO_TEST_CASE(test_timed_join) +{ + timed_test(&do_test_timed_join, 10); +} + +BOOST_AUTO_TEST_CASE(test_swap) +{ + boost::thread t(&simple_thread); + boost::thread t2(&simple_thread); + boost::thread::id id1=t.get_id(); + boost::thread::id id2=t2.get_id(); + + t.swap(t2); + BOOST_CHECK(t.get_id()==id2); + BOOST_CHECK(t2.get_id()==id1); + + swap(t,t2); + BOOST_CHECK(t.get_id()==id1); + BOOST_CHECK(t2.get_id()==id2); +} + diff --git a/src/boost/libs/thread/test/test_thread_exit.cpp b/src/boost/libs/thread/test/test_thread_exit.cpp new file mode 100644 index 000000000..577bcd05d --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_exit.cpp @@ -0,0 +1,63 @@ +// (C) Copyright 2009 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/future.hpp> +#include <utility> +#include <memory> +#include <string> + +#define BOOST_TEST_MODULE Boost.Threads: thread exit test suite + +#include <boost/test/unit_test.hpp> + +boost::thread::id exit_func_thread_id; + +void exit_func() +{ + exit_func_thread_id=boost::this_thread::get_id(); +} + +void tf1() +{ + boost::this_thread::at_thread_exit(exit_func); + BOOST_CHECK(exit_func_thread_id!=boost::this_thread::get_id()); +} + +BOOST_AUTO_TEST_CASE(test_thread_exit_func_runs_when_thread_exits) +{ + exit_func_thread_id=boost::thread::id(); + boost::thread t(&tf1); + boost::thread::id const t_id=t.get_id(); + t.join(); + BOOST_CHECK(exit_func_thread_id==t_id); +} + +struct fo +{ + void operator()() + { + exit_func_thread_id=boost::this_thread::get_id(); + } +}; + +void tf2() +{ + boost::this_thread::at_thread_exit(fo()); + BOOST_CHECK(exit_func_thread_id!=boost::this_thread::get_id()); +} + + +BOOST_AUTO_TEST_CASE(test_can_use_function_object_for_exit_func) +{ + exit_func_thread_id=boost::thread::id(); + boost::thread t(tf2); + boost::thread::id const t_id=t.get_id(); + t.join(); + BOOST_CHECK(exit_func_thread_id==t_id); +} diff --git a/src/boost/libs/thread/test/test_thread_id.cpp b/src/boost/libs/thread/test/test_thread_id.cpp new file mode 100644 index 000000000..477909d1a --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_id.cpp @@ -0,0 +1,139 @@ +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE Boost.Threads: thread::get_id test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/bind/bind.hpp> + +void do_nothing() +{} + +BOOST_AUTO_TEST_CASE(test_thread_id_for_default_constructed_thread_is_default_constructed_id) +{ + boost::thread t; + BOOST_CHECK(t.get_id()==boost::thread::id()); +} + +BOOST_AUTO_TEST_CASE(test_thread_id_for_running_thread_is_not_default_constructed_id) +{ + boost::thread t(&do_nothing); + BOOST_CHECK(t.get_id()!=boost::thread::id()); + t.join(); +} + +BOOST_AUTO_TEST_CASE(test_different_threads_have_different_ids) +{ + boost::thread t(do_nothing); + boost::thread t2(do_nothing); + BOOST_CHECK(t.get_id()!=t2.get_id()); + t.join(); + t2.join(); +} + +BOOST_AUTO_TEST_CASE(test_thread_ids_have_a_total_order) +{ + boost::thread t(do_nothing); + boost::thread t2(do_nothing); + boost::thread t3(do_nothing); + BOOST_CHECK(t.get_id()!=t2.get_id()); + BOOST_CHECK(t.get_id()!=t3.get_id()); + BOOST_CHECK(t2.get_id()!=t3.get_id()); + + BOOST_CHECK((t.get_id()<t2.get_id()) != (t2.get_id()<t.get_id())); + BOOST_CHECK((t.get_id()<t3.get_id()) != (t3.get_id()<t.get_id())); + BOOST_CHECK((t2.get_id()<t3.get_id()) != (t3.get_id()<t2.get_id())); + + BOOST_CHECK((t.get_id()>t2.get_id()) != (t2.get_id()>t.get_id())); + BOOST_CHECK((t.get_id()>t3.get_id()) != (t3.get_id()>t.get_id())); + BOOST_CHECK((t2.get_id()>t3.get_id()) != (t3.get_id()>t2.get_id())); + + BOOST_CHECK((t.get_id()<t2.get_id()) == (t2.get_id()>t.get_id())); + BOOST_CHECK((t2.get_id()<t.get_id()) == (t.get_id()>t2.get_id())); + BOOST_CHECK((t.get_id()<t3.get_id()) == (t3.get_id()>t.get_id())); + BOOST_CHECK((t3.get_id()<t.get_id()) == (t.get_id()>t3.get_id())); + BOOST_CHECK((t2.get_id()<t3.get_id()) == (t3.get_id()>t2.get_id())); + BOOST_CHECK((t3.get_id()<t2.get_id()) == (t2.get_id()>t3.get_id())); + + BOOST_CHECK((t.get_id()<t2.get_id()) == (t2.get_id()>=t.get_id())); + BOOST_CHECK((t2.get_id()<t.get_id()) == (t.get_id()>=t2.get_id())); + BOOST_CHECK((t.get_id()<t3.get_id()) == (t3.get_id()>=t.get_id())); + BOOST_CHECK((t3.get_id()<t.get_id()) == (t.get_id()>=t3.get_id())); + BOOST_CHECK((t2.get_id()<t3.get_id()) == (t3.get_id()>=t2.get_id())); + BOOST_CHECK((t3.get_id()<t2.get_id()) == (t2.get_id()>=t3.get_id())); + + BOOST_CHECK((t.get_id()<=t2.get_id()) == (t2.get_id()>t.get_id())); + BOOST_CHECK((t2.get_id()<=t.get_id()) == (t.get_id()>t2.get_id())); + BOOST_CHECK((t.get_id()<=t3.get_id()) == (t3.get_id()>t.get_id())); + BOOST_CHECK((t3.get_id()<=t.get_id()) == (t.get_id()>t3.get_id())); + BOOST_CHECK((t2.get_id()<=t3.get_id()) == (t3.get_id()>t2.get_id())); + BOOST_CHECK((t3.get_id()<=t2.get_id()) == (t2.get_id()>t3.get_id())); + + if((t.get_id()<t2.get_id()) && (t2.get_id()<t3.get_id())) + { + BOOST_CHECK(t.get_id()<t3.get_id()); + } + else if((t.get_id()<t3.get_id()) && (t3.get_id()<t2.get_id())) + { + BOOST_CHECK(t.get_id()<t2.get_id()); + } + else if((t2.get_id()<t3.get_id()) && (t3.get_id()<t.get_id())) + { + BOOST_CHECK(t2.get_id()<t.get_id()); + } + else if((t2.get_id()<t.get_id()) && (t.get_id()<t3.get_id())) + { + BOOST_CHECK(t2.get_id()<t3.get_id()); + } + else if((t3.get_id()<t.get_id()) && (t.get_id()<t2.get_id())) + { + BOOST_CHECK(t3.get_id()<t2.get_id()); + } + else if((t3.get_id()<t2.get_id()) && (t2.get_id()<t.get_id())) + { + BOOST_CHECK(t3.get_id()<t.get_id()); + } + else + { + BOOST_CHECK(false); + } + + boost::thread::id default_id; + + BOOST_CHECK(default_id < t.get_id()); + BOOST_CHECK(default_id < t2.get_id()); + BOOST_CHECK(default_id < t3.get_id()); + + BOOST_CHECK(default_id <= t.get_id()); + BOOST_CHECK(default_id <= t2.get_id()); + BOOST_CHECK(default_id <= t3.get_id()); + + BOOST_CHECK(!(default_id > t.get_id())); + BOOST_CHECK(!(default_id > t2.get_id())); + BOOST_CHECK(!(default_id > t3.get_id())); + + BOOST_CHECK(!(default_id >= t.get_id())); + BOOST_CHECK(!(default_id >= t2.get_id())); + BOOST_CHECK(!(default_id >= t3.get_id())); + + t.join(); + t2.join(); + t3.join(); +} + +void get_thread_id(boost::thread::id* id) +{ + *id=boost::this_thread::get_id(); +} + +BOOST_AUTO_TEST_CASE(test_thread_id_of_running_thread_returned_by_this_thread_get_id) +{ + boost::thread::id id; + boost::thread t(boost::bind(get_thread_id,&id)); + boost::thread::id t_id=t.get_id(); + t.join(); + BOOST_CHECK(id==t_id); +} diff --git a/src/boost/libs/thread/test/test_thread_launching.cpp b/src/boost/libs/thread/test/test_thread_launching.cpp new file mode 100644 index 000000000..0c74871d3 --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_launching.cpp @@ -0,0 +1,216 @@ +// Copyright (C) 2007-8 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 3 +#define BOOST_TEST_MODULE Boost.Threads: thread launching test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/ref.hpp> +#include <boost/utility.hpp> +#include <string> +#include <vector> + +bool normal_function_called=false; + +void normal_function() +{ + normal_function_called=true; +} + +BOOST_AUTO_TEST_CASE(test_thread_function_no_arguments) +{ + boost::thread function(&normal_function); + function.join(); + BOOST_CHECK(normal_function_called); +} + +int nfoa_res=0; + +void normal_function_one_arg(int i) +{ + nfoa_res=i; +} + +BOOST_AUTO_TEST_CASE(test_thread_function_one_argument) +{ + boost::thread function(&normal_function_one_arg,42); + function.join(); + BOOST_CHECK_EQUAL(42,nfoa_res); +} + +struct callable_no_args +{ + static bool called; + + void operator()() const + { + called=true; + } +}; + +bool callable_no_args::called=false; + +BOOST_AUTO_TEST_CASE(test_thread_callable_object_no_arguments) +{ + callable_no_args func; + boost::thread callable(func); + callable.join(); + BOOST_CHECK(callable_no_args::called); +} + +struct callable_noncopyable_no_args: + boost::noncopyable +{ + callable_noncopyable_no_args() : boost::noncopyable() {} + static bool called; + + void operator()() const + { + called=true; + } +}; + +bool callable_noncopyable_no_args::called=false; + +BOOST_AUTO_TEST_CASE(test_thread_callable_object_ref_no_arguments) +{ + callable_noncopyable_no_args func; + + boost::thread callable(boost::ref(func)); + callable.join(); + BOOST_CHECK(callable_noncopyable_no_args::called); +} + +struct callable_one_arg +{ + static bool called; + static int called_arg; + + void operator()(int arg) const + { + called=true; + called_arg=arg; + } +}; + +bool callable_one_arg::called=false; +int callable_one_arg::called_arg=0; + +BOOST_AUTO_TEST_CASE(test_thread_callable_object_one_argument) +{ + callable_one_arg func; + boost::thread callable(func,42); + callable.join(); + BOOST_CHECK(callable_one_arg::called); + BOOST_CHECK_EQUAL(callable_one_arg::called_arg,42); +} + +struct callable_multiple_arg +{ + static bool called_two; + static int called_two_arg1; + static double called_two_arg2; + static bool called_three; + static std::string called_three_arg1; + static std::vector<int> called_three_arg2; + static int called_three_arg3; + + void operator()(int arg1,double arg2) const + { + called_two=true; + called_two_arg1=arg1; + called_two_arg2=arg2; + } + void operator()(std::string const& arg1,std::vector<int> const& arg2,int arg3) const + { + called_three=true; + called_three_arg1=arg1; + called_three_arg2=arg2; + called_three_arg3=arg3; + } +}; + +bool callable_multiple_arg::called_two=false; +bool callable_multiple_arg::called_three=false; +int callable_multiple_arg::called_two_arg1; +double callable_multiple_arg::called_two_arg2; +std::string callable_multiple_arg::called_three_arg1; +std::vector<int> callable_multiple_arg::called_three_arg2; +int callable_multiple_arg::called_three_arg3; + +BOOST_AUTO_TEST_CASE(test_thread_callable_object_multiple_arguments) +{ + std::vector<int> x; + for(unsigned i=0;i<7;++i) + { + x.push_back(i*i); + } + + callable_multiple_arg func; + // Avoid + // boost/bind/bind.hpp(392) : warning C4244: 'argument' : conversion from 'double' to 'int', possible loss of data + + boost::thread callable3(func,"hello",x,1); + callable3.join(); + BOOST_CHECK(callable_multiple_arg::called_three); + BOOST_CHECK_EQUAL(callable_multiple_arg::called_three_arg1,"hello"); + BOOST_CHECK_EQUAL(callable_multiple_arg::called_three_arg2.size(),x.size()); + for(unsigned j=0;j<x.size();++j) + { + BOOST_CHECK_EQUAL(callable_multiple_arg::called_three_arg2.at(j),x[j]); + } + + BOOST_CHECK_EQUAL(callable_multiple_arg::called_three_arg3,1); + + double const dbl=1.234; + + boost::thread callable2(func,19,dbl); + callable2.join(); + BOOST_CHECK(callable_multiple_arg::called_two); + BOOST_CHECK_EQUAL(callable_multiple_arg::called_two_arg1,19); + BOOST_CHECK_EQUAL(callable_multiple_arg::called_two_arg2,dbl); +} + +struct X +{ + bool function_called; + int arg_value; + + X(): + function_called(false), + arg_value(0) + {} + + + void f0() + { + function_called=true; + } + + void f1(int i) + { + arg_value=i; + } + +}; + +BOOST_AUTO_TEST_CASE(test_thread_member_function_no_arguments) +{ + X x; + + boost::thread function(&X::f0,&x); + function.join(); + BOOST_CHECK(x.function_called); +} + + +BOOST_AUTO_TEST_CASE(test_thread_member_function_one_argument) +{ + X x; + boost::thread function(&X::f1,&x,42); + function.join(); + BOOST_CHECK_EQUAL(42,x.arg_value); +} diff --git a/src/boost/libs/thread/test/test_thread_mf.cpp b/src/boost/libs/thread/test/test_thread_mf.cpp new file mode 100644 index 000000000..843008fa7 --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_mf.cpp @@ -0,0 +1,135 @@ +// +// Copyright (C) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct X +{ + mutable unsigned int hash; + + X(): hash(0) {} + + int f0() { f1(17); return 0; } + int g0() const { g1(17); return 0; } + + int f1(int a1) { hash = (hash * 17041 + a1) % 32768; return 0; } + int g1(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; return 0; } + + int f2(int a1, int a2) { f1(a1); f1(a2); return 0; } + int g2(int a1, int a2) const { g1(a1); g1(a2); return 0; } + + int f3(int a1, int a2, int a3) { f2(a1, a2); f1(a3); return 0; } + int g3(int a1, int a2, int a3) const { g2(a1, a2); g1(a3); return 0; } + + int f4(int a1, int a2, int a3, int a4) { f3(a1, a2, a3); f1(a4); return 0; } + int g4(int a1, int a2, int a3, int a4) const { g3(a1, a2, a3); g1(a4); return 0; } + + int f5(int a1, int a2, int a3, int a4, int a5) { f4(a1, a2, a3, a4); f1(a5); return 0; } + int g5(int a1, int a2, int a3, int a4, int a5) const { g4(a1, a2, a3, a4); g1(a5); return 0; } + + int f6(int a1, int a2, int a3, int a4, int a5, int a6) { f5(a1, a2, a3, a4, a5); f1(a6); return 0; } + int g6(int a1, int a2, int a3, int a4, int a5, int a6) const { g5(a1, a2, a3, a4, a5); g1(a6); return 0; } + + int f7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) { f6(a1, a2, a3, a4, a5, a6); f1(a7); return 0; } + int g7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) const { g6(a1, a2, a3, a4, a5, a6); g1(a7); return 0; } + + int f8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { f7(a1, a2, a3, a4, a5, a6, a7); f1(a8); return 0; } + int g8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const { g7(a1, a2, a3, a4, a5, a6, a7); g1(a8); return 0; } +}; + +int main() +{ + X x; + + // 0 + + boost::thread( &X::f0, &x ).join(); + boost::thread( &X::f0, boost::ref(x) ).join(); + + boost::thread( &X::g0, &x ).join(); + boost::thread( &X::g0, x ).join(); + boost::thread( &X::g0, boost::ref(x) ).join(); + + // 1 + + boost::thread( &X::f1, &x, 1 ).join(); + boost::thread( &X::f1, boost::ref(x), 1 ).join(); + + boost::thread( &X::g1, &x, 1 ).join(); + boost::thread( &X::g1, x, 1 ).join(); + boost::thread( &X::g1, boost::ref(x), 1 ).join(); + + // 2 + + boost::thread( &X::f2, &x, 1, 2 ).join(); + boost::thread( &X::f2, boost::ref(x), 1, 2 ).join(); + + boost::thread( &X::g2, &x, 1, 2 ).join(); + boost::thread( &X::g2, x, 1, 2 ).join(); + boost::thread( &X::g2, boost::ref(x), 1, 2 ).join(); + + // 3 + + boost::thread( &X::f3, &x, 1, 2, 3 ).join(); + boost::thread( &X::f3, boost::ref(x), 1, 2, 3 ).join(); + + boost::thread( &X::g3, &x, 1, 2, 3 ).join(); + boost::thread( &X::g3, x, 1, 2, 3 ).join(); + boost::thread( &X::g3, boost::ref(x), 1, 2, 3 ).join(); + + // 4 + + boost::thread( &X::f4, &x, 1, 2, 3, 4 ).join(); + boost::thread( &X::f4, boost::ref(x), 1, 2, 3, 4 ).join(); + + boost::thread( &X::g4, &x, 1, 2, 3, 4 ).join(); + boost::thread( &X::g4, x, 1, 2, 3, 4 ).join(); + boost::thread( &X::g4, boost::ref(x), 1, 2, 3, 4 ).join(); + + // 5 + + boost::thread( &X::f5, &x, 1, 2, 3, 4, 5 ).join(); + boost::thread( &X::f5, boost::ref(x), 1, 2, 3, 4, 5 ).join(); + + boost::thread( &X::g5, &x, 1, 2, 3, 4, 5 ).join(); + boost::thread( &X::g5, x, 1, 2, 3, 4, 5 ).join(); + boost::thread( &X::g5, boost::ref(x), 1, 2, 3, 4, 5 ).join(); + + // 6 + + boost::thread( &X::f6, &x, 1, 2, 3, 4, 5, 6 ).join(); + boost::thread( &X::f6, boost::ref(x), 1, 2, 3, 4, 5, 6 ).join(); + + boost::thread( &X::g6, &x, 1, 2, 3, 4, 5, 6 ).join(); + boost::thread( &X::g6, x, 1, 2, 3, 4, 5, 6 ).join(); + boost::thread( &X::g6, boost::ref(x), 1, 2, 3, 4, 5, 6 ).join(); + + // 7 + + boost::thread( &X::f7, &x, 1, 2, 3, 4, 5, 6, 7).join(); + boost::thread( &X::f7, boost::ref(x), 1, 2, 3, 4, 5, 6, 7).join(); + + boost::thread( &X::g7, &x, 1, 2, 3, 4, 5, 6, 7).join(); + boost::thread( &X::g7, x, 1, 2, 3, 4, 5, 6, 7).join(); + boost::thread( &X::g7, boost::ref(x), 1, 2, 3, 4, 5, 6, 7).join(); + + // 8 + + boost::thread( &X::f8, &x, 1, 2, 3, 4, 5, 6, 7, 8 ).join(); + boost::thread( &X::f8, boost::ref(x), 1, 2, 3, 4, 5, 6, 7, 8 ).join(); + + boost::thread( &X::g8, &x, 1, 2, 3, 4, 5, 6, 7, 8 ).join(); + boost::thread( &X::g8, x, 1, 2, 3, 4, 5, 6, 7, 8 ).join(); + boost::thread( &X::g8, boost::ref(x), 1, 2, 3, 4, 5, 6, 7, 8 ).join(); + + BOOST_TEST( x.hash == 23558 ); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_thread_move.cpp b/src/boost/libs/thread/test/test_thread_move.cpp new file mode 100644 index 000000000..e86db8cad --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_move.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2007-9 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE Boost.Threads: thread move test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> + +void do_nothing(boost::thread::id* my_id) +{ + *my_id=boost::this_thread::get_id(); +} + +BOOST_AUTO_TEST_CASE(test_move_on_construction) +{ + boost::thread::id the_id; + boost::thread x=boost::thread(do_nothing,&the_id); + boost::thread::id x_id=x.get_id(); + x.join(); + BOOST_CHECK_EQUAL(the_id,x_id); +} + +boost::thread make_thread(boost::thread::id* the_id) +{ + return boost::thread(do_nothing,the_id); +} + +BOOST_AUTO_TEST_CASE(test_move_from_function_return) +{ + boost::thread::id the_id; + boost::thread x=make_thread(&the_id); + boost::thread::id x_id=x.get_id(); + x.join(); + BOOST_CHECK_EQUAL(the_id,x_id); +} + +BOOST_AUTO_TEST_CASE(test_move_assign) +{ + boost::thread::id the_id; + boost::thread x(do_nothing,&the_id); + boost::thread y; + y=boost::move(x); + boost::thread::id y_id=y.get_id(); + y.join(); + BOOST_CHECK_EQUAL(the_id,y_id); +} + + diff --git a/src/boost/libs/thread/test/test_thread_move_return.cpp b/src/boost/libs/thread/test/test_thread_move_return.cpp new file mode 100644 index 000000000..f714fb0a5 --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_move_return.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2009 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_USES_MOVE +#define BOOST_TEST_MODULE Boost.Threads: thread move return test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> + +void do_nothing(boost::thread::id* my_id) +{ + *my_id=boost::this_thread::get_id(); +} + +boost::thread make_thread_move_return(boost::thread::id* the_id) +{ + boost::thread t(do_nothing,the_id); + return boost::move(t); +} + +BOOST_AUTO_TEST_CASE(test_move_from_function_move_return) +{ + boost::thread::id the_id; + boost::thread x=make_thread_move_return(&the_id); + boost::thread::id x_id=x.get_id(); + x.join(); + BOOST_CHECK_EQUAL(the_id,x_id); +} + diff --git a/src/boost/libs/thread/test/test_thread_return_local.cpp b/src/boost/libs/thread/test/test_thread_return_local.cpp new file mode 100644 index 000000000..6ffd1083a --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_return_local.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2009 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_USES_MOVE + +#define BOOST_TEST_MODULE Boost.Threads: thread return local test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> + +void do_nothing(boost::thread::id* my_id) +{ + *my_id=boost::this_thread::get_id(); +} + +boost::thread make_thread_return_local(boost::thread::id* the_id) +{ + boost::thread t(do_nothing,the_id); + return boost::move(t); +} + +BOOST_AUTO_TEST_CASE(test_move_from_function_return_local) +{ + boost::thread::id the_id; + boost::thread x=make_thread_return_local(&the_id); + boost::thread::id x_id=x.get_id(); + x.join(); + BOOST_CHECK_EQUAL(the_id,x_id); +} diff --git a/src/boost/libs/thread/test/test_time_jumps.cpp b/src/boost/libs/thread/test/test_time_jumps.cpp new file mode 100644 index 000000000..706bafa47 --- /dev/null +++ b/src/boost/libs/thread/test/test_time_jumps.cpp @@ -0,0 +1,2398 @@ +#ifdef _WIN32 + #include <windows.h> +#else + #include <sys/time.h> +#endif + +#include "boost/bind/bind.hpp" +#include "boost/chrono.hpp" +#include "boost/chrono/ceil.hpp" +#include "boost/date_time.hpp" +#include "boost/thread/concurrent_queues/sync_priority_queue.hpp" +#include "boost/thread/concurrent_queues/sync_timed_queue.hpp" +#include "boost/thread/future.hpp" +#include "boost/thread/mutex.hpp" +#include "boost/thread/recursive_mutex.hpp" +#include "boost/thread/shared_lock_guard.hpp" +#include "boost/thread/shared_mutex.hpp" +#include "boost/thread/thread.hpp" + +#include <iomanip> +#ifdef TEST_CPP14_FEATURES +#include <future> +#include <mutex> +#include <shared_mutex> +#include <thread> +#endif + +/******************************************************************************/ + +/* + * Summary: + * + * This code tests the behavior of time-related functions in the presence of + * system clock changes (jumps). It requires root/Administrator privileges in + * order to run because it changes the system clock. NTP should also be disabled + * while running this code so that NTP can't change the system clock. + * + * Each function to be tested is executed five times. The amount of time the + * function waits before returning is measured against the amount of time the + * function was expected to wait. If the difference exceeds a threshold value + * (defined below) then the test fails. + * + * The following values are intentially: + * - more than 200 milliseconds + * - more than 200 milliseconds apart + * - not a multiple of 100 milliseconds + * - not a multiple of each other + * - don't sum or diff to a multiple of 100 milliseconds + */ +const long long s_waitMs = 580; +const long long s_shortJumpMs = 230; +const long long s_longJumpMs = 870; // Causes additional, unavoidable failures when BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC is disabled +const long long s_sleepBeforeJumpMs = 110; + +#ifdef _WIN32 +const long long s_maxEarlyErrorMs = 10 + + 100; // Windows is unpredictable, especially in a VM, so allow extra time if the function returns early +const long long s_maxLateErrorMs = 110 // due to polling, functions may not return for up to 100 milliseconds after they are supposed to + + 100; // Windows is slow, especially in a VM, so allow extra time for the functions to return +#else +const long long s_maxEarlyErrorMs = 10; +const long long s_maxLateErrorMs = 110; // Due to polling, functions may not return for up to 100 milliseconds after they are supposed to +#endif + +int g_numTestsRun = 0; +int g_numTestsPassed = 0; +int g_numTestsFailed = 0; + +/******************************************************************************/ + +// A custom clock based off the system clock but with a different epoch. + +namespace custom +{ + class custom_boost_clock + { + public: + typedef boost::chrono::microseconds duration; // intentionally not nanoseconds + typedef duration::rep rep; + typedef duration::period period; + typedef boost::chrono::time_point<custom_boost_clock> time_point; + static bool is_steady; + + static time_point now(); + }; + + bool custom_boost_clock::is_steady = false; + + custom_boost_clock::time_point custom_boost_clock::now() + { + return time_point(boost::chrono::ceil<duration>(boost::chrono::system_clock::now().time_since_epoch()) - boost::chrono::hours(10 * 365 * 24)); + } + +#ifdef TEST_CPP14_FEATURES + class custom_std_clock + { + public: + typedef std::chrono::microseconds duration; // intentionally not nanoseconds + typedef duration::rep rep; + typedef duration::period period; + typedef std::chrono::time_point<custom_std_clock> time_point; + static bool is_steady; + + static time_point now(); + }; + + bool custom_std_clock::is_steady = false; + + custom_std_clock::time_point custom_std_clock::now() + { + return time_point(std::chrono::duration_cast<duration>(std::chrono::system_clock::now().time_since_epoch()) - std::chrono::hours(10 * 365 * 24)); + } +#endif +} + +/******************************************************************************/ + +template <typename MutexType = boost::mutex, typename CondType = boost::condition_variable> +struct BoostHelper +{ + typedef MutexType mutex; + typedef CondType cond; + + typedef boost::lock_guard<MutexType> lock_guard; + typedef boost::unique_lock<MutexType> unique_lock; + + typedef boost::chrono::milliseconds milliseconds; + typedef boost::chrono::nanoseconds nanoseconds; + + typedef boost::chrono::system_clock system_clock; + typedef boost::chrono::steady_clock steady_clock; + typedef custom::custom_boost_clock custom_clock; + + typedef system_clock::time_point system_time_point; + typedef steady_clock::time_point steady_time_point; + typedef custom_clock::time_point custom_time_point; + + typedef boost::cv_status cv_status; + typedef boost::future_status future_status; + + typedef boost::packaged_task<bool> packaged_task; + typedef boost::future<bool> future; + typedef boost::shared_future<bool> shared_future; + + typedef boost::thread thread; + + static const milliseconds waitDur; + + template <typename T> + static void sleep_for(T d) + { + boost::this_thread::sleep_for(d); + } + + template <typename T> + static void sleep_for_no_int(T d) + { + boost::this_thread::no_interruption_point::sleep_for(d); + } + + template <typename T> + static void sleep_until(T t) + { + boost::this_thread::sleep_until(t); + } + + template <typename T> + static void sleep_until_no_int(T t) + { + boost::this_thread::no_interruption_point::sleep_until(t); + } + + static system_time_point systemNow() + { + return system_clock::now(); + } + + static steady_time_point steadyNow() + { + return steady_clock::now(); + } + + static custom_time_point customNow() + { + return custom_clock::now(); + } + + template <class ToDuration, class Rep, class Period> + static ToDuration duration_cast(const boost::chrono::duration<Rep, Period>& d) + { + return boost::chrono::duration_cast<ToDuration>(d); + } + + static milliseconds zero() + { + return milliseconds(0); + } +}; + +template <typename MutexType, typename CondType> +const typename BoostHelper<MutexType, CondType>::milliseconds +BoostHelper<MutexType, CondType>::waitDur = typename BoostHelper<MutexType, CondType>::milliseconds(s_waitMs); + +#ifdef TEST_CPP14_FEATURES +template <typename MutexType = std::mutex, typename CondType = std::condition_variable> +struct StdHelper +{ + typedef MutexType mutex; + typedef CondType cond; + + typedef std::lock_guard<MutexType> lock_guard; + typedef std::unique_lock<MutexType> unique_lock; + + typedef std::chrono::milliseconds milliseconds; + typedef std::chrono::nanoseconds nanoseconds; + + typedef std::chrono::system_clock system_clock; + typedef std::chrono::steady_clock steady_clock; + typedef custom::custom_std_clock custom_clock; + + typedef system_clock::time_point system_time_point; + typedef steady_clock::time_point steady_time_point; + typedef custom_clock::time_point custom_time_point; + + typedef std::cv_status cv_status; + typedef std::future_status future_status; + + typedef std::packaged_task<bool()> packaged_task; + typedef std::future<bool> future; + typedef std::shared_future<bool> shared_future; + + typedef std::thread thread; + + static const milliseconds waitDur; + + template <typename T> + static void sleep_for(T d) + { + std::this_thread::sleep_for(d); + } + + template <typename T> + static void sleep_until(T t) + { + std::this_thread::sleep_until(t); + } + + static system_time_point systemNow() + { + return system_clock::now(); + } + + static steady_time_point steadyNow() + { + return steady_clock::now(); + } + + static custom_time_point customNow() + { + return custom_clock::now(); + } + + template <class ToDuration, class Rep, class Period> + static ToDuration duration_cast(const std::chrono::duration<Rep, Period>& d) + { + return std::chrono::duration_cast<ToDuration>(d); + } + + static milliseconds zero() + { + return milliseconds(0); + } +}; + +template <typename MutexType, typename CondType> +const typename StdHelper<MutexType, CondType>::milliseconds +StdHelper<MutexType, CondType>::waitDur = typename StdHelper<MutexType, CondType>::milliseconds(s_waitMs); +#endif + +/******************************************************************************/ + +#ifdef _WIN32 + +void changeSystemTime(long long changeMs) +{ + Sleep(s_sleepBeforeJumpMs); + + SYSTEMTIME systemTime; + GetSystemTime(&systemTime); + + FILETIME fileTime; + if (!SystemTimeToFileTime(&systemTime, &fileTime)) + { + std::cout << "ERROR: Couldn't convert system time to file time" << std::endl; + } + + ULARGE_INTEGER largeInt; + largeInt.LowPart = fileTime.dwLowDateTime; + largeInt.HighPart = fileTime.dwHighDateTime; + largeInt.QuadPart += changeMs * 10000; + fileTime.dwLowDateTime = largeInt.LowPart; + fileTime.dwHighDateTime = largeInt.HighPart; + + if (!FileTimeToSystemTime(&fileTime, &systemTime)) + { + std::cout << "ERROR: Couldn't convert file time to system time" << std::endl; + } + + if (!SetSystemTime(&systemTime)) + { + std::cout << "ERROR: Couldn't set system time" << std::endl; + } +} + +#else + +void changeSystemTime(long long changeMs) +{ + struct timespec sleepTs; + sleepTs.tv_sec = (s_sleepBeforeJumpMs / 1000); + sleepTs.tv_nsec = (s_sleepBeforeJumpMs % 1000) * 1000000; + nanosleep(&sleepTs, NULL); + + struct timeval tv; + if (gettimeofday(&tv, NULL) != 0) + { + std::cout << "ERROR: Couldn't get system time" << std::endl; + } + + changeMs += tv.tv_sec * 1000; + changeMs += tv.tv_usec / 1000; + tv.tv_sec = (changeMs / 1000); + tv.tv_usec = (changeMs % 1000) * 1000; + + if (settimeofday(&tv, NULL) != 0) + { + std::cout << "ERROR: Couldn't set system time" << std::endl; + } +} + +#endif + +enum RcEnum +{ + e_no_timeout, + e_timeout, + e_failed_bad, + e_failed_good, + e_succeeded_bad, + e_succeeded_good, + e_ready_bad, + e_not_ready_good, + e_na +}; + +template <typename Helper> +void checkWaitTime(typename Helper::nanoseconds expected, typename Helper::nanoseconds actual, RcEnum rc) +{ + if (expected != Helper::zero() && expected < typename Helper::milliseconds(s_sleepBeforeJumpMs)) + { + expected = typename Helper::milliseconds(s_sleepBeforeJumpMs); + } + + typename Helper::milliseconds expectedMs = Helper::template duration_cast<typename Helper::milliseconds>(expected); + typename Helper::milliseconds actualMs = Helper::template duration_cast<typename Helper::milliseconds>(actual); + + std::cout << "Expected: " << std::setw(4) << expectedMs.count() << " ms" + << ", Actual: " << std::setw(4) << actualMs.count() << " ms" + << ", Returned: "; + switch (rc) + { + case e_no_timeout : std::cout << "no_timeout, "; break; + case e_timeout : std::cout << "timeout, "; break; + case e_failed_bad : std::cout << "failed, "; break; + case e_failed_good : std::cout << "failed, "; break; + case e_succeeded_bad : std::cout << "succeeded, "; break; + case e_succeeded_good : std::cout << "succeeded, "; break; + case e_ready_bad : std::cout << "ready, "; break; + case e_not_ready_good : std::cout << "not_ready, "; break; + default : std::cout << "N/A, "; break; + } + + if (expectedMs == Helper::zero()) + { + std::cout << "FAILED: SKIPPED (test would lock up if run)"; + g_numTestsFailed++; + } + else if (actual < expected - typename Helper::milliseconds(s_maxEarlyErrorMs)) + { + std::cout << "FAILED: TOO SHORT"; + if (rc == e_timeout) // bad + { + std::cout << ", RETURNED TIMEOUT"; + } + else if (rc == e_failed_bad) + { + std::cout << ", RETURNED FAILED"; + } + else if (rc == e_succeeded_bad) + { + std::cout << ", RETURNED SUCCEEDED"; + } + else if (rc == e_ready_bad) + { + std::cout << ", RETURNED READY"; + } + g_numTestsFailed++; + } + else if (actual > expected + typename Helper::milliseconds(s_maxLateErrorMs)) + { + std::cout << "FAILED: TOO LONG"; + if (rc == e_no_timeout) // bad + { + std::cout << ", RETURNED NO_TIMEOUT"; + } + else if (rc == e_failed_bad) + { + std::cout << ", RETURNED FAILED"; + } + else if (rc == e_succeeded_bad) + { + std::cout << ", RETURNED SUCCEEDED"; + } + else if (rc == e_ready_bad) + { + std::cout << ", RETURNED READY"; + } + g_numTestsFailed++; + } + else if (rc == e_no_timeout) // bad + { + std::cout << "FAILED: RETURNED NO_TIMEOUT"; + g_numTestsFailed++; + } + else if (rc == e_failed_bad) + { + std::cout << "FAILED: RETURNED FAILED"; + g_numTestsFailed++; + } + else if (rc == e_succeeded_bad) + { + std::cout << "FAILED: RETURNED SUCCEEDED"; + g_numTestsFailed++; + } + else if (rc == e_ready_bad) + { + std::cout << "FAILED: RETURNED READY"; + g_numTestsFailed++; + } + else + { + std::cout << "Passed"; + g_numTestsPassed++; + } + std::cout << std::endl; + + g_numTestsRun++; +} + +void sleepForLongTime() +{ +#ifdef _WIN32 + Sleep(10000); +#else + struct timespec ts = {5, 0}; + nanosleep(&ts, NULL); +#endif +} + +bool returnFalse() +{ + return false; +} + +/******************************************************************************/ + +// Run the test in the context provided, which may be the current thread or a separate thread. +template <typename Helper, typename Context, typename Function> +void runTestInContext(Context context, Function func, const std::string name) +{ + std::cout << name << ":" << std::endl; + + { + std::cout << " While system clock remains stable: "; + context(func, 0); + } + + { + std::cout << " While system clock jumps back (short): "; + typename Helper::thread t(boost::bind(changeSystemTime, -s_shortJumpMs)); + context(func, -s_shortJumpMs); + t.join(); + } + + { + std::cout << " While system clock jumps back (long): "; + typename Helper::thread t(boost::bind(changeSystemTime, -s_longJumpMs)); + context(func, -s_longJumpMs); + t.join(); + } + + { + std::cout << " While system clock jumps forward (short): "; + typename Helper::thread t(boost::bind(changeSystemTime, s_shortJumpMs)); + context(func, s_shortJumpMs); + t.join(); + } + + { + std::cout << " While system clock jumps forward (long): "; + typename Helper::thread t(boost::bind(changeSystemTime, s_longJumpMs)); + context(func, s_longJumpMs); + t.join(); + } +} + +//-------------------------------------- + +template <typename Helper, typename Function> +void noThreadContext(Function func, const long long jumpMs) +{ + func(jumpMs); +} + +template <typename Helper, typename Function> +void threadContextWithNone(Function func, const long long jumpMs) +{ + typename Helper::thread t(boost::bind(func, jumpMs)); + t.join(); +} + +template <typename Helper, typename Function> +void threadContextWithUnique(Function func, const long long jumpMs) +{ + typename Helper::mutex m; + typename Helper::lock_guard g(m); + typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs)); + t.join(); +} + +template <typename Helper, typename Function> +void threadContextWithShared(Function func, const long long jumpMs) +{ + typename Helper::mutex m; + boost::shared_lock_guard<typename Helper::mutex> g(m); + typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs)); + t.join(); +} + +template <typename Helper, typename Function> +void threadContextWithUpgrade(Function func, const long long jumpMs) +{ + typename Helper::mutex m; + boost::upgrade_lock<typename Helper::mutex> g(m); + typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs)); + t.join(); +} + +//-------------------------------------- + +// Run the test in the current thread. +template <typename Helper, typename Function> +void runTest(Function func, const std::string name) +{ + runTestInContext<Helper>(noThreadContext<Helper, Function>, func, name); +} + +// Run the test in a separate thread. +template <typename Helper, typename Function> +void runTestWithNone(Function func, const std::string name) +{ + runTestInContext<Helper>(threadContextWithNone<Helper, Function>, func, name); +} + +// Run the test in a separate thread. Pass a locked mutex to the function under test. +template <typename Helper, typename Function> +void runTestWithUnique(Function func, const std::string name) +{ + runTestInContext<Helper>(threadContextWithUnique<Helper, Function>, func, name); +} + +// Run the test in a separate thread. Pass a shared-locked mutex to the function under test. +template <typename Helper, typename Function> +void runTestWithShared(Function func, const std::string name) +{ + runTestInContext<Helper>(threadContextWithShared<Helper, Function>, func, name); +} + +// Run the test in a separate thread. Pass an upgrade-locked mutex to the function under test. +template <typename Helper, typename Function> +void runTestWithUpgrade(Function func, const std::string name) +{ + runTestInContext<Helper>(threadContextWithUpgrade<Helper, Function>, func, name); +} + +/******************************************************************************/ + +// Test Sleep + +template <typename Helper> +void testSleepFor(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +} + +template <typename Helper> +void testSleepUntilSteady(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +} + +template <typename Helper> +void testSleepUntilSystem(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +} + +template <typename Helper> +void testSleepUntilCustom(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +} + +//-------------------------------------- + +template <typename Helper> +void testSleepRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + boost::this_thread::sleep(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testSleepAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + boost::this_thread::sleep(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testSleepStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testSleepFor <Helper>, name + "::this_thread::sleep_for()"); + runTestWithNone<Helper>(testSleepUntilSteady<Helper>, name + "::this_thread::sleep_until(), steady time"); + runTestWithNone<Helper>(testSleepUntilSystem<Helper>, name + "::this_thread::sleep_until(), system time"); + runTestWithNone<Helper>(testSleepUntilCustom<Helper>, name + "::this_thread::sleep_until(), custom time"); +} + +template <typename Helper> +void testSleepBoost(const std::string& name) +{ + testSleepStd<Helper>(name); + + // Boost-only functions + runTestWithNone<Helper>(testSleepRelative<Helper>, name + "::this_thread::sleep(), relative time"); + runTestWithNone<Helper>(testSleepAbsolute<Helper>, name + "::this_thread::sleep(), absolute time"); +} + +template <typename Helper> +void testSleepNoThreadStd(const std::string& name) +{ + std::cout << std::endl; + runTest<Helper>(testSleepFor <Helper>, name + "::this_thread::sleep_for(), no thread"); + runTest<Helper>(testSleepUntilSteady<Helper>, name + "::this_thread::sleep_until(), no thread, steady time"); + runTest<Helper>(testSleepUntilSystem<Helper>, name + "::this_thread::sleep_until(), no thread, system time"); + runTest<Helper>(testSleepUntilCustom<Helper>, name + "::this_thread::sleep_until(), no thread, custom time"); +} + +template <typename Helper> +void testSleepNoThreadBoost(const std::string& name) +{ + testSleepNoThreadStd<Helper>(name); + + // Boost-only functions + runTest<Helper>(testSleepRelative<Helper>, name + "::this_thread::sleep(), no thread, relative time"); + runTest<Helper>(testSleepAbsolute<Helper>, name + "::this_thread::sleep(), no thread, absolute time"); +} + +/******************************************************************************/ + +// Test Sleep, No Interruption Point + +template <typename Helper> +void testSleepForNoInt(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_for_no_int(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +} + +template <typename Helper> +void testSleepUntilNoIntSteady(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until_no_int(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +} + +template <typename Helper> +void testSleepUntilNoIntSystem(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until_no_int(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +} + +template <typename Helper> +void testSleepUntilNoIntCustom(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until_no_int(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +} + +//-------------------------------------- + +#ifndef SKIP_NO_INT_SLEEP + +template <typename Helper> +void testSleepNoIntRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + boost::this_thread::no_interruption_point::sleep(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testSleepNoIntAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + boost::this_thread::no_interruption_point::sleep(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +#endif + +//-------------------------------------- + +// Only Boost supports no_interruption_point + +template <typename Helper> +void testSleepNoIntBoost(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testSleepForNoInt <Helper>, name + "::this_thread::no_interruption_point::sleep_for()"); + runTestWithNone<Helper>(testSleepUntilNoIntSteady<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), steady time"); + runTestWithNone<Helper>(testSleepUntilNoIntSystem<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), system time"); + runTestWithNone<Helper>(testSleepUntilNoIntCustom<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), custom time"); + +#ifndef SKIP_NO_INT_SLEEP + runTestWithNone<Helper>(testSleepNoIntRelative<Helper>, name + "::this_thread::no_interruption_point::sleep(), relative time"); + runTestWithNone<Helper>(testSleepNoIntAbsolute<Helper>, name + "::this_thread::no_interruption_point::sleep(), absolute time"); +#endif +} + +template <typename Helper> +void testSleepNoThreadNoIntBoost(const std::string& name) +{ + std::cout << std::endl; + runTest<Helper>(testSleepForNoInt <Helper>, name + "::this_thread::no_interruption_point::sleep_for(), no thread"); + runTest<Helper>(testSleepUntilNoIntSteady<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, steady time"); + runTest<Helper>(testSleepUntilNoIntSystem<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, system time"); + runTest<Helper>(testSleepUntilNoIntCustom<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, custom time"); + +#ifndef SKIP_NO_INT_SLEEP + runTest<Helper>(testSleepNoIntRelative<Helper>, name + "::this_thread::no_interruption_point::sleep(), no thread, relative time"); + runTest<Helper>(testSleepNoIntAbsolute<Helper>, name + "::this_thread::no_interruption_point::sleep(), no thread, absolute time"); +#endif +} + +/******************************************************************************/ + +// Test Try Join + +template <typename Helper> +void testTryJoinFor(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.try_join_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryJoinUntilSteady(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.try_join_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryJoinUntilSystem(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.try_join_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryJoinUntilCustom(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.try_join_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTimedJoinRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.timed_join(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testTimedJoinAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.timed_join(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +// Only Boost supports timed try_join functions + +template <typename Helper> +void testJoinBoost(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testTryJoinFor <Helper>, name + "::thread::try_join_for()"); + runTestWithNone<Helper>(testTryJoinUntilSteady<Helper>, name + "::thread::try_join_until(), steady time"); + runTestWithNone<Helper>(testTryJoinUntilSystem<Helper>, name + "::thread::try_join_until(), system time"); + runTestWithNone<Helper>(testTryJoinUntilCustom<Helper>, name + "::thread::try_join_until(), custom time"); + runTestWithNone<Helper>(testTimedJoinRelative <Helper>, name + "::thread::timed_join(), relative time"); + runTestWithNone<Helper>(testTimedJoinAbsolute <Helper>, name + "::thread::timed_join(), absolute time"); +} + +/******************************************************************************/ + +// Test Condition Variable Wait + +template <typename Helper> +void testCondVarWaitFor(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = (cv.wait_for(g, Helper::waitDur) == Helper::cv_status::no_timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilSteady(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = (cv.wait_until(g, Helper::steadyNow() + Helper::waitDur) == Helper::cv_status::no_timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilSystem(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = (cv.wait_until(g, Helper::systemNow() + Helper::waitDur) == Helper::cv_status::no_timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilCustom(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = (cv.wait_until(g, Helper::customNow() + Helper::waitDur) == Helper::cv_status::no_timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +} + +//-------------------------------------- + +template <typename Helper> +void testCondVarTimedWaitRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = cv.timed_wait(g, ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testCondVarTimedWaitAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = cv.timed_wait(g, ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testCondVarStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testCondVarWaitFor <Helper>, name + "::wait_for()"); + runTestWithNone<Helper>(testCondVarWaitUntilSteady<Helper>, name + "::wait_until(), steady time"); + runTestWithNone<Helper>(testCondVarWaitUntilSystem<Helper>, name + "::wait_until(), system time"); + runTestWithNone<Helper>(testCondVarWaitUntilCustom<Helper>, name + "::wait_until(), custom time"); +} + +template <typename Helper> +void testCondVarBoost(const std::string& name) +{ + testCondVarStd<Helper>(name); + + // Boost-only functions + runTestWithNone<Helper>(testCondVarTimedWaitRelative<Helper>, name + "::timed_wait(), relative time"); + runTestWithNone<Helper>(testCondVarTimedWaitAbsolute<Helper>, name + "::timed_wait(), absolute time"); +} + +/******************************************************************************/ + +// Test Condition Variable Wait with Predicate + +template <typename Helper> +void testCondVarWaitForPred(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = cv.wait_for(g, Helper::waitDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilPredSteady(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = cv.wait_until(g, Helper::steadyNow() + Helper::waitDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilPredSystem(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = cv.wait_until(g, Helper::systemNow() + Helper::waitDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilPredCustom(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = cv.wait_until(g, Helper::customNow() + Helper::waitDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +} + +//-------------------------------------- + +template <typename Helper> +void testCondVarTimedWaitPredRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = cv.timed_wait(g, ptDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testCondVarTimedWaitPredAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = cv.timed_wait(g, ptNow + ptDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testCondVarPredStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testCondVarWaitForPred <Helper>, name + "::wait_for(), with predicate"); + runTestWithNone<Helper>(testCondVarWaitUntilPredSteady<Helper>, name + "::wait_until(), with predicate, steady time"); + runTestWithNone<Helper>(testCondVarWaitUntilPredSystem<Helper>, name + "::wait_until(), with predicate, system time"); + runTestWithNone<Helper>(testCondVarWaitUntilPredCustom<Helper>, name + "::wait_until(), with predicate, custom time"); +} + +template <typename Helper> +void testCondVarPredBoost(const std::string& name) +{ + testCondVarPredStd<Helper>(name); + + // Boost-only functions + runTestWithNone<Helper>(testCondVarTimedWaitPredRelative<Helper>, name + "::timed_wait(), with predicate, relative time"); + runTestWithNone<Helper>(testCondVarTimedWaitPredAbsolute<Helper>, name + "::timed_wait(), with predicate, absolute time"); +} + +/******************************************************************************/ + +// Test Try Lock + +template <typename Helper> +void testTryLockFor(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTimedLockRelative(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testTimedLockAbsolute(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testMutexStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithUnique<Helper>(testTryLockFor <Helper>, name + "::try_lock_for()"); + runTestWithUnique<Helper>(testTryLockUntilSteady<Helper>, name + "::try_lock_until(), steady time"); + runTestWithUnique<Helper>(testTryLockUntilSystem<Helper>, name + "::try_lock_until(), system time"); + runTestWithUnique<Helper>(testTryLockUntilCustom<Helper>, name + "::try_lock_until(), custom time"); +} + +template <typename Helper> +void testMutexBoost(const std::string& name) +{ + testMutexStd<Helper>(name); + + // Boost-only functions + runTestWithUnique<Helper>(testTimedLockRelative<Helper>, name + "::timed_lock(), relative time"); + runTestWithUnique<Helper>(testTimedLockAbsolute<Helper>, name + "::timed_lock(), absolute time"); +} + +/******************************************************************************/ + +// Test Try Lock Shared + +template <typename Helper> +void testTryLockSharedFor(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_shared_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockSharedUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_shared_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockSharedUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_shared_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockSharedUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_shared_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTimedLockSharedRelative(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock_shared(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testTimedLockSharedAbsolute(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock_shared(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testMutexSharedStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithUnique<Helper>(testTryLockSharedFor <Helper>, name + "::try_lock_shared_for()"); + runTestWithUnique<Helper>(testTryLockSharedUntilSteady<Helper>, name + "::try_lock_shared_until(), steady time"); + runTestWithUnique<Helper>(testTryLockSharedUntilSystem<Helper>, name + "::try_lock_shared_until(), system time"); + runTestWithUnique<Helper>(testTryLockSharedUntilCustom<Helper>, name + "::try_lock_shared_until(), custom time"); +} + +template <typename Helper> +void testMutexSharedBoost(const std::string& name) +{ + testMutexSharedStd<Helper>(name); + + // Boost-only functions + runTestWithUnique<Helper>(testTimedLockSharedRelative<Helper>, name + "::timed_lock_shared(), relative time"); + runTestWithUnique<Helper>(testTimedLockSharedAbsolute<Helper>, name + "::timed_lock_shared(), absolute time"); +} + +/******************************************************************************/ + +// Test Try Lock Upgrade + +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + +template <typename Helper> +void testTryLockUpgradeFor(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_upgrade_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUpgradeUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_upgrade_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUpgradeUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_upgrade_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUpgradeUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_upgrade_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTimedLockUpgradeRelative(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock_upgrade(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testTimedLockUpgradeAbsolute(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock_upgrade(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testTryUnlockSharedAndLockFor(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTryUnlockUpgradeAndLockFor(typename Helper::mutex& m, const long long jumpMs) +{ + boost::upgrade_lock<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_upgrade_and_lock_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockUpgradeAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + boost::upgrade_lock<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockUpgradeAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + boost::upgrade_lock<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockUpgradeAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + boost::upgrade_lock<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTryUnlockSharedAndLockUpgradeFor(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_upgrade_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUpgradeUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUpgradeUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUpgradeUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +#endif + +//-------------------------------------- + +// Only Boost supports upgrade mutexes + +template <typename Helper> +void testMutexUpgradeBoost(const std::string& name) +{ +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + std::cout << std::endl; + runTestWithUnique<Helper>(testTryLockUpgradeFor <Helper>, name + "::try_lock_upgrade_for()"); + runTestWithUnique<Helper>(testTryLockUpgradeUntilSteady<Helper>, name + "::try_lock_upgrade_until(), steady time"); + runTestWithUnique<Helper>(testTryLockUpgradeUntilSystem<Helper>, name + "::try_lock_upgrade_until(), system time"); + runTestWithUnique<Helper>(testTryLockUpgradeUntilCustom<Helper>, name + "::try_lock_upgrade_until(), custom time"); + runTestWithUnique<Helper>(testTimedLockUpgradeRelative <Helper>, name + "::timed_lock_upgrade(), relative time"); + runTestWithUnique<Helper>(testTimedLockUpgradeAbsolute <Helper>, name + "::timed_lock_upgrade(), absolute time"); + + std::cout << std::endl; + runTestWithShared<Helper>(testTryUnlockSharedAndLockFor <Helper>, name + "::try_unlock_shared_and_lock_for()"); + runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilSteady<Helper>, name + "::try_unlock_shared_and_lock_until(), steady time"); + runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilSystem<Helper>, name + "::try_unlock_shared_and_lock_until(), system time"); + runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilCustom<Helper>, name + "::try_unlock_shared_and_lock_until(), custom time"); + + std::cout << std::endl; + runTestWithShared<Helper>(testTryUnlockUpgradeAndLockFor <Helper>, name + "::try_unlock_upgrade_and_lock_for()"); + runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilSteady<Helper>, name + "::try_unlock_upgrade_and_lock_until(), steady time"); + runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilSystem<Helper>, name + "::try_unlock_upgrade_and_lock_until(), system time"); + runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilCustom<Helper>, name + "::try_unlock_upgrade_and_lock_until(), custom time"); + + std::cout << std::endl; + runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockFor <Helper>, name + "::try_unlock_shared_and_lock_upgrade_for()"); + runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilSteady<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), steady time"); + runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilSystem<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), system time"); + runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilCustom<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), custom time"); +#endif +} + +/******************************************************************************/ + +// Test Future Wait + +template <typename Helper> +void testFutureWaitFor(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (f.wait_for(Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testFutureWaitUntilSteady(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (f.wait_until(Helper::steadyNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testFutureWaitUntilSystem(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (f.wait_until(Helper::systemNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testFutureWaitUntilCustom(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (f.wait_until(Helper::customNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +//-------------------------------------- + +template <typename Helper> +void testFutureTimedWaitRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = f.timed_wait(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testFutureTimedWaitAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = f.timed_wait_until(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testFutureStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testFutureWaitFor <Helper>, name + "::wait_for()"); + runTestWithNone<Helper>(testFutureWaitUntilSteady<Helper>, name + "::wait_until(), steady time"); + runTestWithNone<Helper>(testFutureWaitUntilSystem<Helper>, name + "::wait_until(), system time"); + runTestWithNone<Helper>(testFutureWaitUntilCustom<Helper>, name + "::wait_until(), custom time"); +} + +template <typename Helper> +void testFutureBoost(const std::string& name) +{ + testFutureStd<Helper>(name); + + // Boost-only functions + runTestWithNone<Helper>(testFutureTimedWaitRelative<Helper>, name + "::timed_wait(), relative time"); + runTestWithNone<Helper>(testFutureTimedWaitAbsolute<Helper>, name + "::timed_wait_until(), absolute time"); +} + +/******************************************************************************/ + +// Test Shared Future Wait + +template <typename Helper> +void testSharedFutureWaitFor(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (sf.wait_for(Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSharedFutureWaitUntilSteady(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (sf.wait_until(Helper::steadyNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSharedFutureWaitUntilSystem(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (sf.wait_until(Helper::systemNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSharedFutureWaitUntilCustom(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (sf.wait_until(Helper::customNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +//-------------------------------------- + +template <typename Helper> +void testSharedFutureTimedWaitRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = sf.timed_wait(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testSharedFutureTimedWaitAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = sf.timed_wait_until(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testSharedFutureStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testSharedFutureWaitFor <Helper>, name + "::wait_for()"); + runTestWithNone<Helper>(testSharedFutureWaitUntilSteady<Helper>, name + "::wait_until(), steady time"); + runTestWithNone<Helper>(testSharedFutureWaitUntilSystem<Helper>, name + "::wait_until(), system time"); + runTestWithNone<Helper>(testSharedFutureWaitUntilCustom<Helper>, name + "::wait_until(), custom time"); +} + +template <typename Helper> +void testSharedFutureBoost(const std::string& name) +{ + testSharedFutureStd<Helper>(name); + + // Boost-only functions + runTestWithNone<Helper>(testSharedFutureTimedWaitRelative<Helper>, name + "::timed_wait(), relative time"); + runTestWithNone<Helper>(testSharedFutureTimedWaitAbsolute<Helper>, name + "::timed_wait_until(), absolute time"); +} + +/******************************************************************************/ + +// Test Sync Priority Queue + +template <typename Helper> +void testSyncPriorityQueuePullFor(const long long jumpMs) +{ + boost::sync_priority_queue<int> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncPriorityQueuePullUntilSteady(const long long jumpMs) +{ + boost::sync_priority_queue<int> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncPriorityQueuePullUntilSystem(const long long jumpMs) +{ + boost::sync_priority_queue<int> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncPriorityQueuePullUntilCustom(const long long jumpMs) +{ + boost::sync_priority_queue<int> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +//-------------------------------------- + +// Only Boost supports sync_priority_queue + +template <typename Helper> +void testSyncPriorityQueueBoost(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testSyncPriorityQueuePullFor <Helper>, name + "::pull_for()"); + runTestWithNone<Helper>(testSyncPriorityQueuePullUntilSteady<Helper>, name + "::pull_until(), steady time"); + runTestWithNone<Helper>(testSyncPriorityQueuePullUntilSystem<Helper>, name + "::pull_until(), system time"); + runTestWithNone<Helper>(testSyncPriorityQueuePullUntilCustom<Helper>, name + "::pull_until(), custom time"); +} + +/******************************************************************************/ + +// Test Sync Timed Queue + +template <typename Helper> +void testSyncTimedQueuePullForEmptySteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncTimedQueuePullForEmptySystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncTimedQueuePullForEmptyCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilEmptySteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilEmptySystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilEmptyCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +//-------------------------------------- + +template <typename Helper> +void testSyncTimedQueuePullForNotReadySteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullForNotReadySystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullForNotReadyCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilNotReadySteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilNotReadySystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilNotReadyCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +//-------------------------------------- + +template <typename Helper> +void testSyncTimedQueuePullForSucceedsSteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + q.push(0, Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullForSucceedsSystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + q.push(0, Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullForSucceedsCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + q.push(0, Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilSucceedsSteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + q.push(0, Helper::steadyNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_until(Helper::steadyNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilSucceedsSystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + q.push(0, Helper::systemNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_until(Helper::systemNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilSucceedsCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + q.push(0, Helper::customNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_until(Helper::customNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +//-------------------------------------- + +template <typename Helper> +void testSyncTimedQueueWaitPullSucceedsSteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + q.push(0, Helper::steadyNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueueWaitPullSucceedsSystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + q.push(0, Helper::systemNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueueWaitPullSucceedsCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + q.push(0, Helper::customNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +//-------------------------------------- + +// Only Boost supports sync_timed_queue + +template <typename Helper> +void testSyncTimedQueueBoost(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testSyncTimedQueuePullForEmptySteady <Helper>, name + "::pull_for(), empty, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForEmptySystem <Helper>, name + "::pull_for(), empty, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForEmptyCustom <Helper>, name + "::pull_for(), empty, custom time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptySteady<Helper>, name + "::pull_until(), empty, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptySystem<Helper>, name + "::pull_until(), empty, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptyCustom<Helper>, name + "::pull_until(), empty, custom time"); + + std::cout << std::endl; + runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadySteady <Helper>, name + "::pull_for(), not ready, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadySystem <Helper>, name + "::pull_for(), not ready, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadyCustom <Helper>, name + "::pull_for(), not ready, custom time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadySteady<Helper>, name + "::pull_until(), not ready, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadySystem<Helper>, name + "::pull_until(), not ready, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadyCustom<Helper>, name + "::pull_until(), not ready, custom time"); + + std::cout << std::endl; + runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsSteady <Helper>, name + "::pull_for(), succeeds, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsSystem <Helper>, name + "::pull_for(), succeeds, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsCustom <Helper>, name + "::pull_for(), succeeds, custom time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsSteady<Helper>, name + "::pull_until(), succeeds, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsSystem<Helper>, name + "::pull_until(), succeeds, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsCustom<Helper>, name + "::pull_until(), succeeds, custom time"); + + std::cout << std::endl; + runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsSteady<Helper>, name + "::wait_pull(), succeeds, steady time"); + runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsSystem<Helper>, name + "::wait_pull(), succeeds, system time"); + runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsCustom<Helper>, name + "::wait_pull(), succeeds, custom time"); +} + +/******************************************************************************/ + +int main() +{ + std::cout << std::endl; + std::cout << "INFO: This test requires root/Administrator privileges in order to change the system clock." << std::endl; + std::cout << "INFO: Disable NTP while running this test to prevent NTP from changing the system clock." << std::endl; + std::cout << std::endl; + + std::cout << "BOOST_HAS_PTHREAD_DELAY_NP: "; +#ifdef BOOST_HAS_PTHREAD_DELAY_NP + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_HAS_NANOSLEEP: "; +#ifdef BOOST_HAS_NANOSLEEP + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_THREAD_SLEEP_FOR_IS_STEADY: "; +#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "CLOCK_MONOTONIC: "; +#ifdef CLOCK_MONOTONIC + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN: "; +#ifdef BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS: "; +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_THREAD_V2_SHARED_MUTEX: "; +#ifdef BOOST_THREAD_V2_SHARED_MUTEX + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC: "; +#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << std::endl; + std::cout << "Wait Time: " << s_waitMs << " ms" << std::endl; + std::cout << "Short Jump Time: " << s_shortJumpMs << " ms" << std::endl; + std::cout << "Long Jump Time: " << s_longJumpMs << " ms" << std::endl; + std::cout << "Sleep Before Jump Time: " << s_sleepBeforeJumpMs << " ms" << std::endl; + std::cout << "Max Early Error: " << s_maxEarlyErrorMs << " ms" << std::endl; + std::cout << "Max Late Error: " << s_maxLateErrorMs << " ms" << std::endl; + + testSleepBoost <BoostHelper< > >("boost"); + testSleepNoIntBoost <BoostHelper< > >("boost"); + testSleepNoThreadBoost <BoostHelper< > >("boost"); + testSleepNoThreadNoIntBoost<BoostHelper< > >("boost"); + testJoinBoost <BoostHelper< > >("boost"); + testCondVarBoost <BoostHelper<boost::mutex, boost::condition_variable > >("boost::condition_variable"); + testCondVarPredBoost <BoostHelper<boost::mutex, boost::condition_variable > >("boost::condition_variable"); + testCondVarBoost <BoostHelper<boost::mutex, boost::condition_variable_any> >("boost::condition_variable_any"); + testCondVarPredBoost <BoostHelper<boost::mutex, boost::condition_variable_any> >("boost::condition_variable_any"); + testMutexBoost <BoostHelper<boost::timed_mutex > >("boost::timed_mutex"); + testMutexBoost <BoostHelper<boost::recursive_timed_mutex > >("boost::recursive_timed_mutex"); + testMutexBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex + testMutexSharedBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex + testMutexUpgradeBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex + testFutureBoost <BoostHelper< > >("boost::future"); + testSharedFutureBoost <BoostHelper< > >("boost::shared_future"); + testSyncPriorityQueueBoost <BoostHelper< > >("boost::sync_priority_queue"); + testSyncTimedQueueBoost <BoostHelper< > >("boost::sync_timed_queue"); + +#ifdef TEST_CPP14_FEATURES + testSleepStd <StdHelper< > >("std"); + testSleepNoThreadStd<StdHelper< > >("std"); + testCondVarStd <StdHelper<std::mutex, std::condition_variable > >("std::condition_variable"); + testCondVarPredStd <StdHelper<std::mutex, std::condition_variable > >("std::condition_variable"); + testCondVarStd <StdHelper<std::mutex, std::condition_variable_any> >("std::condition_variable_any"); + testCondVarPredStd <StdHelper<std::mutex, std::condition_variable_any> >("std::condition_variable_any"); + testMutexStd <StdHelper<std::timed_mutex > >("std::timed_mutex"); + testMutexStd <StdHelper<std::recursive_timed_mutex > >("std::recursive_timed_mutex"); + testMutexStd <StdHelper<std::shared_timed_mutex > >("std::shared_timed_mutex"); + testMutexSharedStd <StdHelper<std::shared_timed_mutex > >("std::shared_timed_mutex"); + testFutureStd <StdHelper< > >("std::future"); + testSharedFutureStd <StdHelper< > >("std::shared_future"); +#endif + + std::cout << std::endl; + std::cout << "Number of Tests Run: " << g_numTestsRun << std::endl; + std::cout << "Number of Tests Passed: " << g_numTestsPassed << std::endl; + std::cout << "Number of Tests Failed: " << g_numTestsFailed << std::endl; + + return 0; +} diff --git a/src/boost/libs/thread/test/test_tss.cpp b/src/boost/libs/thread/test/test_tss.cpp new file mode 100644 index 000000000..08bbddc0c --- /dev/null +++ b/src/boost/libs/thread/test/test_tss.cpp @@ -0,0 +1,511 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +#define BOOST_TEST_MODULE Boost.Threads: tss test suite + +#include <boost/thread/detail/config.hpp> +#include <boost/predef/platform.h> + +#include <boost/thread/tss.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> + +#include <boost/test/unit_test.hpp> + +#include "./util.inl" + +#include <iostream> + +#if defined(BOOST_THREAD_PLATFORM_WIN32) + #define WIN32_LEAN_AND_MEAN + #include <windows.h> +#endif + +boost::mutex check_mutex; +boost::mutex tss_mutex; +int tss_instances = 0; +int tss_total = 0; + +struct tss_value_t +{ + tss_value_t() + { + boost::unique_lock<boost::mutex> lock(tss_mutex); + ++tss_instances; + ++tss_total; + value = 0; + } + ~tss_value_t() + { + boost::unique_lock<boost::mutex> lock(tss_mutex); + --tss_instances; + } + int value; +}; + +boost::thread_specific_ptr<tss_value_t> tss_value; + +void test_tss_thread() +{ + tss_value.reset(new tss_value_t()); + for (int i=0; i<1000; ++i) + { + int& n = tss_value->value; + // Don't call BOOST_CHECK_EQUAL directly, as it doesn't appear to + // be thread safe. Must evaluate further. + if (n != i) + { + boost::unique_lock<boost::mutex> lock(check_mutex); + BOOST_CHECK_EQUAL(n, i); + } + ++n; + } +} + + + +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#if BOOST_PLAT_WINDOWS_RUNTIME + typedef std::shared_ptr<std::thread> native_thread_t; + + BOOST_AUTO_TEST_CASE(test_tss_thread_native) + { + test_tss_thread(); + } + + native_thread_t create_native_thread() + { + return std::make_shared<std::thread>(test_tss_thread_native); + } + + void join_native_thread(native_thread_t thread) + { + thread->join(); + } + +#else + typedef HANDLE native_thread_t; + + DWORD WINAPI test_tss_thread_native(LPVOID /*lpParameter*/) + { + test_tss_thread(); + return 0; + } + + native_thread_t create_native_thread(void) + { + native_thread_t const res=CreateThread( + 0, //security attributes (0 = not inheritable) + 0, //stack size (0 = default) + &test_tss_thread_native, //function to execute + 0, //parameter to pass to function + 0, //creation flags (0 = run immediately) + 0 //thread id (0 = thread id not returned) + ); + BOOST_CHECK(res!=0); + return res; + } + + void join_native_thread(native_thread_t thread) + { + DWORD res = WaitForSingleObject(thread, INFINITE); + BOOST_CHECK(res == WAIT_OBJECT_0); + + res = CloseHandle(thread); + BOOST_CHECK(SUCCEEDED(res)); + } +#endif +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) + typedef pthread_t native_thread_t; + +extern "C" +{ + void* test_tss_thread_native(void* ) + { + test_tss_thread(); + return 0; + } +} + + native_thread_t create_native_thread() + { + native_thread_t thread_handle; + + int const res = pthread_create(&thread_handle, 0, &test_tss_thread_native, 0); + BOOST_CHECK(!res); + return thread_handle; + } + + void join_native_thread(native_thread_t thread) + { + void* result=0; + int const res=pthread_join(thread,&result); + BOOST_CHECK(!res); + } +#endif + +void do_test_tss() +{ + tss_instances = 0; + tss_total = 0; + + const int NUMTHREADS=5; + boost::thread_group threads; + try + { + for (int i=0; i<NUMTHREADS; ++i) + threads.create_thread(&test_tss_thread); + threads.join_all(); + } + catch(...) + { + threads.interrupt_all(); + threads.join_all(); + throw; + } + + + std::cout + << "tss_instances = " << tss_instances + << "; tss_total = " << tss_total + << "\n"; + std::cout.flush(); + + BOOST_CHECK_EQUAL(tss_instances, 0); + BOOST_CHECK_EQUAL(tss_total, 5); + + tss_instances = 0; + tss_total = 0; + + native_thread_t thread1 = create_native_thread(); + native_thread_t thread2 = create_native_thread(); + native_thread_t thread3 = create_native_thread(); + native_thread_t thread4 = create_native_thread(); + native_thread_t thread5 = create_native_thread(); + + join_native_thread(thread5); + join_native_thread(thread4); + join_native_thread(thread3); + join_native_thread(thread2); + join_native_thread(thread1); + + std::cout + << "tss_instances = " << tss_instances + << "; tss_total = " << tss_total + << "\n"; + std::cout.flush(); + + // The following is not really an error. TSS cleanup support still is available for boost threads. + // Also this usually will be triggered only when bound to the static version of thread lib. + // 2006-10-02 Roland Schwarz + //BOOST_CHECK_EQUAL(tss_instances, 0); +#if !defined(__MINGW32__) + // This fails on MinGW, when using the static lib + BOOST_CHECK_MESSAGE(tss_instances == 0, "Support of automatic tss cleanup for native threading API not available"); +#endif + BOOST_CHECK_EQUAL(tss_total, 5); +} + +BOOST_AUTO_TEST_CASE(test_tss) +{ + timed_test(&do_test_tss, 2); +} + + +bool tss_void_cleanup_called=false; + +void tss_void_custom_cleanup(void* d) +{ + std::cout << d << std::endl; + delete reinterpret_cast<tss_value_t*>(d); + tss_void_cleanup_called=true; +} + +boost::thread_specific_ptr<void> tss_void(tss_void_custom_cleanup); + +void test_tss_void_thread() +{ + tss_void.reset(new tss_value_t()); + for (int i=0; i<10; ++i) + { + int& n = static_cast<tss_value_t*>(tss_value.get())->value; + *tss_value; + // Don't call BOOST_CHECK_EQUAL directly, as it doesn't appear to + // be thread safe. Must evaluate further. + if (n != i) + { + boost::unique_lock<boost::mutex> lock(check_mutex); + BOOST_CHECK_EQUAL(n, i); + } + ++n; + } +} +void do_test_tss_void() +{ + tss_instances = 0; + tss_total = 0; + + const int NUMTHREADS=5; + boost::thread_group threads; + try + { + for (int i=0; i<NUMTHREADS; ++i) + threads.create_thread(&test_tss_void_thread); + threads.join_all(); + } + catch(...) + { + threads.interrupt_all(); + threads.join_all(); + throw; + } + + + std::cout + << "tss_instances = " << tss_instances + << "; tss_total = " << tss_total + << "\n"; + std::cout.flush(); + + BOOST_CHECK_EQUAL(tss_instances, 0); + BOOST_CHECK_EQUAL(tss_total, 5); + +// tss_instances = 0; +// tss_total = 0; +// +// native_thread_t thread1 = create_native_thread(); +// native_thread_t thread2 = create_native_thread(); +// native_thread_t thread3 = create_native_thread(); +// native_thread_t thread4 = create_native_thread(); +// native_thread_t thread5 = create_native_thread(); +// +// join_native_thread(thread5); +// join_native_thread(thread4); +// join_native_thread(thread3); +// join_native_thread(thread2); +// join_native_thread(thread1); +// +// std::cout +// << "tss_instances = " << tss_instances +// << "; tss_total = " << tss_total +// << "\n"; +// std::cout.flush(); +// +// // The following is not really an error. TSS cleanup support still is available for boost threads. +// // Also this usually will be triggered only when bound to the static version of thread lib. +// // 2006-10-02 Roland Schwarz +// //BOOST_CHECK_EQUAL(tss_instances, 0); +// BOOST_CHECK_MESSAGE(tss_instances == 0, "Support of automatic tss cleanup for native threading API not available"); +// BOOST_CHECK_EQUAL(tss_total, 5); +} + +//BOOST_AUTO_TEST_CASE(test_tss_void) +//{ +// timed_test(&do_test_tss_void, 2); +//} + + +boost::thread_specific_ptr<void> tss_void_with_cleanup(tss_void_custom_cleanup); + +void tss_void_thread_with_custom_cleanup() +{ + tss_void_with_cleanup.reset(new tss_value_t); +} + +void do_test_tss_void_with_custom_cleanup() +{ + boost::thread t(tss_void_thread_with_custom_cleanup); + try + { + t.join(); + } + catch(...) + { + t.interrupt(); + t.join(); + throw; + } + + BOOST_CHECK(tss_void_cleanup_called); +} + + +BOOST_AUTO_TEST_CASE(test_tss_void_with_custom_cleanup) +{ + timed_test(&do_test_tss_void_with_custom_cleanup, 2); +} + + +bool tss_cleanup_called=false; + +struct Dummy +{}; + +void tss_custom_cleanup(Dummy* d) +{ + delete d; + tss_cleanup_called=true; +} + +boost::thread_specific_ptr<Dummy> tss_with_cleanup(tss_custom_cleanup); + +void tss_thread_with_custom_cleanup() +{ + tss_with_cleanup.reset(new Dummy); +} + +void do_test_tss_with_custom_cleanup() +{ + boost::thread t(tss_thread_with_custom_cleanup); + try + { + t.join(); + } + catch(...) + { + t.interrupt(); + t.join(); + throw; + } + + BOOST_CHECK(tss_cleanup_called); +} + + +BOOST_AUTO_TEST_CASE(test_tss_with_custom_cleanup) +{ + timed_test(&do_test_tss_with_custom_cleanup, 2); +} + +Dummy* tss_object=new Dummy; + +void tss_thread_with_custom_cleanup_and_release() +{ + tss_with_cleanup.reset(tss_object); + tss_with_cleanup.release(); +} + +void do_test_tss_does_no_cleanup_after_release() +{ + tss_cleanup_called=false; + boost::thread t(tss_thread_with_custom_cleanup_and_release); + try + { + t.join(); + } + catch(...) + { + t.interrupt(); + t.join(); + throw; + } + + BOOST_CHECK(!tss_cleanup_called); + if(!tss_cleanup_called) + { + delete tss_object; + } +} + +struct dummy_class_tracks_deletions +{ + static unsigned deletions; + + ~dummy_class_tracks_deletions() + { + ++deletions; + } + +}; + +unsigned dummy_class_tracks_deletions::deletions=0; + +boost::thread_specific_ptr<dummy_class_tracks_deletions> tss_with_null_cleanup(NULL); + +void tss_thread_with_null_cleanup(dummy_class_tracks_deletions* delete_tracker) +{ + tss_with_null_cleanup.reset(delete_tracker); +} + +void do_test_tss_does_no_cleanup_with_null_cleanup_function() +{ + dummy_class_tracks_deletions* delete_tracker=new dummy_class_tracks_deletions; + boost::thread t(tss_thread_with_null_cleanup,delete_tracker); + try + { + t.join(); + } + catch(...) + { + t.interrupt(); + t.join(); + throw; + } + + BOOST_CHECK(!dummy_class_tracks_deletions::deletions); + if(!dummy_class_tracks_deletions::deletions) + { + delete delete_tracker; + } +} + +BOOST_AUTO_TEST_CASE(test_tss_does_no_cleanup_after_release) +{ + timed_test(&do_test_tss_does_no_cleanup_after_release, 2); +} + +BOOST_AUTO_TEST_CASE(test_tss_does_no_cleanup_with_null_cleanup_function) +{ + timed_test(&do_test_tss_does_no_cleanup_with_null_cleanup_function, 2); +} + +void thread_with_local_tss_ptr() +{ + { + boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup); + + local_tss.reset(new Dummy); + } + BOOST_CHECK(tss_cleanup_called); + tss_cleanup_called=false; +} + + +BOOST_AUTO_TEST_CASE(test_tss_does_not_call_cleanup_after_ptr_destroyed) +{ + boost::thread t(thread_with_local_tss_ptr); + t.join(); + BOOST_CHECK(!tss_cleanup_called); +} + +BOOST_AUTO_TEST_CASE(test_tss_cleanup_not_called_for_null_pointer) +{ + boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup); + local_tss.reset(new Dummy); + tss_cleanup_called=false; + local_tss.reset(0); + BOOST_CHECK(tss_cleanup_called); + tss_cleanup_called=false; + local_tss.reset(new Dummy); + BOOST_CHECK(!tss_cleanup_called); +} + +//BOOST_AUTO_TEST_CASE(test_tss_at_the_same_adress) +//{ +// for(int i=0; i<2; i++) +// { +// boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup); +// local_tss.reset(new Dummy); +// tss_cleanup_called=false; +// BOOST_CHECK(tss_cleanup_called); +// tss_cleanup_called=false; +// BOOST_CHECK(!tss_cleanup_called); +// } +//} + diff --git a/src/boost/libs/thread/test/test_xtime.cpp b/src/boost/libs/thread/test/test_xtime.cpp new file mode 100644 index 000000000..4988d1f86 --- /dev/null +++ b/src/boost/libs/thread/test/test_xtime.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: xtime test suite + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/xtime.hpp> + +#include <boost/test/unit_test.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition.hpp> + +BOOST_AUTO_TEST_CASE(test_xtime_cmp) +{ + boost::xtime xt1, xt2, cur; + BOOST_CHECK_EQUAL( + boost::xtime_get(&cur, boost::TIME_UTC_), + static_cast<int>(boost::TIME_UTC_)); + + xt1 = xt2 = cur; + xt1.nsec -= 1; + xt2.nsec += 1; + + BOOST_CHECK(boost::xtime_cmp(xt1, cur) < 0); + BOOST_CHECK(boost::xtime_cmp(xt2, cur) > 0); + BOOST_CHECK(boost::xtime_cmp(cur, cur) == 0); + + xt1 = xt2 = cur; + xt1.sec -= 1; + xt2.sec += 1; + + BOOST_CHECK(boost::xtime_cmp(xt1, cur) < 0); + BOOST_CHECK(boost::xtime_cmp(xt2, cur) > 0); + BOOST_CHECK(boost::xtime_cmp(cur, cur) == 0); +} + +BOOST_AUTO_TEST_CASE(test_xtime_get) +{ + boost::xtime orig, cur, old; + BOOST_CHECK_EQUAL( + boost::xtime_get(&orig, + boost::TIME_UTC_), static_cast<int>(boost::TIME_UTC_)); + old = orig; + + for (int x=0; x < 100; ++x) + { + BOOST_CHECK_EQUAL( + boost::xtime_get(&cur, boost::TIME_UTC_), + static_cast<int>(boost::TIME_UTC_)); + BOOST_CHECK(boost::xtime_cmp(cur, orig) >= 0); + BOOST_CHECK(boost::xtime_cmp(cur, old) >= 0); + old = cur; + } +} + +BOOST_AUTO_TEST_CASE(test_xtime_mutex_backwards_compatibility) +{ + boost::timed_mutex m; + BOOST_CHECK(m.timed_lock(boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)))); + m.unlock(); + boost::timed_mutex::scoped_timed_lock lk(m,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10))); + BOOST_CHECK(lk.owns_lock()); + if(lk.owns_lock()) + { + lk.unlock(); + } + BOOST_CHECK(lk.timed_lock(boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)))); + if(lk.owns_lock()) + { + lk.unlock(); + } +} + +bool predicate() +{ + return false; +} + + +BOOST_AUTO_TEST_CASE(test_xtime_condvar_backwards_compatibility) +{ + boost::condition_variable cond; + boost::condition_variable_any cond_any; + boost::mutex m; + + boost::unique_lock<boost::mutex> lk(m); + cond.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10))); + cond.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)),predicate); + cond_any.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10))); + cond_any.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)),predicate); +} diff --git a/src/boost/libs/thread/test/threads/container/thread_ptr_list_pass.cpp b/src/boost/libs/thread/test/threads/container/thread_ptr_list_pass.cpp new file mode 100644 index 000000000..76047051f --- /dev/null +++ b/src/boost/libs/thread/test/threads/container/thread_ptr_list_pass.cpp @@ -0,0 +1,101 @@ +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_USES_MOVE + +#include <boost/config.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/csbl/list.hpp> +//#include <boost/interprocess/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr.hpp> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + + +int count = 0; +boost::mutex mutex; + +namespace { + + +template <typename TC> +void join_all(TC & tc) +{ + for (typename TC::iterator it = tc.begin(); it != tc.end(); ++it) + { + (*it)->join(); + } +} + + +void increment_count() +{ + boost::unique_lock<boost::mutex> lock(mutex); + std::cout << "count = " << ++count << std::endl; +} + +template <class T> +struct default_delete +{ + typedef T* pointer; + + BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {} //= default; + template <class U> + default_delete(const default_delete<U>&) BOOST_NOEXCEPT + {} + void operator()(T* ptr) const + { + delete ptr; + } +}; + +} +int main() +{ + { + typedef boost::shared_ptr<boost::thread > thread_ptr; + //typedef boost::interprocess::shared_ptr<boost::thread, std::allocator<boost::thread>, default_delete<boost::thread> > thread_ptr; + typedef boost::csbl::list<thread_ptr > thread_ptr_list; + thread_ptr_list threads; + for (int i = 0; i < 10; ++i) + { + //threads.push_back(BOOST_THREAD_MAKE_RV_REF(thread_ptr(new boost::thread(&increment_count)))); + threads.push_back(thread_ptr(new boost::thread(&increment_count))); + } + BOOST_TEST(threads.size()==10); + //join_all(threads); + for (thread_ptr_list::iterator it = threads.begin(); it != threads.end(); ++it) + { + (*it)->join(); + } + } + count = 0; + { + typedef boost::shared_ptr<boost::thread > thread_ptr; + //typedef boost::interprocess::shared_ptr<boost::thread, std::allocator<boost::thread>, default_delete<boost::thread> > thread_ptr; + typedef boost::csbl::list<thread_ptr > thread_ptr_list; + thread_ptr_list threads; + for (int i = 0; i < 10; ++i) + { + //threads.push_back(BOOST_THREAD_MAKE_RV_REF(thread_ptr(new boost::thread(&increment_count)))); + threads.push_back(thread_ptr(new boost::thread(&increment_count))); + } + BOOST_TEST(threads.size()==10); + thread_ptr sth(new boost::thread(&increment_count)); + threads.push_back(sth); + BOOST_TEST(threads.size()==11); + threads.remove(sth); + BOOST_TEST(threads.size()==10); + sth->join(); + //join_all(threads); + for (thread_ptr_list::iterator it = threads.begin(); it != threads.end(); ++it) + { + (*it)->join(); + } + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/container/thread_vector_pass.cpp b/src/boost/libs/thread/test/threads/container/thread_vector_pass.cpp new file mode 100644 index 000000000..059a77e36 --- /dev/null +++ b/src/boost/libs/thread/test/threads/container/thread_vector_pass.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_USES_MOVE + +#include <boost/thread/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/csbl/vector.hpp> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +int count = 0; +boost::mutex mutex; + +namespace +{ +template <typename TC> +void join_all(TC & tc) +{ + for (typename TC::iterator it = tc.begin(); it != tc.end(); ++it) + { + it->join(); + } +} + +template <typename TC> +void interrupt_all(TC & tc) +{ +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + for (typename TC::iterator it = tc.begin(); it != tc.end(); ++it) + { + it->interrupt(); + } +#endif +} +} + +void increment_count() +{ + boost::unique_lock<boost::mutex> lock(mutex); + std::cout << "count = " << ++count << std::endl; +} + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_THREAD_USES_MOVE +BOOST_STATIC_ASSERT(::boost::is_function<boost::rv<boost::rv<boost::thread> >&>::value==false); +#endif + +int main() +{ + typedef boost::csbl::vector<boost::thread> thread_vector; + { + thread_vector threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) + { + boost::thread th(&increment_count); + threads.push_back(boost::move(th)); + } + join_all(threads); + } + count = 0; + { + thread_vector threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) + { + threads.push_back(BOOST_THREAD_MAKE_RV_REF(boost::thread(&increment_count))); + } + join_all(threads); + } + count = 0; + { + thread_vector threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) + { + threads.emplace_back(&increment_count); + } + join_all(threads); + } + count = 0; + { + thread_vector threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) + { + threads.emplace_back(&increment_count); + } + interrupt_all(threads); + join_all(threads); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/this_thread/get_id/get_id_pass.cpp b/src/boost/libs/thread/test/threads/this_thread/get_id/get_id_pass.cpp new file mode 100644 index 000000000..f0287cb6a --- /dev/null +++ b/src/boost/libs/thread/test/threads/this_thread/get_id/get_id_pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// thread::id this_thread::get_id(); + +#include <boost/thread/thread_only.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::thread::id id = boost::this_thread::get_id(); + BOOST_TEST(id != boost::thread::id()); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/this_thread/sleep_for/sleep_for_pass.cpp b/src/boost/libs/thread/test/threads/this_thread/sleep_for/sleep_for_pass.cpp new file mode 100644 index 000000000..05c5a790d --- /dev/null +++ b/src/boost/libs/thread/test/threads/this_thread/sleep_for/sleep_for_pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// thread::id this_thread::get_id(); + +#include <boost/thread/thread_only.hpp> +#include <cstdlib> +#include <algorithm> + +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +int main() +{ + { + typedef boost::chrono::system_clock Clock; + typedef Clock::time_point time_point; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::sleep_for(ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + { + typedef boost::chrono::system_clock Clock; + typedef Clock::time_point time_point; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::no_interruption_point::sleep_for(ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + return boost::report_errors(); + +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/threads/this_thread/sleep_until/sleep_until_pass.cpp b/src/boost/libs/thread/test/threads/this_thread/sleep_until/sleep_until_pass.cpp new file mode 100644 index 000000000..232712eed --- /dev/null +++ b/src/boost/libs/thread/test/threads/this_thread/sleep_until/sleep_until_pass.cpp @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// thread::id this_thread::get_id(); + +#include <boost/thread/thread_only.hpp> +#include <cstdlib> +#include <algorithm> + +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +int main() +{ + { + typedef boost::chrono::steady_clock Clock; + typedef Clock::time_point time_point; + //typedef Clock::duration duration; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::sleep_until(t0 + ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + { + typedef boost::chrono::system_clock Clock; + typedef Clock::time_point time_point; + //typedef Clock::duration duration; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::sleep_until(t0 + ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + { + typedef boost::chrono::steady_clock Clock; + typedef Clock::time_point time_point; + //typedef Clock::duration duration; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::no_interruption_point::sleep_until(t0 + ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + { + typedef boost::chrono::system_clock Clock; + typedef Clock::time_point time_point; + //typedef Clock::duration duration; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::no_interruption_point::sleep_until(t0 + ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + return boost::report_errors(); + +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/threads/thread/assign/copy_fail.cpp b/src/boost/libs/thread/test/threads/thread/assign/copy_fail.cpp new file mode 100644 index 000000000..5ccac5b31 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/assign/copy_fail.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// thread& operator=(thread&& t); + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } + +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + boost::thread t1; + t1 = t0; + } +} + +#include "../../../remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/threads/thread/assign/move_pass.cpp b/src/boost/libs/thread/test/threads/thread/assign/move_pass.cpp new file mode 100644 index 000000000..293c5d838 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/assign/move_pass.cpp @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// thread& operator=(thread&& t); + +#define BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } + + void operator()(int i, double j) + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + BOOST_TEST(i == 5); + BOOST_TEST(j == 5.5); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +void f1() +{ + std::exit(boost::report_errors()); +} + +int main() +{ + std::set_terminate(f1); + { + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t0(G(), 5, 5.5); + boost::thread::id id = t0.get_id(); + boost::thread t1; + t1 = boost::move(t0); + BOOST_TEST(t1.get_id() == id); + BOOST_TEST(t0.get_id() == boost::thread::id()); + t1.join(); + BOOST_TEST(G::op_run); + } + BOOST_TEST(G::n_alive == 0); + { + boost::thread t0(G(), 5, 5.5); + boost::thread t1; + t0 = boost::move(t1); + BOOST_TEST(false); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/constr/FArgs_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/FArgs_pass.cpp new file mode 100644 index 000000000..afdc7018f --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/FArgs_pass.cpp @@ -0,0 +1,145 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class F, class ...Args> thread(F f, Args... args); + +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +unsigned throw_one = 0xFFFF; + +#if defined _GLIBCXX_THROW +void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc) +#elif defined BOOST_MSVC +void* operator new(std::size_t s) +#elif __cplusplus > 201402L +void* operator new(std::size_t s) +#else +void* operator new(std::size_t s) throw (std::bad_alloc) +#endif +{ + //std::cout << __FILE__ << ":" << __LINE__ << std::endl; + if (throw_one == 0) throw std::bad_alloc(); + --throw_one; + return std::malloc(s); +} + +#if defined BOOST_MSVC +void operator delete(void* p) +#else +void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW +#endif +{ + //std::cout << __FILE__ << ":" << __LINE__ << std::endl; + std::free(p); +} + +bool f_run = false; + +void f(int i, double j) +{ + BOOST_TEST(i == 5); + BOOST_TEST(j == 5.5); + f_run = true; +} + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()(int i, double j) + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive >= 1); + BOOST_TEST(i == 5); + BOOST_TEST(j == 5.5); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + + +int main() +{ + { + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + boost::thread t(f, 5, 5.5); + t.join(); + BOOST_TEST(f_run == true); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + } +#if !defined(BOOST_MSVC) && !defined(__MINGW32__) + f_run = false; + { + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + try + { + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + throw_one = 0; + boost::thread t(f, 5, 5.5); + BOOST_TEST(false); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + } + catch (...) + { + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + throw_one = 0xFFFF; + BOOST_TEST(!f_run); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + } + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + } +#endif + { + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + BOOST_TEST(G::n_alive == 0); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + BOOST_TEST(!G::op_run); + boost::thread t(G(), 5, 5.5); + t.join(); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(G::op_run); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/constr/F_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/F_pass.cpp new file mode 100644 index 000000000..7fd2bbc24 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/F_pass.cpp @@ -0,0 +1,150 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class F, class ...Args> thread(F f, Args... args); + +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +unsigned throw_one = 0xFFFF; + +#if defined _GLIBCXX_THROW +void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc) +#elif defined BOOST_MSVC +void* operator new(std::size_t s) +#elif __cplusplus > 201402L +void* operator new(std::size_t s) +#else +void* operator new(std::size_t s) throw (std::bad_alloc) +#endif +{ + //std::cout << __FILE__ << ":" << __LINE__ << std::endl; + if (throw_one == 0) throw std::bad_alloc(); + --throw_one; + return std::malloc(s); +} + +#if defined BOOST_MSVC +void operator delete(void* p) +#else +void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW +#endif +{ + //std::cout << __FILE__ << ":" << __LINE__ << std::endl; + std::free(p); +} + +bool f_run = false; + +void f() +{ + f_run = true; +} + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive >= 1); + op_run = true; + } + +}; + +int G::n_alive = 0; +bool G::op_run = false; + + +int main() +{ + { + boost::thread t(f); + t.join(); + BOOST_TEST(f_run == true); + } + f_run = false; +#if !defined(BOOST_MSVC) && !defined(__MINGW32__) + { + try + { + throw_one = 0; + boost::thread t(f); + BOOST_TEST(false); + } + catch (...) + { + throw_one = 0xFFFF; + BOOST_TEST(!f_run); + } + } +#endif + { + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t( (G())); + t.join(); + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(G::op_run); + } +#if !defined(BOOST_MSVC) && !defined(__MINGW32__) + G::op_run = false; + { + try + { + throw_one = 0; + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t( (G())); + BOOST_TEST(false); + } + catch (...) + { + throw_one = 0xFFFF; + BOOST_TEST(G::n_alive == 0); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + BOOST_TEST(!G::op_run); + } + } +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp new file mode 100644 index 000000000..e76db7022 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp @@ -0,0 +1,103 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class F, class ...Args> thread(F&& f, Args&&... args); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class MoveOnly +{ +public: + BOOST_THREAD_MOVABLE_ONLY(MoveOnly) + MoveOnly() + { + } + MoveOnly(BOOST_THREAD_RV_REF(MoveOnly)) + {} + + void operator()(BOOST_THREAD_RV_REF(MoveOnly)) + { + } +}; + +class M +{ + +public: + long data_; + static int n_moves; + + BOOST_THREAD_MOVABLE_ONLY(M) + static void reset() { + n_moves=0; + } + explicit M(long i) : data_(i) + { + } + M(BOOST_THREAD_RV_REF(M) a) : data_(BOOST_THREAD_RV(a).data_) + { + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + } + M& operator=(BOOST_THREAD_RV_REF(M) a) + { + data_ = BOOST_THREAD_RV(a).data_; + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + return *this; + } + ~M() + { + } + + void operator()(int) const + { } + long operator()() const + { return data_;} + long operator()(long i, long j) const + { return data_ + i + j;} +}; + +int M::n_moves = 0; + +void fct(BOOST_THREAD_RV_REF(M) v) +{ + BOOST_TEST_EQ(v.data_, 1); +} + +int main() +{ +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + boost::thread t = boost::thread( MoveOnly(), MoveOnly() ); + t.join(); + } + { + M::reset(); + boost::thread t = boost::thread( fct, M(1) ); + t.join(); + BOOST_TEST_EQ(M::n_moves, 2); + } +#endif + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/constr/Frvalue_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/Frvalue_pass.cpp new file mode 100644 index 000000000..38061e0a7 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/Frvalue_pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class F, class ...Args> thread(F&& f, Args&&... args); + +#define BOOST_THREAD_USES_MOVE + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +class MoveOnly +{ +public: + BOOST_THREAD_MOVABLE_ONLY(MoveOnly) + MoveOnly() + { + } + MoveOnly(BOOST_THREAD_RV_REF(MoveOnly)) + {} + + void operator()() + { + } +}; + +MoveOnly MakeMoveOnly() { + return BOOST_THREAD_MAKE_RV_REF(MoveOnly()); +} + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_THREAD_USES_MOVE +BOOST_STATIC_ASSERT(::boost::is_function<boost::rv<boost::rv<MoveOnly> >&>::value==false); +#endif + +int main() +{ + { + boost::thread t(( BOOST_THREAD_MAKE_RV_REF(MakeMoveOnly()) )); + t.join(); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/constr/copy_fail.cpp b/src/boost/libs/thread/test/threads/thread/constr/copy_fail.cpp new file mode 100644 index 000000000..caa72c2d8 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/copy_fail.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// thread(const thread&) = delete; + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } + + void operator()(int i, double j) + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + BOOST_TEST(i == 5); + BOOST_TEST(j == 5.5); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t0(G(), 5, 5.5); + boost::thread::id id = t0.get_id(); + boost::thread t1( (t0)); + BOOST_TEST(t1.get_id() == id); + BOOST_TEST(t0.get_id() == boost::thread::id()); + t1.join(); + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(G::op_run); + } +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/threads/thread/constr/default_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/default_pass.cpp new file mode 100644 index 000000000..cea602d15 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/default_pass.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// thread(); + +#include <boost/thread/thread_only.hpp> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::thread t; + BOOST_TEST(t.get_id() == boost::thread::id()); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/constr/lambda_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/lambda_pass.cpp new file mode 100644 index 000000000..84615bf88 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/lambda_pass.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class Clousure> thread(Clousure f); + +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if ! defined BOOST_NO_CXX11_LAMBDAS + +unsigned throw_one = 0xFFFF; + +#if defined _GLIBCXX_THROW +void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc) +#elif defined BOOST_MSVC +void* operator new(std::size_t s) +#elif __cplusplus > 201402L +void* operator new(std::size_t s) +#else +void* operator new(std::size_t s) throw (std::bad_alloc) +#endif +{ + if (throw_one == 0) throw std::bad_alloc(); + --throw_one; + return std::malloc(s); +} + +#if defined BOOST_MSVC +void operator delete(void* p) +#else +void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW +#endif +{ + std::free(p); +} + +bool f_run = false; + +int main() +{ + { + f_run = false; + boost::thread t( []() { f_run = true; } ); + t.join(); + BOOST_TEST(f_run == true); + } +#if !defined(BOOST_MSVC) && !defined(__MINGW32__) + { + f_run = false; + try + { + throw_one = 0; + boost::thread t( []() { f_run = true; } ); + BOOST_TEST(false); + } + catch (...) + { + throw_one = 0xFFFF; + BOOST_TEST(!f_run); + } + } +#endif + + return boost::report_errors(); +} + +#else +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/threads/thread/constr/move_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/move_pass.cpp new file mode 100644 index 000000000..66f9d7546 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/move_pass.cpp @@ -0,0 +1,94 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// thread(thread&& t); + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } + + void operator()(int i, double j) + { + BOOST_TEST(alive_ == 1); + std::cout << __FILE__ << ":" << __LINE__ <<" " << n_alive << std::endl; + //BOOST_TEST(n_alive == 1); + BOOST_TEST(i == 5); + BOOST_TEST(j == 5.5); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +boost::thread make_thread() { + return boost::thread(G(), 5, 5.5); +} + +int main() +{ + { + //BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t0((G())); + boost::thread::id id = t0.get_id(); + boost::thread t1((boost::move(t0))); + BOOST_TEST(t1.get_id() == id); + BOOST_TEST(t0.get_id() == boost::thread::id()); + t1.join(); + BOOST_TEST(G::op_run); + } + //BOOST_TEST(G::n_alive == 0); + { + boost::thread t1((BOOST_THREAD_MAKE_RV_REF(make_thread()))); + t1.join(); + BOOST_TEST(G::op_run); + } + //BOOST_TEST(G::n_alive == 0); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/destr/dtor_pass.cpp b/src/boost/libs/thread/test/threads/thread/destr/dtor_pass.cpp new file mode 100644 index 000000000..ea0e6bac4 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/destr/dtor_pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// ~thread(); + +#define BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +void f1() +{ + std::exit(boost::report_errors()); +} + +int main() +{ + std::set_terminate(f1); + { + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t( (G())); +#if defined BOOST_THREAD_USES_CHRONO + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); +#endif + BOOST_TEST(t.joinable()); + } + BOOST_TEST(false); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/id/hash_pass.cpp b/src/boost/libs/thread/test/threads/thread/id/hash_pass.cpp new file mode 100644 index 000000000..6ce52c97a --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/id/hash_pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// <functional> + +// template <class T> +// struct hash +// : public unary_function<T, size_t> +// { +// size_t operator()(T val) const; +// }; + + +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + boost::thread::id id1; + boost::thread::id id2 = boost::this_thread::get_id(); + typedef boost::hash<boost::thread::id> H; + H h; + BOOST_TEST(h(id1) != h(id2)); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/detach_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/detach_pass.cpp new file mode 100644 index 000000000..927175338 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/detach_pass.cpp @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// void detach(); + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.detach(); + BOOST_TEST(!t0.joinable()); +#if defined BOOST_THREAD_USES_CHRONO + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); + BOOST_TEST(G::op_run); + BOOST_TEST(G::n_alive == 0); +#endif + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/get_id_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/get_id_pass.cpp new file mode 100644 index 000000000..dcaa7090b --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/get_id_pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// id get_id() const; + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + //boost::thread::id id0 = t0.get_id(); + boost::thread t1; + boost::thread::id id1 = t1.get_id(); + BOOST_TEST(t0.get_id() != id1); + BOOST_TEST(t1.get_id() == boost::thread::id()); + t0.join(); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/join_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/join_pass.cpp new file mode 100644 index 000000000..f2d42b72b --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/join_pass.cpp @@ -0,0 +1,135 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// void join(); +#define BOOST_THREAD_VESRION 3 +#include <boost/thread/thread_only.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/locks.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +boost::thread* resource_deadlock_would_occur_th=0; +boost::mutex resource_deadlock_would_occur_mtx; +void resource_deadlock_would_occur_tester() +{ + try + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + resource_deadlock_would_occur_th->join(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + catch (...) + { + BOOST_TEST(false&&"exception thrown"); + } +} + +int main() +{ + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.join(); + BOOST_TEST(!t0.joinable()); + } + + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + boost::thread t0( resource_deadlock_would_occur_tester ); + resource_deadlock_would_occur_th = &t0; + BOOST_TEST(t0.joinable()); + lk.unlock(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); + boost::unique_lock<boost::mutex> lk2(resource_deadlock_would_occur_mtx); + t0.join(); + BOOST_TEST(!t0.joinable()); + } + + { + boost::thread t0( (G())); + t0.detach(); + try + { + t0.join(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + } + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.join(); + try + { + t0.join(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/joinable_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/joinable_pass.cpp new file mode 100644 index 000000000..dcf09d1f8 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/joinable_pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// bool joinable() const; + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.join(); + BOOST_TEST(!t0.joinable()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/native_handle_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/native_handle_pass.cpp new file mode 100644 index 000000000..01115da05 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/native_handle_pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// native_handle_type native_handle(); + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + // boost::thread::native_handle_type hdl = + (void)t0.native_handle(); + t0.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/swap_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/swap_pass.cpp new file mode 100644 index 000000000..16af2d1b8 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/swap_pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// native_handle_type native_handle(); + +#include <boost/thread/thread_only.hpp> +#include <cstdlib> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + std::cout << n_alive << std::endl; + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + boost::thread::id id0 = t0.get_id(); + boost::thread t1; + boost::thread::id id1 = t1.get_id(); + t0.swap(t1); + BOOST_TEST(t0.get_id() == id1); + BOOST_TEST(t1.get_id() == id0); + t1.join(); + return boost::report_errors(); + } +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/try_join_for_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/try_join_for_pass.cpp new file mode 100644 index 000000000..5215d18d6 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/try_join_for_pass.cpp @@ -0,0 +1,161 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class Rep, class Period> +// bool try_join_for(const chrono::duration<Rep, Period>& rel_time); + +#define BOOST_THREAD_VESRION 3 +#include <boost/thread/thread_only.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/locks.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +class G +{ + int alive_; +public: + static bool op_run; + + G() : + alive_(1) + { + } + G(const G& g) : + alive_(g.alive_) + { + } + ~G() + { + alive_ = 0; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + op_run = true; + } +}; + +bool G::op_run = false; + +boost::thread* resource_deadlock_would_occur_th=0; +boost::mutex resource_deadlock_would_occur_mtx; +void resource_deadlock_would_occur_tester() +{ + try + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + resource_deadlock_would_occur_th->try_join_for(boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + catch (...) + { + BOOST_TEST(false&&"exception thrown"); + } +} + +void th_250_ms() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); +} + +int main() +{ + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + BOOST_TEST(t0.try_join_for(boost::chrono::milliseconds(250))); + BOOST_TEST(!t0.joinable()); + } + { + boost::thread t0( (th_250_ms)); + BOOST_TEST(!t0.try_join_for(boost::chrono::milliseconds(50))); + t0.join(); + } + + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + boost::thread t0( resource_deadlock_would_occur_tester ); + resource_deadlock_would_occur_th = &t0; + BOOST_TEST(t0.joinable()); + lk.unlock(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); + boost::unique_lock<boost::mutex> lk2(resource_deadlock_would_occur_mtx); + t0.join(); + BOOST_TEST(!t0.joinable()); + } + + { + boost::thread t0( (G())); + t0.detach(); + try + { + t0.try_join_for(boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + } + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.join(); + try + { + t0.try_join_for(boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + + } + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.try_join_for(boost::chrono::milliseconds(250)); + try + { + t0.join(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/threads/thread/members/try_join_until_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/try_join_until_pass.cpp new file mode 100644 index 000000000..749ff5b06 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/try_join_until_pass.cpp @@ -0,0 +1,162 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class Clock, class Duration> +// bool try_join_until(const chrono::time_point<Clock, Duration>& t); + +#define BOOST_THREAD_VESRION 3 +#include <boost/thread/thread_only.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/locks.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +class G +{ + int alive_; +public: + static bool op_run; + + G() : + alive_(1) + { + } + G(const G& g) : + alive_(g.alive_) + { + } + ~G() + { + alive_ = 0; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + op_run = true; + } +}; + +bool G::op_run = false; + +boost::thread* resource_deadlock_would_occur_th=0; +boost::mutex resource_deadlock_would_occur_mtx; +void resource_deadlock_would_occur_tester() +{ + try + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + resource_deadlock_would_occur_th->try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + catch (...) + { + BOOST_TEST(false&&"exception thrown"); + } +} + +void th_250_ms() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); +} + + +int main() +{ + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(250)); + BOOST_TEST(!t0.joinable()); + } + { + boost::thread t0( (th_250_ms)); + BOOST_TEST(!t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50))); + t0.join(); + } + + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + boost::thread t0( resource_deadlock_would_occur_tester ); + resource_deadlock_would_occur_th = &t0; + BOOST_TEST(t0.joinable()); + lk.unlock(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); + boost::unique_lock<boost::mutex> lk2(resource_deadlock_would_occur_mtx); + t0.join(); + BOOST_TEST(!t0.joinable()); + } + + { + boost::thread t0( (G())); + t0.detach(); + try + { + t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + } + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.join(); + try + { + t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + + } + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(250)); + try + { + t0.join(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/threads/thread/non_members/swap_pass.cpp b/src/boost/libs/thread/test/threads/thread/non_members/swap_pass.cpp new file mode 100644 index 000000000..eb6faf157 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/non_members/swap_pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// void swap(thread& x, thread& y); + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + boost::thread::id id0 = t0.get_id(); + boost::thread t1; + boost::thread::id id1 = t1.get_id(); + swap(t0, t1); + BOOST_TEST(t0.get_id() == id1); + BOOST_TEST(t1.get_id() == id0); + t1.join(); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/static/hardware_concurrency_pass.cpp b/src/boost/libs/thread/test/threads/thread/static/hardware_concurrency_pass.cpp new file mode 100644 index 000000000..2a2a227ed --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/static/hardware_concurrency_pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// <boost/thread/thread.hpp> + +// class thread + +// static unsigned hardware_concurrency(); + +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_TEST(boost::thread::hardware_concurrency() > 0); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/timming.hpp b/src/boost/libs/thread/test/timming.hpp new file mode 100644 index 000000000..6ae320e8d --- /dev/null +++ b/src/boost/libs/thread/test/timming.hpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_TEST_TIMMING_HPP +#define BOOST_THREAD_TEST_TIMMING_HPP + +#include <boost/thread/detail/config.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if ! defined BOOST_THREAD_TEST_TIME_MS +#ifdef __linux__ +#define BOOST_THREAD_TEST_TIME_MS 75 +#else +// Windows, Cygwin, macOS all need this +#define BOOST_THREAD_TEST_TIME_MS 250 +#endif +#endif + +#if ! defined BOOST_THREAD_TEST_TIME_WARNING +#define BOOST_THREAD_TEST_IT(A, B) BOOST_TEST_LT((A).count(), (B).count()) +#else +#define BOOST_THREAD_TEST_IT(A, B) BOOST_TEST_LT((A).count(), (B).count()) +#endif + +#endif diff --git a/src/boost/libs/thread/test/util.inl b/src/boost/libs/thread/test/util.inl new file mode 100644 index 000000000..e4709bc3e --- /dev/null +++ b/src/boost/libs/thread/test/util.inl @@ -0,0 +1,243 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007-8 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(UTIL_INL_WEK01242003) +#define UTIL_INL_WEK01242003 + +#include <boost/thread/xtime.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/thread.hpp> +#include <boost/config.hpp> + +#ifndef DEFAULT_EXECUTION_MONITOR_TYPE +# define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition +#endif + +// boostinspect:nounnamed + + + +namespace +{ +inline boost::xtime delay(int secs, int msecs=0, int nsecs=0) +{ + const int MILLISECONDS_PER_SECOND = 1000; + const int NANOSECONDS_PER_SECOND = 1000000000; + const int NANOSECONDS_PER_MILLISECOND = 1000000; + + boost::xtime xt; + if (boost::TIME_UTC_ != boost::xtime_get (&xt, boost::TIME_UTC_)) + BOOST_ERROR ("boost::xtime_get != boost::TIME_UTC_"); + + nsecs += xt.nsec; + msecs += nsecs / NANOSECONDS_PER_MILLISECOND; + secs += msecs / MILLISECONDS_PER_SECOND; + nsecs += (msecs % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; + xt.nsec = nsecs % NANOSECONDS_PER_SECOND; + xt.sec += secs + (nsecs / NANOSECONDS_PER_SECOND); + + return xt; +} + +} +namespace boost +{ +namespace threads +{ +namespace test +{ +inline bool in_range(const boost::xtime& xt, int secs=1) +{ + boost::xtime min = delay(-secs); + boost::xtime max = delay(0); + return (boost::xtime_cmp(xt, min) >= 0) && + (boost::xtime_cmp(xt, max) <= 0); +} +} +} +} + + +namespace +{ +class execution_monitor +{ +public: + enum wait_type { use_sleep_only, use_mutex, use_condition }; + + execution_monitor(wait_type type, int secs) + : done(false), type(type), secs(secs) { } + void start() + { + if (type != use_sleep_only) { + boost::unique_lock<boost::mutex> lock(mutex); done = false; + } else { + done = false; + } + } + void finish() + { + if (type != use_sleep_only) { + boost::unique_lock<boost::mutex> lock(mutex); + done = true; + if (type == use_condition) + cond.notify_one(); + } else { + done = true; + } + } + bool wait() + { + boost::xtime xt = delay(secs); + if (type == use_sleep_only) { + boost::thread::sleep(xt); + return done; + } + if (type == use_condition) { + boost::unique_lock<boost::mutex> lock(mutex); + while (!done) { + if (!cond.timed_wait(lock, xt)) + break; + } + return done; + } + for (int i = 0; ; ++i) { + { + boost::unique_lock<boost::mutex> lock(mutex); + if (done) + return true; + else if (i > secs * 2) + return done; + } + boost::thread::sleep(delay(0, 500)); + } + } + +private: + boost::mutex mutex; + boost::condition cond; + bool done; + wait_type type; + int secs; +}; +} +namespace thread_detail_anon +{ +template <typename F> +class indirect_adapter +{ +public: + indirect_adapter(F func, execution_monitor& monitor) + : func(func), monitor(monitor) { } +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + indirect_adapter(indirect_adapter const&) = default; +#endif + + void operator()() const + { + try + { + boost::thread thrd(func); + thrd.join(); + } + catch (...) + { + monitor.finish(); + throw; + } + monitor.finish(); + } + +private: + F func; + execution_monitor& monitor; + void operator=(indirect_adapter&); +}; + +} +// boostinspect:nounnamed +namespace +{ + +template <typename F> +void timed_test(F func, int secs, + execution_monitor::wait_type type=DEFAULT_EXECUTION_MONITOR_TYPE) +{ + execution_monitor monitor(type, secs); + thread_detail_anon::indirect_adapter<F> ifunc(func, monitor); + monitor.start(); + boost::thread thrd(ifunc); + BOOST_REQUIRE_MESSAGE(monitor.wait(), + "Timed test didn't complete in time, possible deadlock."); +} + +} + +namespace thread_detail_anon +{ + +template <typename F, typename T> +class thread_binder +{ +public: + thread_binder(const F& func, const T& param) + : func(func), param(param) { } + void operator()() const { func(param); } + +private: + F func; + T param; +}; + +} + +// boostinspect:nounnamed +namespace +{ +template <typename F, typename T> +thread_detail_anon::thread_binder<F, T> bind(const F& func, const T& param) +{ + return thread_detail_anon::thread_binder<F, T>(func, param); +} +} + +namespace thread_detail_anon +{ + +template <typename R, typename T> +class thread_member_binder +{ +public: + thread_member_binder(R (T::*func)(), T& param) + : func(func), param(param) { } +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + thread_member_binder(thread_member_binder const&) = default; +#endif + + void operator()() const { (param.*func)(); } + +private: + void operator=(thread_member_binder&); + + R (T::*func)(); + T& param; +}; + +} + +// boostinspect:nounnamed +namespace +{ +template <typename R, typename T> +thread_detail_anon::thread_member_binder<R, T> bind(R (T::*func)(), T& param) +{ + return thread_detail_anon::thread_member_binder<R, T>(func, param); +} +} // namespace + +#endif diff --git a/src/boost/libs/thread/test/winrt_init.cpp b/src/boost/libs/thread/test/winrt_init.cpp new file mode 100644 index 000000000..b6d0864ba --- /dev/null +++ b/src/boost/libs/thread/test/winrt_init.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2014 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/predef/platform.h> + +#if BOOST_PLAT_WINDOWS_RUNTIME + +#include <wrl\wrappers\corewrappers.h> +#pragma comment(lib, "runtimeobject.lib") + +// Necessary for the tests which to keep the Windows Runtime active, +// when running in an actual Windows store/phone application initialization +// is handled automatically by the CRT. +// This is easier than calling in the main function for each test case. +Microsoft::WRL::Wrappers::RoInitializeWrapper runtime(RO_INIT_MULTITHREADED); + +#endif |