2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-03 09:42:16 +00:00

Compare commits

...

824 Commits

Author SHA1 Message Date
Vicente J. Botet Escriba
58698f44f1 More renamming and added some comments on scheduler.hpp. 2014-11-05 19:41:56 +01:00
Vicente J. Botet Escriba
37afdd2e9a Moved test_scheduler_p to a explicit test_suite. 2014-11-05 01:03:44 +01:00
Vicente J. Botet Escriba
c87b24923a Added scheduler at/after/on executor factory helper functions. 2014-11-05 00:41:29 +01:00
Vicente J. Botet Escriba
1210fc4859 Add missing include file. 2014-11-05 00:38:21 +01:00
Vicente J. Botet Escriba
d8b6ae6266 Ensure that the numbers of pools is at least 1. 2014-11-05 00:37:52 +01:00
Vicente J. Botet Escriba
04e2223d5e Minor renamming. 2014-11-04 22:51:25 +01:00
Vicente J. Botet Escriba
579748e7a0 Avoid locking while doing callback. 2014-11-04 22:48:57 +01:00
Vicente J. Botet Escriba
41c3914aaf Don't try-catch on try_executing_one_task. 2014-11-02 19:42:18 +01:00
Vicente J. Botet Escriba
8693eec4a4 Make submit strong-thread safe. 2014-11-02 19:41:57 +01:00
Vicente J. Botet Escriba
3f699750a8 Avoid locking while doing callback. 2014-11-02 19:41:42 +01:00
Vicente J. Botet Escriba
4f8243cf59 Remove waiting_empty_. 2014-11-02 19:41:25 +01:00
Vicente J. Botet Escriba
4f01891da7 Added not_ready and timeout queue_op_status. Make sync_timed_queue and sync_priority_queue conform to the sync_queue interface. Aapt the test to the new interface. 2014-11-02 15:13:37 +01:00
Vicente J. Botet Escriba
efab5af918 Fix inspection issue. 2014-11-02 15:11:28 +01:00
Vicente J. Botet Escriba
4d03b410a8 Update executors doc adding thread executor. 2014-11-02 15:10:15 +01:00
Vicente J. Botet Escriba
c1925df81c Fix task exception silently ignored. Make submit throw if closed. join the threads created by the thread_executor 2014-11-02 15:09:11 +01:00
Vicente J. Botet Escriba
cbf9fe8a5c Fix inspection issues. 2014-11-02 15:08:44 +01:00
Vicente J. Botet Escriba
6fd7dc0d94 Added move semantics for C++11 compilers. Need of a detail::priority_queue. Tried to do it for C++98, but heap_push/heap_pop algorithms are not move aware:(. 2014-11-01 22:18:32 +01:00
Vicente J. Botet Escriba
a2f2924298 Added missing file sync_queue_base and refactor the concurrent queues to make use of this class. 2014-11-01 22:18:09 +01:00
Vicente J. Botet Escriba
49d485f1aa Removed BOOST_THREAD_QUEUE_DEPRECATE_OLD for priority and timed queues. 2014-11-01 11:21:09 +01:00
Vicente J. Botet Escriba
d7251f223e Added sync_queue_base and refactor the concurrent queues to make use of this class. Make other refactor on priority and timed queues. 2014-11-01 11:02:18 +01:00
Vicente J. Botet Escriba
20a6ef7de8 Added wait_until_not_empty, wait_until_not_empty_or_closed. Rename _q_qempty to _not_empty. 2014-11-01 01:14:41 +01:00
Vicente J. Botet Escriba
d5c41e4c4a Added tyy_pus returning queue_op_status. Rename is_closed to closed. 2014-10-31 23:49:34 +01:00
Vicente J. Botet Escriba
b96b9904b7 move scheduled_executor_base.hpp and declare scheduled_thread_pool::worker_loop inline. 2014-10-31 08:21:27 +01:00
Vicente J. Botet Escriba
304240b206 Move priority/timed queues to concurrent name space and scheduled executors to executors name spapce. 2014-10-31 08:03:15 +01:00
Vicente J. Botet Escriba
c61c139933 merged scheduled executors GSOC project from Ian Forbed. 2014-10-31 00:19:10 +01:00
Vicente J. Botet Escriba
5fb51a74fe remove thread_was_interrupted and fix wait_internal pending issue. 2014-10-24 18:43:26 +02:00
Vicente J. Botet Escriba
02bb6abef4 Merge pull request #29 from awulkiew/patch-1
Change members order in win32 thread_data_base to match ctor initializer...
2014-10-23 00:39:04 +02:00
Adam Wulkiewicz
1a4bd71616 Change members order in win32 thread_data_base to match ctor initializer list. 2014-10-23 00:01:37 +02:00
Vicente J. Botet Escriba
63dd439992 update history. 2014-10-12 16:28:29 +02:00
Vicente J. Botet Escriba
1029fa9c59 take in account deferred/ready futures on variadic when_all/when_any. 2014-10-12 15:47:16 +02:00
Vicente J. Botet Escriba
3e28ea806c Added deferred then tests. 2014-10-11 07:33:57 +02:00
Vicente J. Botet Escriba
07dc40a9ff Added missing boost/config.hpp file when checking for BOOST_NO_CXX11_DECLTYPE. 2014-10-09 06:51:02 +02:00
Vicente J. Botet Escriba
6f91af2154 Try to address #9569. 2014-10-05 09:11:58 +02:00
Vicente J. Botet Escriba
c3cff80557 Merge branch 'develop' of github.com:boostorg/thread into develop 2014-10-05 09:07:18 +02:00
Vicente J. Botet Escriba
729c8b63bb added missing file. 2014-10-05 09:06:52 +02:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
6fe7f44ea0 Clarified issue #6782 which can now be closed. 2014-10-04 19:47:48 +01:00
Vicente J. Botet Escriba
8fd4755e79 Added shared_future::then executor. 2014-10-04 10:36:57 +02:00
Vicente J. Botet Escriba
02b007a20e Make nullary_function copyable and movable following Boost.Move. Make use of std::shared_ptr when available. 2014-10-04 10:36:44 +02:00
Vicente J. Botet Escriba
c0c78e87fc Make invoker copyable and movable following Boost.Move. 2014-10-04 10:36:31 +02:00
Vicente J. Botet Escriba
58cde5af05 Trying to use std::function for executors::work. This doesn't works yet. 2014-10-03 21:46:57 +02:00
Vicente J. Botet Escriba
c1f2c8a1f1 Added shared_ptr.hpp. 2014-10-03 21:43:50 +02:00
Vicente J. Botet Escriba
bacf5b52ec The added commented lines should work, but don't. 2014-10-03 21:42:42 +02:00
Vicente J. Botet Escriba
3babf7966e update doc for future/shared_future::then(Executor, Fct). 2014-10-02 22:34:47 +02:00
Vicente J. Botet Escriba
f3de7bf10f Add fuutre::then(ex, fct). 2014-10-02 07:36:52 +02:00
Vicente J. Botet Escriba
90154217cf Added const to shred_future::then(). 2014-10-01 08:34:34 +02:00
Vicente J. Botet Escriba
ac0b2f9ba7 minor changes to unwrap. 2014-10-01 07:55:36 +02:00
Vicente J. Botet Escriba
da739e680a Merge pull request #27 from Lastique/patch-4
Fix GCC warnings about initialization order
2014-09-30 23:54:06 +02:00
Andrey Semashev
b240b097c7 Fix GCC warnings about initialization order 2014-09-30 22:42:13 +04:00
Vicente J. Botet Escriba
debe2fb0d1 Merge pull request #26 from Lastique/patch-3
Fix compilation with BOOST_USE_WINDOWS_H defined
2014-09-30 20:38:35 +02:00
Andrey Semashev
b264ec8fc0 Fix compilation with BOOST_USE_WINDOWS_H defined
Don't use macros defined only in Windows SDK 6.0 and later as this breaks compilation with MinGW and older MSVC.
2014-09-30 22:17:44 +04:00
Vicente J. Botet Escriba
372f8fe10f Merge branch 'develop' of github.com:boostorg/thread into develop 2014-09-29 23:22:16 +02:00
Vicente J. Botet Escriba
e3c240df0a shared_future<R>::then() should be const. 2014-09-29 23:22:03 +02:00
Niall Douglas
748ea5164e Merge pull request #25 from MarcelRaad/patch-1
Fix GetTickCount return type
2014-09-29 19:18:38 +01:00
Vicente J. Botet Escriba
b44627f97d don't use std::queue with MSVC 11. 2014-09-29 00:19:35 +02:00
Vicente J. Botet Escriba
c8cd7d1d08 don't check for is_ready on all the futures when using when_wny. 2014-09-29 00:19:18 +02:00
Vicente J. Botet Escriba
f0d0c0551b rollback to not define BOOST_RESULT_OF_USE_DECLTYPE. 2014-09-29 00:00:49 +02:00
Vicente J. Botet Escriba
bb72eadbd8 Added validation of invalid inner future in wrap. 2014-09-29 00:00:06 +02:00
Marcel Raad
f52f32afda Fix GetTickCount return type
int as a return type results in a signed/unsigned mismatch warning with MSVC (although disabled by default), and it doesn't even compile with clang-cl if the definiton from the Windows header was included before.
2014-09-28 21:25:36 +02:00
Vicente J. Botet Escriba
b973e9b32e remove BOOST_THREAD_NO_CXX11_DECLTYPE_N3276. 2014-09-28 13:46:21 +02:00
Vicente J. Botet Escriba
1ffef9ed2d Add missing invoke.hpp include. 2014-09-28 13:40:16 +02:00
Vicente J. Botet Escriba
f24ea524bd Remove confusing may be remark and replace T by FutTypes. 2014-09-28 11:55:35 +02:00
Vicente J. Botet Escriba
4111471ba5 fix typo on file guard. 2014-09-28 09:19:42 +02:00
Vicente J. Botet Escriba
5e970b987e remove warning. 2014-09-28 00:34:15 +02:00
Vicente J. Botet Escriba
c7b5729cf3 Avoid the use fo invoke if not available, even if the semantics is not the same. 2014-09-27 19:59:25 +02:00
Vicente J. Botet Escriba
291ebded8e update changes and compliance with last fixed issues. 2014-09-27 19:58:17 +02:00
Vicente J. Botet Escriba
0c2c8ed3b8 Update doc with last modifications from Concurrent TS. 2014-09-27 19:57:33 +02:00
Vicente J. Botet Escriba
5294dfa149 Update doc with last modifications from Concurrent TS. 2014-09-27 16:45:39 +02:00
Vicente J. Botet Escriba
7f5dfb633d MSVC 10 doesn't provide std::is_copy_constructible. Make use of the boost version. 2014-09-26 06:48:40 +02:00
Vicente J. Botet Escriba
f381a7d591 Don't delete copy constructor when rvalue references are disabled. 2014-09-25 07:25:39 +02:00
Vicente J. Botet Escriba
aceabda609 try to avoid to unlock prematurely to see if this is the cause of the test_latch spourious failure. 2014-09-24 08:09:40 +02:00
Vicente J. Botet Escriba
dc4b619b57 Don't delete copy constructor when rvalue references are disabled. 2014-09-23 23:34:42 +02:00
Vicente J. Botet Escriba
abb3fc97e0 fix reported error. 2014-09-23 23:30:26 +02:00
Vicente J. Botet Escriba
ec6ae7b9b4 Take in account small durations. 2014-09-23 23:29:38 +02:00
Vicente J. Botet Escriba
8c5ba97d39 Don't use lambdas on test if not available. 2014-09-21 18:59:08 +02:00
Vicente J. Botet Escriba
617b979214 try a workaround with MSVC for error C3520: 'T' : parameter pack must be expanded in this context. 2014-09-21 18:58:41 +02:00
Vicente J. Botet Escriba
96667cfcce MSVC 10 doesn't provide std::is_move_constructible. Let as if all classes were movable in this case. 2014-09-21 18:58:23 +02:00
Vicente J. Botet Escriba
a981650ce9 cleanup. 2014-09-20 16:11:03 +02:00
Vicente J. Botet Escriba
00b25853b2 Added when_all/when_any iterators tests. 2014-09-20 16:05:19 +02:00
Vicente J. Botet Escriba
ef04ce8bce enable disabled test. 2014-09-20 14:53:06 +02:00
Vicente J. Botet Escriba
5091ad705f Added when_any/variadic_pass.cpp. 2014-09-20 14:37:47 +02:00
Vicente J. Botet Escriba
b77f802c47 variadic when_all/when_any must retur tuple instead of vector even when all the types are the same.. 2014-09-20 13:25:50 +02:00
Vicente J. Botet Escriba
da945436c1 avoid call to boost::get_system_time() when relative is true. 2014-09-14 21:51:01 +02:00
Vicente J. Botet Escriba
27befdf26f Added test for threads_specific_ptr<void>. 2014-09-14 21:49:31 +02:00
Vicente J. Botet Escriba
f73007910a replace unique_ptr<T> by optional<T> on shared_state when rvalue references are supported by the compiler, as optional<T> doesn't use Boost.Move. 2014-09-14 21:12:44 +02:00
Vicente J. Botet Escriba
8c3cfacf06 emulate template alias queue views. 2014-09-14 21:00:27 +02:00
Vicente J. Botet Escriba
7d4392e157 try to get rid of missing std::is_copy_constructible < gcc-4.5. 2014-09-14 09:09:59 +02:00
Vicente J. Botet Escriba
aff3f424a9 move sync_queue_closed to concurrent directory. 2014-09-13 22:17:19 +02:00
Vicente J. Botet Escriba
546ca909c4 try to avoid issue with < gcc-4.5 - error: 'is_copy_constructible' is not a member of 'std'. 2014-09-13 22:16:57 +02:00
Vicente J. Botet Escriba
7dac51706c Merge branch 'develop' 2014-09-12 23:40:30 +02:00
Vicente J. Botet Escriba
5ee0e27b5a add more try catch to trac the source of the error. 2014-09-12 22:50:56 +02:00
Vicente J. Botet Escriba
b4fd7fdeb1 fail test when exception cautch instead of rethrow it. 2014-09-11 13:33:43 +02:00
Vicente J. Botet Escriba
c75ea7db89 force the use of lambdas when available on multi_thread_pass test. 2014-09-11 13:32:11 +02:00
Vicente J. Botet Escriba
19294dc756 Change ref by ptr on queue fields of queue_views so that the default constructors can be generated on MSVC. 2014-09-11 13:30:48 +02:00
Vicente J. Botet Escriba
52a360775e cleanup. 2014-09-11 07:32:40 +02:00
Vicente J. Botet Escriba
c632b75db1 fix uninitialized variable. 2014-09-11 07:29:53 +02:00
Vicente J. Botet Escriba
11e4c950ac fix 10478 data race in boost/thread/future.hpp 2014-09-10 13:44:44 +02:00
Vicente J. Botet Escriba
8440e9a7d8 add tests on non_intettuption_point::sleep_... 2014-09-10 13:42:15 +02:00
Vicente J. Botet Escriba
02bc292c20 document non_intettuption_point::sleep_... 2014-09-10 13:41:11 +02:00
Vicente J. Botet Escriba
6d68bac44b fix move semantic issues on promise::set_value. Prepare the use of unique_ptr<T,D> to fix allocator issue. 2014-09-09 13:21:01 +02:00
Vicente J. Botet Escriba
5d0d128cab let movelib do the std adaptation. 2014-09-09 13:15:51 +02:00
Vicente J. Botet Escriba
ec542d3c8b remove commented code. 2014-09-08 05:49:10 +02:00
Vicente J. Botet Escriba
6e3216643b Remove future_traits<> as there are always an specialization. 2014-09-07 19:46:02 +02:00
Vicente J. Botet Escriba
016f5653cf Added when_all().then() tests. 2014-09-07 09:04:00 +02:00
Vicente J. Botet Escriba
ce46539183 Added when_all/when_any/queue_views tests. 2014-09-06 23:30:50 +02:00
Vicente J. Botet Escriba
e93035ce42 Added run_if_is_deferred to shared_future. 2014-09-06 23:30:36 +02:00
Vicente J. Botet Escriba
53a46593a8 make classes using BOOST_THREAD_MOVABLE_ONLY<T> satisfy is_copy_constructible<T>::value == false. 2014-09-06 14:20:59 +02:00
Vicente J. Botet Escriba
c2426b8fad fix missin common virtual function in queue_base_copyable_only. 2014-09-06 14:19:37 +02:00
Vicente J. Botet Escriba
7d841f6337 fix typo. 2014-09-06 14:18:36 +02:00
Vicente J. Botet Escriba
556bbde8a7 Implemented when_all/when_any when a tuple is returned. 2014-09-04 20:00:03 +02:00
Vicente J. Botet Escriba
a0c1462a6a merge from develop. 2014-09-02 21:41:59 +02:00
Vicente J. Botet Escriba
234df13faf remove BOOST_THREAD_USES_LOG. 2014-09-01 19:59:30 +02:00
Vicente J. Botet Escriba
24983f0bce Let the deferred tests be executed when BOOST_THREAD_PROVIDES_VARIADIC_THREAD is defined. 2014-08-31 20:05:43 +02:00
Vicente J. Botet Escriba
722997379b Added thread pool join function. 2014-08-31 18:16:49 +02:00
Vicente J. Botet Escriba
f36f5d6dbb Added more async deferred tests. 2014-08-31 18:16:14 +02:00
Vicente J. Botet Escriba
9ee1044f92 Merge branch 'develop' of github.com:boostorg/thread into develop 2014-08-31 09:00:04 +02:00
Vicente J. Botet Escriba
ebeb36646c Add test for issue #10340. 2014-08-31 08:59:40 +02:00
Vicente J. Botet Escriba
8ebf0e7f21 take in account ready tasks on when_all/when_any. 2014-08-31 08:57:27 +02:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
0dc2f69bc1 Fixed typo in just made merge for WinRT support. 2014-08-30 18:58:43 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
c3b549d947 Merge branch 'MSOpenTech-winrt2' into develop 2014-08-30 18:24:46 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
6552cf64b5 Fixed up WinRT support patch not compiling on WinRT. 2014-08-30 18:24:13 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
d5f335b8a4 Merge branch 'winrt2' of https://github.com/MSOpenTech/thread into MSOpenTech-winrt2 2014-08-30 17:16:17 +01:00
Vicente J. Botet Escriba
80591fb64d try to fix 10428 for uinque_ptr issues. 2014-08-30 17:57:12 +02:00
Vicente J. Botet Escriba
0543b522cb try to fix 10340. 2014-08-30 17:54:12 +02:00
Vicente J. Botet Escriba
3dbc5d0664 Added when_all/when_any documentation. 2014-08-30 13:43:42 +02:00
Vicente J. Botet Escriba
2d0272345b update doc cith generic executor and queue views. 2014-08-30 10:07:08 +02:00
Vicente J. Botet Escriba
f1a274b51c make it possible to have polymorphic queue copyable_only/movable_only/copyable_and_movable. 2014-08-29 21:06:15 +02:00
Vicente J. Botet Escriba
b7f1706ab8 Add test won when_all iterators for c++98 compilers. 2014-08-29 21:04:33 +02:00
Vicente J. Botet Escriba
f299fb8083 fix typo. 2014-08-29 12:51:42 +02:00
Vicente J. Botet Escriba
074dcbcbf5 make polymorphic queues move operations only available if C++11 RVALE supported. 2014-08-28 22:26:02 +02:00
Vicente J. Botet Escriba
af6f80a3c7 Added generic_executor_ref.cpp tp regression tests. 2014-08-27 13:36:58 +02:00
Vicente J. Botet Escriba
957253401f Try to fix invoker making it ComyConstructible and Movable. 2014-08-27 13:35:59 +02:00
Vicente J. Botet Escriba
3195253230 rollback last merge as it is breaking all the regression tests. 2014-08-27 00:16:19 +02:00
Vicente J. Botet Escriba
4336a7bbe3 Merge pull request #24 from MarcelRaad/patch-1
Use BOOST_THREAD_RV_REF for move constructors
2014-08-26 18:44:38 +02:00
Marcel Raad
3b75d6dabc Use BOOST_THREAD_RV_REF for move constructors
If BOOST_THREAD_FWD_REF is used, the copy constructor is re-declared. Tested with clang 3.4.
2014-08-26 10:17:26 +02:00
Vicente J. Botet Escriba
fc0d7e23b3 remove todo comments. 2014-08-25 17:17:50 +02:00
Vicente J. Botet Escriba
aeabda8d45 make use of move when a rvalue is used and make use of BOOST_THREAD_FWD_REF when a URef is used. 2014-08-24 22:48:06 +02:00
Vicente J. Botet Escriba
3bde7e103c Added virtual submit(work&). 2014-08-24 18:17:59 +02:00
Vicente J. Botet Escriba
ea0889485e Make use of BOOST_THREAD_COPYABLE_AND_MOVABLE and BOOST_THREAD_COPY_ASSIGN_REF when appropriated. 2014-08-24 18:16:28 +02:00
Vicente J. Botet Escriba
d4d46c64dd fix loop_executor run_queued_closures issue. 2014-08-23 19:14:21 +02:00
Vicente J. Botet Escriba
f3fa80c866 Added generic_executor_ref, queue_base and queue views, fix some issues in executors. 2014-08-23 18:29:47 +02:00
Vicente J. Botet Escriba
7e21f24991 Merge branch 'develop' of github.com:boostorg/thread into develop 2014-08-21 19:18:56 +02:00
Vicente J. Botet Escriba
2037a64c51 Avoid pedantic clang watnings. 2014-08-21 19:17:27 +02:00
Vicente J. Botet Escriba
8bfd1cea31 fix typo. 2014-08-21 19:16:41 +02:00
Niall Douglas
a26e7eb8c4 Merge pull request #22 from eldiener/master
For clang turn warnings to 'on' and remove '-pedantic' to avoid Boost PP...
2014-08-05 10:10:05 +01:00
Edward Diener
e47eba8751 For clang turn warnings to 'on' and remove '-pedantic' to avoid Boost PP warnings. 2014-08-04 19:30:29 -04:00
Eric Niebler
8aef8000d9 Merge branch 'master' into develop 2014-08-03 12:12:27 -07:00
Andrey Semashev
0b2a61bca0 Fixed compilation with gcc 4.6 in C++11 mode
The compiler considers invoke() call ambiguous when the function object is actually a function pointer. This caused compilation errors in Boost.Coroutine, which uses invoke() through call_once(). Also added missing includes.
2014-08-03 11:58:54 -07:00
Niall Douglas
78f1044c68 The previous mingw32 fix unfortunately broke mingw-w64, so that is now fixed too. 2014-08-02 21:38:31 +01:00
Niall Douglas
26042ca26a Fixed mingw32 compile breakage. 2014-08-02 18:56:08 +01:00
Vicente J. Botet Escriba
74132067ba prepare tss<void>. 2014-07-31 19:29:19 +02:00
Vicente J. Botet Escriba
c4d42e6b6c make use of wait_pull_front instead of pull_front. 2014-07-31 19:28:04 +02:00
Vicente J. Botet Escriba
59c504d5d8 Merge pull request #21 from Lastique/patch-3
Fixed compilation with gcc 4.6 in C++11 mode
2014-07-31 07:11:42 +02:00
Andrey Semashev
b81a838a43 Fixed compilation with gcc 4.6 in C++11 mode
The compiler considers invoke() call ambiguous when the function object is actually a function pointer. This caused compilation errors in Boost.Coroutine, which uses invoke() through call_once(). Also added missing includes.
2014-07-31 02:27:33 +04:00
Vicente J. Botet Escriba
c6e70226ea Merge branch 'develop' 2014-07-26 07:19:59 +02:00
Vicente J. Botet Escriba
5cdd807718 fix typo. 2014-07-26 07:19:28 +02:00
Vicente J. Botet Escriba
2a6948d74d comment scheduled_executor. 2014-07-26 06:07:30 +02:00
Steve Gates
a06dde3794 Merge branch 'develop' into winrt2
Conflicts:
	include/boost/thread/win32/thread_primitives.hpp
	src/win32/gettickcount64.cpp
2014-07-18 12:19:46 -07:00
Steve Gates
726a3faf19 Removing QueueUserAPC on Windows Runtime. 2014-07-17 10:49:09 -07:00
Niall Douglas
590a3d99b0 Merge pull request #20 from ned14/develop
Decrufted GetTicksCount64 patch. Fixed break of build on MSVC.
2014-07-11 10:27:27 +01:00
Steve Gates
c977c8d420 Qualifying some functions calls in thread_primitives.hpp to avoid potentially ambiguity. 2014-07-10 18:09:24 -07:00
Steve Gates
a1faacd7bb Fixing up copyrights that got reordered. 2014-07-09 16:43:48 -07:00
Steve Gates
866b78cbd0 Addressing more feedback:
Reverting disabling thread attributes for WinRT.
Created common GetSystemInfo/GetNativeSystemInfo function.
Fix this_thread get_id() bug on WinRT.
Enabled initializing the Windows Runtime in each test for execution. This
is not when using in Windows store/phone applications, just if a desktop
app.
2014-07-09 15:47:37 -07:00
Steve Gates
0861f81b05 Merge branch 'develop' of https://github.com/boostorg/thread into feedback 2014-07-08 14:53:47 -07:00
Steve Gates
6488028a22 Incorporating feedback: removed copyright, removed some ifdefs. 2014-07-08 14:53:39 -07:00
Vicente J. Botet Escriba
14dfe49c50 Merge branch 'develop' 2014-07-08 21:56:44 +02:00
Vicente J. Botet Escriba
08c4599fb6 Added inline for when_all() and when_any(). 2014-07-07 22:07:44 +02:00
Vicente J. Botet Escriba
ca14e6187d Merge branch 'develop' 2014-07-06 18:48:30 +02:00
Vicente J. Botet Escriba
f263c6014e fix wait_pull_front in case the queue is closed while empty. 2014-07-06 18:47:48 +02:00
Vicente J. Botet Escriba
9e962e12e2 Merge branch 'develop' 2014-07-06 11:48:55 +02:00
Vicente J. Botet Escriba
6e154d45a4 fix wait_pull_front issue introduced in previous commit and add more tests. 2014-07-06 11:05:51 +02:00
Vicente J. Botet Escriba
c54e519f72 disable traces. 2014-07-06 11:03:30 +02:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
5c61dced5e Replaced tabs with spaces. 2014-07-05 19:31:42 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
8a7f927be9 Fixed breakage on MSVC. 2014-07-05 19:30:58 +01:00
Vicente J. Botet Escriba
6074487b73 Fix isse on sync_bounded_queue::wait_push_front and add tests. 2014-07-05 19:38:10 +02:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
04c53415fd Extracted the original GetTicksCount64 de-cruft patch and rebased on boostorg/thread:develop. 2014-07-05 16:38:17 +01:00
Vicente J. Botet Escriba
fe6daec2bc don't close the queue when an exception is throw, don't return empty on wait_pull_pull_front. 2014-07-05 14:57:37 +02:00
Vicente J. Botet Escriba
f75b2ca155 don't close the queue when an exception is throw, don't return empty on wait_pull_pull_front. 2014-07-05 14:57:10 +02:00
Vicente J. Botet Escriba
68be44ec06 Restore breaking change. 2014-07-05 10:34:22 +02:00
Vicente J. Botet Escriba
817591b87c protect the use of && when BOOST_NO_CXX11_RVALUE_REFERENCES is defined. 2014-07-04 08:07:57 +02:00
Vicente J. Botet Escriba
d7a3f124db Merge branch 'develop' 2014-07-03 07:10:04 +02:00
Vicente J. Botet Escriba
c6817aeb1c fall back to harware concurrency when physical concurrency doesn't works. 2014-07-03 07:08:07 +02:00
Steve Gates
9ceea9822f Enabling Boost.Thread to be used in the Windows Runtime.
This involves basically 3 changes:
1. Using __declspec(thread) instead of the Tls APIs.
2. Using Windows::System::Threading since Win32 Threading APIs aren't allowed.
3. Updating or replacing some banned APIs like WaitForSingleObject with WaitForSingleObjectEx.
2014-07-02 14:21:43 -07:00
Vicente J. Botet Escriba
c266790b8d Try to fix phisical_concurrency on PowerPC arch. 2014-06-29 23:48:18 +02:00
Vicente J. Botet Escriba
00ad9dddb9 Added nested type op_status. 2014-06-29 23:04:34 +02:00
Vicente J. Botet Escriba
21617e1acb Merge pull request #15 from Lastique/patch-2
Fix warnings about redefining a defined macro
2014-06-22 17:41:34 +02:00
Andrey Semashev
99ac322223 Fix warnings about redefining a defined macro
The warnings appear when a dependent project (e.g. Boost.Log tests and examples) builds with link=shared and defines BOOST_ALL_DYN_LINK macro. In this case BOOST_THREAD_USE_DLL is defined by both thread/build/Jamfile.v2 and boost/thread/detail/config.hpp. This commit makes sure that doesn't happen.
2014-06-22 19:13:01 +04:00
Vicente J. Botet Escriba
414fce4580 Merge branch 'develop' 2014-06-13 18:58:08 +02:00
Vicente J. Botet Escriba
fe195e776b make use of underlying_cast<int> insted of int cast. 2014-06-12 19:43:16 +02:00
Vicente J. Botet Escriba
8a6d3d68ce Merge pull request #14 from MarcelRaad/patch-1
Fix for BOOST_NO_CXX11_RVALUE_REFERENCES
2014-06-12 18:40:01 +02:00
Marcel Raad
3a5c926930 Fix for BOOST_NO_CXX11_RVALUE_REFERENCES
Fix compilation of future.hpp with BOOST_NO_CXX11_RVALUE_REFERENCES defined. Tested on clang and MSVC12.

BOOST_NO_CXX11_RVALUE_REFERENCES has to be defined if the compiler provides rvalue references, but the standard library doesn't provide std::move. Without these fixes, the deleted copy constructor is called.
2014-06-12 17:41:20 +02:00
Vicente J. Botet Escriba
685ee1506a Merge branch 'develop' 2014-06-10 17:42:23 +02:00
Vicente J. Botet Escriba
2062cebb54 Merge pull request #13 from danieljames/json-fix
Json fix
2014-06-10 07:29:01 +02:00
Daniel James
126030eb8c JSON fix. 2014-06-10 00:18:36 +01:00
Vicente J. Botet Escriba
ac1b9653f3 Merge branch 'develop' 2014-06-09 17:55:57 +02:00
Vicente J. Botet Escriba
54ee07e745 Make use of core files. 2014-06-09 17:35:00 +02:00
Vicente J. Botet Escriba
ca298c2c86 Don't use atomic<thread::id> and so don't use testable_mutex. 2014-06-09 15:41:42 +02:00
Vicente J. Botet Escriba
4def87448e Merge pull request #12 from Lastique/patch-3
Silence warnings about unused variables.
2014-06-09 15:07:48 +02:00
Vicente J. Botet Escriba
5719ea9e9f Added meta/libraries.json. 2014-06-09 14:07:54 +02:00
Vicente J. Botet Escriba
6583d87c92 Added README.md. 2014-06-09 14:05:57 +02:00
Vicente J. Botet Escriba
fcf7a1811e make use of underlying_cast<int> when casting from an enum class. 2014-06-09 14:04:11 +02:00
Andrey Semashev
d8f628ae65 Silence warnings about unused variables. 2014-06-09 15:20:12 +04:00
Vicente J. Botet Escriba
0bd10b7244 Merge branch 'develop' 2014-06-08 12:11:31 +02:00
Vicente J. Botet Escriba
24635c588f Removed incomplete file. 2014-06-04 13:04:59 +02:00
Vicente J. Botet Escriba
4f8106c00e remove dependency on Optional. 2014-06-04 08:21:08 +02:00
Vicente J. Botet Escriba
3c4f1ea365 remove dependency on MPL. 2014-06-04 08:20:28 +02:00
Vicente J. Botet Escriba
b5a50ab443 remove unused param warning. 2014-06-04 08:19:34 +02:00
Vicente J. Botet Escriba
cb8a4a27bb Throw if malloc fails. 2014-05-31 18:19:43 +02:00
Vicente J. Botet Escriba
8c0640e5be Fix typo. 2014-05-21 20:07:53 +02:00
Vicente J. Botet Escriba
f807a678e0 Merge branch 'develop' of github.com:boostorg/thread into develop 2014-05-21 19:52:01 +02:00
Vicente J. Botet Escriba
49a1779d7f Merge pull request #10 from kylelutz/variadic-wait-for
Variadic wait functions
2014-05-21 19:48:04 +02:00
Kyle Lutz
d3d2ad2390 Add variadic wait_for_all() and wait_for_any() functions 2014-05-20 22:49:44 -07:00
Vicente J. Botet Escriba
abf844f50e fix #10008. 2014-05-08 01:30:23 +02:00
Vicente J. Botet Escriba
4d52ef0740 Comment no more existing functions. 2014-04-28 18:41:53 +02:00
Vicente J. Botet Escriba
40620e3d4b Merge branch 'develop' 2014-04-27 15:45:16 +02:00
Vicente J. Botet Escriba
c3ab21a7ba comment mingw toolset flags - #3967. 2014-04-19 13:04:15 +02:00
Vicente J. Botet Escriba
c3002edc54 cleanup. 2014-03-30 17:29:06 +02:00
Vicente J. Botet Escriba
100bb706d6 Merge branch 'develop' 2014-03-17 19:55:06 +01:00
Vicente J. Botet Escriba
de6a4df3a8 Merge pull request #7 from kylelutz/fix-futures-doc
Thanks for the signaling this typo.
2014-03-13 08:46:13 +01:00
Kyle Lutz
9669830a86 Fix documentation for shared_future example 2014-03-12 20:35:27 -07:00
Vicente J. Botet Escriba
2937171413 Added asynchronous executors doc. 2014-03-12 00:04:03 +01:00
Vicente J. Botet Escriba
dd0bfdd7ce Update compliance to standard proposals. 2014-03-12 00:03:19 +01:00
Vicente J. Botet Escriba
89e340b177 Update last fixed bugs. 2014-03-12 00:02:44 +01:00
Vicente J. Botet Escriba
c744899e45 Complete sync queues reference doc. 2014-03-12 00:02:12 +01:00
Vicente J. Botet Escriba
0a4af0c5ed Merge branch 'develop' 2014-03-10 19:28:02 +01:00
Vicente J. Botet Escriba
e6eb24d4a9 Merge pull request #6 from Lastique/patch-1
Fix compilation on Windows
2014-03-10 18:55:19 +01:00
Andrey Semashev
0d10e282fa Fix compilation on Windows
Corrected is_special method name.
2014-03-10 19:43:46 +03:00
Vicente J. Botet Escriba
e8181da6d4 Merge branch 'develop' 2014-03-09 14:47:51 +01:00
Vicente J. Botet Escriba
68dc454a66 Take in account pos_infinity. 2014-03-09 14:42:50 +01:00
Vicente J. Botet Escriba
0e0ee99c61 Added BOOST_THREAD_DECL to GetTickCount64. 2014-03-04 00:29:39 +01:00
Vicente J. Botet Escriba
f747d79c5b comment redefinition of ticks_type. 2014-03-02 12:46:56 +01:00
Vicente J. Botet Escriba
73fbc520e8 extract async executor test. 2014-03-01 08:38:08 +01:00
Vicente J. Botet Escriba
7d4f485ade Added test for #9303. 2014-03-01 08:32:53 +01:00
Vicente J. Botet Escriba
143adde27d pull patch for #8070. 2014-02-27 07:47:20 +01:00
Vicente J. Botet Escriba
a7400061c6 added test for #9711. 2014-02-26 22:09:15 +01:00
Vicente J. Botet Escriba
d2a65d2427 fix #9711. 2014-02-26 22:08:09 +01:00
Vicente J. Botet Escriba
82379f83a8 fix #9673. 2014-02-26 18:48:02 +01:00
Vicente J. Botet Escriba
cc29295986 Merge branch 'develop' 2014-02-21 13:37:06 +01:00
Vicente J. Botet Escriba
9d1c957625 change check time to 500 ms. 2014-02-21 13:36:33 +01:00
Vicente J. Botet Escriba
1dbf7028fe Try to workaround some issues with MSVC lambdas. 2014-02-21 10:52:18 +01:00
Vicente J. Botet Escriba
0bba5e630e Merge branch 'develop' 2014-02-16 23:39:00 +01:00
Vicente J. Botet Escriba
84c30313a2 Start invoker_ret. 2014-02-16 23:34:52 +01:00
Vicente J. Botet Escriba
54646e9959 Added sleep_for/until with no interruption point. 2014-02-16 23:33:03 +01:00
Vicente J. Botet Escriba
3f5823f50a Add parallel_quick_sort example. 2014-02-16 17:25:49 +01:00
Vicente J. Botet Escriba
e1636bdbd5 Take care of #9618: try_join_for(ms(1)). 2014-02-16 10:53:07 +01:00
Vicente J. Botet Escriba
750c849b0f merge from develop for 1.56. 2014-02-15 16:08:32 +01:00
Vicente J. Botet Escriba
0a05db8399 rename async_func.hpp by invoker.hpp. 2014-02-11 22:39:55 +01:00
Vicente J. Botet Escriba
1d7da085ea rename async_func.hpp by invoker.hpp. 2014-02-10 07:42:28 +01:00
Vicente J. Botet Escriba
75236fe3ae rename async_func by invoker. 2014-02-09 16:53:19 +01:00
Vicente J. Botet Escriba
80634ee51e Added with_lock_guard example. 2014-02-09 04:01:53 +01:00
Vicente J. Botet Escriba
b1ac899f23 Pulled with_lock_guard patch. 2014-02-09 03:42:39 +01:00
Vicente J. Botet Escriba
aa37de7aad remove traces on tests. 2014-02-08 17:48:54 +01:00
Vicente J. Botet Escriba
9d527bebe0 fix typo on scoped_thread tutorial. 2014-02-08 17:47:28 +01:00
Vicente J. Botet Escriba
f7c18c55bb remove availability of deprecated functions. 2014-02-08 17:46:34 +01:00
Vicente J. Botet Escriba
1a2197c7f9 Added exceptional_ptr documentation. 2014-02-08 17:45:41 +01:00
Vicente J. Botet Escriba
4a54ac0331 make functions that must be private private, e.g. as start_thread. 2014-02-08 17:43:23 +01:00
Vicente J. Botet Escriba
c6593d87b0 clarify thread destructor and move constructor semantics. 2014-02-08 17:42:28 +01:00
Vicente J. Botet Escriba
51e49c69b5 refactor elapsed time check and fix bad uses of base_type. in csbl::unique_ptr. 2014-02-08 16:28:02 +01:00
Vicente J. Botet Escriba
ab2a180de5 Added test for async_func and fixed a some issues. 2014-02-08 07:58:39 +01:00
Vicente J. Botet Escriba
3772a8294b Format/indent file. 2014-02-07 07:32:34 +01:00
Vicente J. Botet Escriba
155ccfffbe fix copyright. 2014-02-03 18:57:10 +01:00
Vicente J. Botet Escriba
bfa0ccee88 Added BOOST_RESULT_OF_USE_DECLTYPE on async test. 2014-02-03 18:33:01 +01:00
Vicente J. Botet Escriba
980772d514 Added make_ready_no_decay_future and remove the use of asynch on make_future test. 2014-02-03 18:31:43 +01:00
Vicente J. Botet Escriba
94b27db991 move when mawros to config.hpp file. 2014-02-03 18:30:08 +01:00
Vicente J. Botet Escriba
0a58445b63 comment #error 2014-02-02 08:47:56 +01:00
Vicente J. Botet Escriba
f02e25e4e7 Add BOOST_RESULT_OF_USE_DECLTYPE. 2014-02-02 08:45:29 +01:00
Vicente J. Botet Escriba
acb117b5a9 Added lvalue test to call_once. 2014-02-02 08:38:40 +01:00
Vicente J. Botet Escriba
8682f7cb48 Added some test to internal invoke function add the associated fixes. 2014-02-02 08:13:58 +01:00
Vicente J. Botet Escriba
4503c0e1da comment the warning as it generates an error. 2014-02-01 21:56:22 +01:00
Vicente J. Botet Escriba
dc3397c452 Added parallel_acumulate example. 2014-01-28 23:14:43 +01:00
Vicente J. Botet Escriba
af7fde5eae Added test async with a member function. 2014-01-28 23:12:29 +01:00
Vicente J. Botet Escriba
36bc3c0523 Added 2 arguments async executor. 2014-01-28 23:08:07 +01:00
Vicente J. Botet Escriba
0218cb90b3 fix typo issues on invoke. 2014-01-28 23:01:41 +01:00
Vicente J. Botet Escriba
f4d4c16294 try to fix compiler error while using std::get instead of csbl::get 2014-01-27 22:30:48 +01:00
Vicente J. Botet Escriba
85d22a8d93 Added exceptional_ptr and adapt futures to be implicitly convertible from exceptional_ptr. 2014-01-26 17:55:09 +01:00
Vicente J. Botet Escriba
7eb67443dd Added exceptional_ptr and adapt futures to be implicitly convertible from exceptional_ptr. 2014-01-26 17:53:49 +01:00
Vicente J. Botet Escriba
4308e0ec24 Added make_exceptional_future. 2014-01-26 09:19:31 +01:00
Vicente J. Botet Escriba
ac9497dec9 Try to solve some issues with invoke on MSVC. 2014-01-26 09:18:34 +01:00
Vicente J. Botet Escriba
8fec35f444 Update mutex destructor to see if the assertion message is better. 2014-01-26 09:15:12 +01:00
Vicente J. Botet Escriba
7b3fa08503 make shared_state_nullary_task copyable and movable and avoid msvc default generation. 2014-01-20 23:02:48 +01:00
Vicente J. Botet Escriba
a2e1e80343 Try to see if giving the addres solves the MSVC compiler issue. 2014-01-20 23:01:23 +01:00
Vicente J. Botet Escriba
690feeb9ba indent and comment #if. 2014-01-19 07:56:57 +01:00
Vicente J. Botet Escriba
5d76ab52e7 reorder async() conditional compilation variants to factor more code. 2014-01-19 07:52:38 +01:00
Vicente J. Botet Escriba
cb845f19e4 Fix issues with future::async and disable the code when BOOST_NO_CXX11_DECLTYPE_N3276 is defined as it is bugged. 2014-01-18 15:27:03 +01:00
Vicente J. Botet Escriba
2886e985b4 cleanup comments. 2014-01-16 23:58:37 +01:00
Vicente J. Botet Escriba
f4d0ecbab5 Added at thread entry callback on thread pool. 2014-01-13 22:51:57 +01:00
Vicente J. Botet Escriba
d187732946 Added minimal inline and thread test. 2014-01-13 22:32:30 +01:00
Vicente J. Botet Escriba
1fc78c7ceb Added inline and thread executors. 2014-01-13 22:16:09 +01:00
Vicente J. Botet Escriba
5c18d92a5f Make work public. 2014-01-13 22:10:34 +01:00
Vicente J. Botet Escriba
06325961ef Make work public. 2014-01-13 22:09:43 +01:00
Vicente J. Botet Escriba
10b283e03a Added missing iomanip include. 2014-01-13 22:08:20 +01:00
Vicente J. Botet Escriba
6ab71dc057 executor_adaptor<serial_executor> a(b) doesn't compiles on C++03. 2014-01-12 18:28:24 +01:00
Vicente J. Botet Escriba
47be5228b1 fix typo on try_push_back. 2014-01-12 18:26:46 +01:00
Vicente J. Botet Escriba
6c5a6e4330 Reorganized executors on its own directory adding serial_executor and renamed thread_pool by basic_thread_pool and user_scheduler by loop_scheduler. 2014-01-12 17:52:27 +01:00
Vicente J. Botet Escriba
326842cc7f Fix #9335 Missing exception safety might result in crash 2014-01-11 21:19:05 +01:00
Vicente J. Botet Escriba
9f592860cd Update sync queues closed operations 2014-01-11 18:57:44 +01:00
Vicente J. Botet Escriba
4148842426 Apply changed from #9471 Synchronization documentation nits and prepare changes notes for Boost 1.56
modified:   changes.qbk
	modified:   external_locking.qbk
	modified:   internal_locking.qbk
	modified:   thread.qbk
2014-01-11 12:44:28 +01:00
Vicente J. Botet Escriba
7edae6614b Thread: add exception trace.
[SVN r86774]
2013-11-19 22:09:40 +00:00
Vicente J. Botet Escriba
2554065a91 Thread: update doc with last features changes.
[SVN r86773]
2013-11-19 22:08:29 +00:00
Vicente J. Botet Escriba
74bb7d6b29 Thread: for explicit constructor for nullary_function.
[SVN r86772]
2013-11-19 22:00:56 +00:00
Vicente J. Botet Escriba
fbfda71555 Thread: Allows to force the use of boost libraries on csbl.
[SVN r86771]
2013-11-19 21:58:59 +00:00
Vicente J. Botet Escriba
f3a66f76e0 Thread: merge from trunk for 1.56.
[SVN r86770]
2013-11-19 21:58:34 +00:00
Vicente J. Botet Escriba
19346e1817 Thread: improve async_func to try to solve msvc issue with executor.
[SVN r86744]
2013-11-17 23:44:45 +00:00
Vicente J. Botet Escriba
5753026ceb Thread: increase the number of cycles of the failing tests.
[SVN r86732]
2013-11-17 00:32:28 +00:00
Vicente J. Botet Escriba
f6edd7cace Thread: use PP only if MSVC not defined, until I can debug it.
[SVN r86714]
2013-11-15 19:51:40 +00:00
Vicente J. Botet Escriba
126ed2428b Thread: try to remove warning C4520: 'boost::executor_adaptor<boost::thread_pool>' : multiple default constructors specified.
[SVN r86698]
2013-11-14 18:53:51 +00:00
Vicente J. Botet Escriba
fd631e2794 Thread: remove BOOST_THREAD_MAX_ARGS_P1.
[SVN r86697]
2013-11-14 17:56:07 +00:00
Vicente J. Botet Escriba
44f9a2f4ad Thread: merge dummy replacement to fix #9341.
[SVN r86658]
2013-11-12 18:35:19 +00:00
Vicente J. Botet Escriba
8665c5d510 Thread: merge missing include string.
[SVN r86657]
2013-11-12 18:33:52 +00:00
Vicente J. Botet Escriba
e1d6baddd6 Thread: merge missing thread move constructor noexcept.
[SVN r86656]
2013-11-12 18:32:37 +00:00
Vicente J. Botet Escriba
9287a29c9d Thread: Adding pp variadic to asyn_func and fix some typos.
[SVN r86629]
2013-11-11 23:00:37 +00:00
Vicente J. Botet Escriba
5c0cecaaf8 Thread: add _back/_front using queue_op_status interface to sync queues and update the depending classes thread_pool and user_scheduler; Simplfy some test to isolate the errors on msvc-12.
[SVN r86616]
2013-11-11 10:43:15 +00:00
Vicente J. Botet Escriba
713f5a449c Thread: Added missing include.
[SVN r86599]
2013-11-09 15:26:49 +00:00
Vicente J. Botet Escriba
b336427571 Thread: try to fix error on mscv-12 when scoped_thread uses private dummy class with enable_if.
[SVN r86595]
2013-11-09 11:50:21 +00:00
Vicente J. Botet Escriba
2a16b649ad Thread: Added caller_context.hpp; Change executor by Executor template parameter in async; update the number of time the failing tests are run to catch all the compilers.
[SVN r86586]
2013-11-08 17:51:39 +00:00
Vicente J. Botet Escriba
3723cedcab Thread: Added user_scheduler (loop_executor).
[SVN r86570]
2013-11-06 06:37:46 +00:00
Vicente J. Botet Escriba
3ad582222c Thread: added test for #9303.
[SVN r86569]
2013-11-05 23:08:13 +00:00
Vicente J. Botet Escriba
c9a33b8668 Thread: avoid thread ambiguity on vacpp tester.
[SVN r86568]
2013-11-05 23:07:28 +00:00
Vicente J. Botet Escriba
88880770d3 Thread: merge [86540] to fix #9319.
[SVN r86552]
2013-11-03 20:43:42 +00:00
Vicente J. Botet Escriba
9138a2ae92 Thread: Added missing variadic constructor for task_shared_state.
[SVN r86548]
2013-11-03 16:17:23 +00:00
Vicente J. Botet Escriba
d558de7811 Thread: added new/old tickets tests for regression purposes.
[SVN r86545]
2013-11-02 12:58:03 +00:00
Vicente J. Botet Escriba
19290fddf9 Thread: manage system::errc as it was an real enum class, so no implicitly convertible to an int.
[SVN r86544]
2013-11-02 09:58:33 +00:00
Vicente J. Botet Escriba
2ac967d1dc Thread: try to avoid compile error with msvc.12 or atleast remove warning C4512.
[SVN r86543]
2013-11-02 09:56:20 +00:00
Vicente J. Botet Escriba
6e81db4172 Thread: try to avoid compile error with msvc.12.
[SVN r86542]
2013-11-02 09:54:13 +00:00
Vicente J. Botet Escriba
3a68a63478 Thread: unlock around the calls to continuations oe deferred future executions.
[SVN r86540]
2013-11-01 21:08:00 +00:00
Vicente J. Botet Escriba
7875edd234 Thread: make use of csbl to make the code more readable and to ensure that it interact well with the std.
[SVN r86504]
2013-10-28 20:08:39 +00:00
Vicente J. Botet Escriba
2be0b4f8fd Thread: added missing boost/tuple/tuple.hpp file.
[SVN r86498]
2013-10-28 10:34:51 +00:00
Vicente J. Botet Escriba
67528fc9af Thread: fix thread move constructor noexecpt.
[SVN r86493]
2013-10-28 02:31:55 +00:00
Vicente J. Botet Escriba
4da1e9dca1 Thread: cleanup replacing some macros by the types imported on csbl namespace comming from std or boost. Cleanup work type ussage.
[SVN r86471]
2013-10-26 23:35:40 +00:00
Vicente J. Botet Escriba
d8c9be3449 Thread: fix change of BOOST_THREAD_VECTOR to boost::csbl::vector.
[SVN r86467]
2013-10-26 22:47:02 +00:00
Vicente J. Botet Escriba
f02390a804 Thread: fix double definition of i in test.
[SVN r86466]
2013-10-26 22:43:12 +00:00
Vicente J. Botet Escriba
955b207c05 Thread: Added csbl (Common Std Boost Library) files, which allows to use on the csbl namespace eother a std or a boost file, e.g. tuple, vector, functional.
[SVN r86453]
2013-10-26 15:07:34 +00:00
Vicente J. Botet Escriba
c17f5d3fc7 Thread: merge update history for limitations.
[SVN r86449]
2013-10-26 12:39:50 +00:00
Vicente J. Botet Escriba
8685c32d18 Thread: update history with know limitations.
[SVN r86446]
2013-10-26 11:59:52 +00:00
Vicente J. Botet Escriba
f51e8c812a Thread: Add a loop to catch more quickly the multiple bugs on boost::future experimental features and see which tester are failing.
[SVN r86444]
2013-10-26 11:22:14 +00:00
Vicente J. Botet Escriba
51aff0fb00 Thread: Adapt barrier to new nullary_function.
[SVN r86443]
2013-10-26 10:23:00 +00:00
Vicente J. Botet Escriba
bfe7af29bc Thread: adapt thread_pool and executor to the new nullary_function work.
[SVN r86442]
2013-10-26 10:21:27 +00:00
Vicente J. Botet Escriba
4681104b33 Thread: Added a portable copyable/movable thread_pool/executor work.
[SVN r86441]
2013-10-26 10:20:13 +00:00
Vicente J. Botet Escriba
d602f44af6 Thread: Added a portable copyable/movable nullary_function functor.
[SVN r86440]
2013-10-26 10:20:02 +00:00
Vicente J. Botet Escriba
dc55945760 Thread: Add BOOST_THREAD_RV when accessing a BOOST_THREAD_RV_REF to be portable.
[SVN r86439]
2013-10-26 10:19:38 +00:00
Vicente J. Botet Escriba
f7f0347780 Thread: first steps toward async(executor&, f).
[SVN r86327]
2013-10-16 06:15:51 +00:00
Vicente J. Botet Escriba
d6c4be0cd0 Thread: add thread_pool reserv for worker threads.
[SVN r86291]
2013-10-13 13:15:05 +00:00
Vicente J. Botet Escriba
e146febd70 Thread: Added future::when_all/when_any (async vector version) for C++11 compilers.
[SVN r86290]
2013-10-13 13:08:29 +00:00
Vicente J. Botet Escriba
67ca45ed83 Thread: Added synchronized_value const test.
[SVN r86283]
2013-10-13 10:13:10 +00:00
Vicente J. Botet Escriba
cad6f2b9a6 Thread: Add Copyright.
[SVN r86282]
2013-10-13 10:11:06 +00:00
Tim Blechmann
7756df2ce0 thread: physical_concurrency - avoid c++03-style vector::data
[SVN r86226]
2013-10-10 14:53:37 +00:00
Tim Blechmann
ae831efe08 thread: physical_concurrency - work around getline issue in libc++
[SVN r86216]
2013-10-09 15:25:31 +00:00
Tim Blechmann
fc65611e82 Revert "Thread: provide physical concurrency conditional until it no regression is introduced."
This reverts commit 271ba281aecd5c556b2b863a9f05a8066e717854.

[SVN r86215]
2013-10-09 15:24:58 +00:00
Vicente J. Botet Escriba
8c6dcb9709 Thread: fix some issues with double definition of shared_state_base and avoid ambiguity of disable_if with Boost.Test.
[SVN r86202]
2013-10-08 17:09:38 +00:00
Vicente J. Botet Escriba
67afa35c49 Thread: try to fix issue with double definition of shared_state_base.
[SVN r86162]
2013-10-04 20:07:03 +00:00
Vicente J. Botet Escriba
63d9ae2b29 Thread: Added a polymorphic executor and an executor_adaptor.
[SVN r86161]
2013-10-04 20:05:26 +00:00
Vicente J. Botet Escriba
08aa0d2fb6 Thread: use boost::disable_if instead of disable_if to avoid ambiguity.
[SVN r86140]
2013-10-02 22:45:23 +00:00
Stephen Kelly
3c8334f8c4 Thread: Remove obsolete GCC version check.
[SVN r86117]
2013-10-01 08:48:07 +00:00
Vicente J. Botet Escriba
0e2c8ed9e3 Thread: ensure that the thread is joined on the future destructor created by future<T>::then().
[SVN r86010]
2013-09-29 19:10:11 +00:00
Vicente J. Botet Escriba
5bfa7cff41 Thread: update history.
[SVN r86005]
2013-09-29 16:10:56 +00:00
Vicente J. Botet Escriba
e3a1498355 Thread: provide physical_concurrency conditionally.
[SVN r86002]
2013-09-29 14:41:01 +00:00
Vicente J. Botet Escriba
6fab117c17 Thread: future::then should join the thread before destruction.
[SVN r85962]
2013-09-26 14:47:24 +00:00
Vicente J. Botet Escriba
4a63d4992c Thread: provide physical concurrency conditional until it no regression is introduced.
[SVN r85926]
2013-09-26 06:54:33 +00:00
Tim Blechmann
04e3d918fb thread: implement physical_concurrency
[SVN r85864]
2013-09-24 06:41:24 +00:00
Vicente J. Botet Escriba
0073516f0a Thread: added missing function wrapper.
[SVN r85863]
2013-09-24 05:35:11 +00:00
Vicente J. Botet Escriba
89de3dcf4f Thread: make it possible to use non default constructible types in sync_queue, but sync_bounded_queue requires it yet.
[SVN r85861]
2013-09-23 21:40:08 +00:00
Vicente J. Botet Escriba
47f40f991f Thread: added first thread_pool.
[SVN r85855]
2013-09-23 16:45:00 +00:00
Vicente J. Botet Escriba
8b351fe473 Thread: fix some move semantic issues on sync_queue and sync_bounded_queue and add tests.
[SVN r85854]
2013-09-23 16:44:26 +00:00
Vicente J. Botet Escriba
2da4e8c29e Thread: add a test on get_exception_ptr.
[SVN r85843]
2013-09-22 23:35:04 +00:00
Vicente J. Botet Escriba
8dce737911 Thread: fix non-copyable issues with intel compiler.
[SVN r85842]
2013-09-22 23:33:52 +00:00
Vicente J. Botet Escriba
24f1e620e8 Thread: fix some move issues on sync_queue.
[SVN r85841]
2013-09-22 22:23:58 +00:00
Vicente J. Botet Escriba
ed6459ecd2 Thread: make code uniform heap_new/heap_delete pairwise.
[SVN r85840]
2013-09-22 22:22:08 +00:00
Andrey Semashev
3a7f0b1e78 Merged changes from trunk.
[SVN r85818]
2013-09-22 09:57:15 +00:00
Vicente J. Botet Escriba
8f06153f46 Thread: merge from trunk to fix 8070 and possibly 7461.
[SVN r85815]
2013-09-21 20:45:06 +00:00
Vicente J. Botet Escriba
858816b2d2 Thread: add detail:: to access detail::win32::GetTickCount64().
[SVN r85772]
2013-09-18 10:58:46 +00:00
Vicente J. Botet Escriba
4bc70444a4 Thread: try to fix SIGSEGV on win32 issue #7666.
[SVN r85734]
2013-09-17 21:17:02 +00:00
Vicente J. Botet Escriba
fcc027369f Thread: try to fix win32 condition_variable issue #7461.
[SVN r85733]
2013-09-17 21:01:05 +00:00
Vicente J. Botet Escriba
5c78582794 Thread: refactor make_ready_at_thread_exit + inhibit at_thread_exit functions from external threads.
[SVN r85732]
2013-09-17 20:57:46 +00:00
Vicente J. Botet Escriba
7f479a1dec Thread: Added test for tickets.
[SVN r85729]
2013-09-17 19:32:03 +00:00
Vicente J. Botet Escriba
4f2a7b2256 Thread: make use of explicit noncopyable constructor to avoid compile error with Intel compiler.
[SVN r85728]
2013-09-17 19:25:18 +00:00
Vicente J. Botet Escriba
5c88e6ce61 Thread: patch for #8070 to make use of GetTickCount64 when available.
[SVN r85714]
2013-09-16 19:43:37 +00:00
Vicente J. Botet Escriba
650e374492 Thread: Added ostream_buffer.
[SVN r85709]
2013-09-16 17:24:30 +00:00
Vicente J. Botet Escriba
6319080ef2 Thread: add test for get_exception_ptr.
[SVN r85708]
2013-09-16 17:15:05 +00:00
Vicente J. Botet Escriba
3ac48bdd65 Thread: patch for #8070 to make use of GetTickCount64 when available.
[SVN r85701]
2013-09-16 16:55:21 +00:00
Vicente J. Botet Escriba
c3c8ada97d Thread: replace TABS.
[SVN r85677]
2013-09-15 16:13:47 +00:00
Vicente J. Botet Escriba
325d8cf5ca Thread: merge atomic linked conditionaly + future:get_exception_ptr.
[SVN r85666]
2013-09-14 14:22:45 +00:00
Vicente J. Botet Escriba
134c323958 Thread: merge scoped_thread constr + condition_variable timed wait issues on windows + doc typos.
[SVN r85663]
2013-09-13 19:01:48 +00:00
Vicente J. Botet Escriba
fd5dd0c2ed Thread: added future<>::get_exception_ptr().
[SVN r85644]
2013-09-10 19:40:14 +00:00
Vicente J. Botet Escriba
4a83aa58ed Thread: add workaround for non compliants compilers on scoped_thread constructor.
[SVN r85643]
2013-09-10 18:55:52 +00:00
Vicente J. Botet Escriba
7d96aa625c Thread: update doc with history.
[SVN r85623]
2013-09-09 17:37:54 +00:00
Vicente J. Botet Escriba
5520763a73 Thread fix #8943.
[SVN r85622]
2013-09-09 17:04:15 +00:00
Vicente J. Botet Escriba
ad010e0647 Thread: fix #8417.
[SVN r85621]
2013-09-09 16:57:32 +00:00
Vicente J. Botet Escriba
d57a4c6565 Thread: link with boost_atomic conditionaly.
[SVN r85616]
2013-09-08 22:20:48 +00:00
Vicente J. Botet Escriba
73f5c060ca Thread: merge from trunk upgrade_to_unique_lock::mutex() + doc typos + BOOST_THREAD_USES_ATOMIC doc + synchronized _value call + rename wait_until params.
[SVN r85603]
2013-09-08 09:50:12 +00:00
Vicente J. Botet Escriba
c67e39f126 Thread: protect condition_variable/_any wait_for and wait_until from malicious input.
[SVN r85592]
2013-09-07 12:11:44 +00:00
Vicente J. Botet Escriba
5a3c301582 Thread: protect condition_variable/_any wait_for and wait_until from malicious input.
[SVN r85591]
2013-09-07 12:11:18 +00:00
Vicente J. Botet Escriba
dc5a8a9c4e Thread: try to handle with not needed definition of uintptr_t #8817.
[SVN r85540]
2013-09-01 07:25:56 +00:00
Vicente J. Botet Escriba
1e49343ff4 Thread: try to handle with call_once intel issue #8943.
[SVN r85539]
2013-09-01 07:22:21 +00:00
Vicente J. Botet Escriba
93d1855e64 Thread: fix scoped_thread variadic constructor.
[SVN r85494]
2013-08-27 22:37:15 +00:00
Vicente J. Botet Escriba
a39dd7e8b3 Thread: avoid conflict with thread symbol.
[SVN r85493]
2013-08-27 22:35:21 +00:00
Vicente J. Botet Escriba
7e5cb92bab Thread: fix some typos in doc.
[SVN r85492]
2013-08-27 22:31:32 +00:00
Vicente J. Botet Escriba
62cf0f86f6 Thread: fix more typos in doc.
[SVN r85485]
2013-08-27 11:32:24 +00:00
Vicente J. Botet Escriba
c12e07754a Thread: link with boost_chrono and boost_atomic independently of the platform.
[SVN r85464]
2013-08-25 15:13:17 +00:00
Vicente J. Botet Escriba
cbc4266774 Thread: rename wait_until parameter to avoid shadow with member function.
[SVN r85463]
2013-08-25 15:09:12 +00:00
Vicente J. Botet Escriba
3a038d33e5 Thread: rename check by cgeck_counter to avoid conflict with macro.
[SVN r85462]
2013-08-25 15:08:08 +00:00
Vicente J. Botet Escriba
51ba4be998 Thread: fix type and add BOOST_THREAD_USE_ATOMIC macro doc.
[SVN r85432]
2013-08-22 22:11:48 +00:00
Vicente J. Botet Escriba
2d50af8481 Thread: Added synchronized_value operator() to synchronize around a function call.
[SVN r85306]
2013-08-11 20:33:47 +00:00
Vicente J. Botet Escriba
3fb971386a Thread: merge from trunk last updates since 1.54.
[SVN r85200]
2013-08-03 16:04:39 +00:00
Vicente J. Botet Escriba
e438c98070 Thread: Add mutex() to upgrade_to_unique_lock (#8891).
[SVN r85195]
2013-08-03 07:47:18 +00:00
Vicente J. Botet Escriba
1e2a76de47 Thread: apply pathc for #8931.
[SVN r85194]
2013-08-03 07:44:15 +00:00
Vicente J. Botet Escriba
34311a60fa Thread: update doc for latches, future continuations.
[SVN r84980]
2013-07-07 20:50:14 +00:00
Vicente J. Botet Escriba
794d54a65c Thread: fix issue with continuation's future parameter which must taken by value.
[SVN r84979]
2013-07-07 20:44:02 +00:00
Vicente J. Botet Escriba
d759dd2dba Thread: fix issue with continuation's future parameter which must taken by value.
[SVN r84978]
2013-07-07 20:36:05 +00:00
Hartmut Kaiser
fe46155997 Getting rid of 64bit warning generated by VS2012
[SVN r84960]
2013-07-06 18:51:54 +00:00
Vicente J. Botet Escriba
cacb5b19a6 Thread: fix issue with future<>::then() when th efuture was not created with async.
[SVN r84955]
2013-07-04 21:44:25 +00:00
Vicente J. Botet Escriba
30803a38b2 Thread: Added assertion on testable_mutex lock when the mutex is locked by this thread.
[SVN r84954]
2013-07-04 21:42:11 +00:00
Vicente J. Botet Escriba
9fc6fec1eb Thread: Add return type to lambda to be portable on msvc10.
[SVN r84953]
2013-07-04 21:40:15 +00:00
Vicente J. Botet Escriba
29babb974e Thread: remove warning in barrier.hpp.
[SVN r84952]
2013-07-04 21:38:33 +00:00
Vicente J. Botet Escriba
66578bf57b Thread: rollback change in #8070 as this includes a regression on windows XP.
[SVN r84946]
2013-07-03 21:16:49 +00:00
Vicente J. Botet Escriba
1da5f9563c Thread: make use of barrier on test sync_queue/multi_thread_pass.cpp and remove some warnings in sync_queue|sync_bounded_queue/single_thread_pass.cpp tests.
[SVN r84911]
2013-06-28 06:00:44 +00:00
Vicente J. Botet Escriba
52039f75a3 Thread: fix some issues with sync_bounded_queue and added tests.
[SVN r84888]
2013-06-23 20:47:03 +00:00
Vicente J. Botet Escriba
bb6fcc3b5c Thread: unused parameter warning removal.
[SVN r84887]
2013-06-23 20:45:26 +00:00
Vicente J. Botet Escriba
6225c8309a Thread: merge fix for msvc 8/9 regression.
[SVN r84870]
2013-06-21 23:10:48 +00:00
Vicente J. Botet Escriba
1fc1d8aedb Thread: Added future unwrapp constructor.
[SVN r84810]
2013-06-16 21:29:52 +00:00
Vicente J. Botet Escriba
042a86c984 Thread: added completion function on barrier class.
[SVN r84809]
2013-06-16 21:27:59 +00:00
Vicente J. Botet Escriba
364f3ea030 Thread: try to fix regression on MSVC 8/9.
[SVN r84807]
2013-06-16 19:34:25 +00:00
Vicente J. Botet Escriba
fe8991b7fa Thread: fix #8458 and update doc.
[SVN r84792]
2013-06-15 10:35:45 +00:00
Vicente J. Botet Escriba
c87d27a06d Thread: update history, compliance and fix some parts in external locking doc.
[SVN r84771]
2013-06-14 05:50:29 +00:00
Vicente J. Botet Escriba
68d7c69a4b Thread: update future ref doc.
[SVN r84770]
2013-06-14 05:46:11 +00:00
Vicente J. Botet Escriba
f4fb2c1ab0 Thread: merge fixes for #8422, #8458, #8674.
[SVN r84750]
2013-06-12 20:54:44 +00:00
Vicente J. Botet Escriba
6873d85650 Thread: Added future::unwrap()/get_or()/fallback_to().
[SVN r84719]
2013-06-09 21:41:00 +00:00
Vicente J. Botet Escriba
b59e57e4cc Thread: used cons& in deleted constructors and assignment simulation.
[SVN r84718]
2013-06-09 21:29:17 +00:00
Vicente J. Botet Escriba
582649ed44 Thread: fix #8550, #8671, #8672.
[SVN r84717]
2013-06-09 17:18:15 +00:00
Vicente J. Botet Escriba
d0f9d6216a Thread: remove const on strict locks mutex() function.
[SVN r84712]
2013-06-09 09:15:26 +00:00
Vicente J. Botet Escriba
28564064ff Thread: update history and document force use of Boost.Chrono on windows platforms.
[SVN r84711]
2013-06-09 09:07:05 +00:00
Vicente J. Botet Escriba
ff9636b8e0 Thread: take in account wait_abandoned.
[SVN r84710]
2013-06-09 08:28:28 +00:00
Vicente J. Botet Escriba
d83d23bee0 Thread: force use of chrono on windows.
[SVN r84709]
2013-06-09 08:27:00 +00:00
Vicente J. Botet Escriba
63f35e9f52 Thread: Added test_8674.cpp test.
[SVN r84691]
2013-06-08 16:04:46 +00:00
Vicente J. Botet Escriba
5ad38d52e8 Thread: update doc external_locking.qbk to remove const in mutex() function.
[SVN r84690]
2013-06-08 15:47:00 +00:00
Vicente J. Botet Escriba
9d6cd40d8d Thread: cleanup test_8596.cpp.
[SVN r84689]
2013-06-08 14:54:46 +00:00
Vicente J. Botet Escriba
4362cd655e Thread: update future doc with void set_exception_at_thread_exit(E p).
[SVN r84688]
2013-06-08 14:50:26 +00:00
Vicente J. Botet Escriba
0c44630029 Thread: fix bug on future::then when the continuation is void() ir T&().
[SVN r84685]
2013-06-08 10:53:46 +00:00
Vicente J. Botet Escriba
a01af79331 Thread: apply patch #8550.
[SVN r84684]
2013-06-08 08:21:34 +00:00
Vicente J. Botet Escriba
2df6ce78a4 Thread: fix promise set_at_..._thread_exit; Added preconditions.
[SVN r84678]
2013-06-07 19:03:49 +00:00
Vicente J. Botet Escriba
74891c9836 Thread: Merge history and fix #8645.
[SVN r84629]
2013-06-04 06:08:49 +00:00
Vicente J. Botet Escriba
3951871d70 Thread: update history and fix typo on strict_lock.
[SVN r84628]
2013-06-04 06:02:20 +00:00
Vicente J. Botet Escriba
9dd08547f7 Thread: merge 84331 to fix #8576.
[SVN r84627]
2013-06-04 06:01:54 +00:00
Vicente J. Botet Escriba
c6dbb0c9a5 Thread: merge 84540 to fiw #8626; fix show stopper in packaged_task<void()>.
[SVN r84623]
2013-06-03 16:53:59 +00:00
Vicente J. Botet Escriba
5a1a9df623 Thread: fix shared_future::get when the shared state is async; refactor the shared_state classes.
[SVN r84607]
2013-06-02 05:56:13 +00:00
Vicente J. Botet Escriba
a6f67e25e3 Thread: fix packaged_task<void()> issue and add tests.
[SVN r84597]
2013-06-01 14:27:16 +00:00
Vicente J. Botet Escriba
b69ec54695 Thread: continue the future.hpp renaming using shared_state.
[SVN r84590]
2013-06-01 07:05:35 +00:00
Vicente J. Botet Escriba
465aee1b66 Thread: Added test for #8596.
[SVN r84589]
2013-06-01 05:11:34 +00:00
Vicente J. Botet Escriba
14d3c59682 Thread added shared_future::then tests.
[SVN r84548]
2013-05-29 20:48:37 +00:00
Vicente J. Botet Escriba
3f2d8f8865 Thread: Added shared_future::then doc.
[SVN r84544]
2013-05-29 06:22:44 +00:00
Vicente J. Botet Escriba
dc8449bd0e Thread: Added shared_future::then.
[SVN r84541]
2013-05-28 20:25:34 +00:00
Vicente J. Botet Escriba
d3a6277714 Thread: Reintroduce BOOST_VERIFY on pthread_mutex_destroy return type #8626.
[SVN r84540]
2013-05-28 20:06:51 +00:00
Vicente J. Botet Escriba
81d8944b96 Thread: fix some typos on external locking.
[SVN r84539]
2013-05-28 20:01:34 +00:00
Vicente J. Botet Escriba
54faaaf087 Thread: replace asynchronous result by shared state on the future doc and add value_type on futures and promise.
[SVN r84521]
2013-05-26 21:28:17 +00:00
Vicente J. Botet Escriba
5a43d5ffe9 Thread: fix copy_exception ambiguity.
[SVN r84520]
2013-05-26 21:26:25 +00:00
Vicente J. Botet Escriba
c628e51e6c Thread: little refactoring on future.hpp; Added make_ready_future.
[SVN r84493]
2013-05-25 12:44:43 +00:00
Vicente J. Botet Escriba
a66b269198 Thread: update history.
[SVN r84489]
2013-05-25 12:01:22 +00:00
Vicente J. Botet Escriba
9e07202e21 Thread: rename internal future_object class by shared_state.
[SVN r84474]
2013-05-25 06:36:37 +00:00
Vicente J. Botet Escriba
9e2a34ca9d Thread: extend duration check from 200ms to 300ms.
[SVN r84467]
2013-05-24 21:24:13 +00:00
Vicente J. Botet Escriba
4cf80c6685 Thread: update latch to use generation to prevent spurious wake-ups.
[SVN r84421]
2013-05-22 17:18:23 +00:00
Vicente J. Botet Escriba
455c31c0e9 Thread: fix inspection issues.
[SVN r84420]
2013-05-22 17:13:03 +00:00
Vicente J. Botet Escriba
a8d5fd48c1 Thread: fix warning.
[SVN r84419]
2013-05-22 17:11:31 +00:00
Vicente J. Botet Escriba
294a5404c2 Thread: fix inspection issues
[SVN r84418]
2013-05-22 17:09:49 +00:00
Vicente J. Botet Escriba
6d01267030 Thread: manage with #8596.
[SVN r84414]
2013-05-22 05:40:58 +00:00
Vicente J. Botet Escriba
1c48d237a8 Thread: fix sur parolle.
[SVN r84331]
2013-05-17 19:24:19 +00:00
Vicente J. Botet Escriba
11ae5c8c44 Thread: fix inspection report.
[SVN r84330]
2013-05-17 19:22:25 +00:00
Vicente J. Botet Escriba
9d10bd035a Thread: fix inspection report.
[SVN r84329]
2013-05-17 19:20:45 +00:00
Vicente J. Botet Escriba
7b48c02d2f Thread: fix warning
[SVN r84185]
2013-05-07 22:18:15 +00:00
Vicente J. Botet Escriba
d8a9331464 Thread: Rollback unwanted and unchecked change
[SVN r84138]
2013-05-04 16:03:48 +00:00
Vicente J. Botet Escriba
b60968b045 Thread: remove definition of BOOST_THREAD_NOEXCEPT_OR_THROW.
[SVN r84134]
2013-05-04 09:05:11 +00:00
Vicente J. Botet Escriba
da41bdb632 Thread: update externally_locked.
[SVN r84110]
2013-05-02 15:42:12 +00:00
Vicente J. Botet Escriba
5fcfd0e4e8 Thread: update the externally_locked_stream interface.
[SVN r84109]
2013-05-02 15:32:29 +00:00
Vicente J. Botet Escriba
2d2d1112d6 Thread: replace boost:tuple in async_func.hpp as not movable until the patch is applied.
[SVN r84098]
2013-05-01 09:19:18 +00:00
Vicente J. Botet Escriba
7cf6934515 Thread: Added #8508 test.
[SVN r84097]
2013-05-01 09:17:39 +00:00
Vicente J. Botet Escriba
757327ba10 Thread: apply patch for #8530.
[SVN r84096]
2013-05-01 08:18:03 +00:00
Vicente J. Botet Escriba
a82843d3ab Thread: update Future section.
[SVN r84084]
2013-04-29 11:45:03 +00:00
Vicente J. Botet Escriba
5779f6676d Thread: update externally_locked with assignment.
[SVN r84076]
2013-04-28 20:12:28 +00:00
Vicente J. Botet Escriba
b359424858 Thread: refactor latch by adding an internal counter that has an associated condition_variable and add doc.
[SVN r84075]
2013-04-28 20:09:50 +00:00
Vicente J. Botet Escriba
a5f7d92960 Thread: fix some typos in externally_locked doc.
[SVN r84065]
2013-04-28 12:12:38 +00:00
Vicente J. Botet Escriba
83167d8c15 Thread: make barrier not copyable.
[SVN r84064]
2013-04-28 12:10:24 +00:00
Vicente J. Botet Escriba
7d2270f8c8 Thread: try to fix time based functions.
[SVN r84056]
2013-04-27 14:39:45 +00:00
Vicente J. Botet Escriba
f87dbb83b1 Thread: Added latch and completion_latch classes.
[SVN r84055]
2013-04-27 06:51:18 +00:00
Vicente J. Botet Escriba
1a613d03a9 Thread: Added call_once test with boost::ref().
[SVN r84005]
2013-04-21 16:39:04 +00:00
Vicente J. Botet Escriba
d42f4ff169 Thread: re-apply the change to invoke as it works for gcc but not for msvc.
[SVN r84004]
2013-04-21 15:32:16 +00:00
Vicente J. Botet Escriba
ffbcf96d90 Thread: let a little bit more time.
[SVN r84003]
2013-04-21 15:04:05 +00:00
Vicente J. Botet Escriba
f5e246ebb0 Thread: rollback comments on invoke as there is a regression on msvc.
[SVN r83988]
2013-04-20 16:31:10 +00:00
Vicente J. Botet Escriba
467a88c4f8 Thread: make use of _POSIX_TIMEOUTS instead of _POSIX_C_SOURCE on the definition BOOST_PTHREAD_HAS_TIMEDLOCK #8443.
[SVN r83962]
2013-04-18 21:34:32 +00:00
Vicente J. Botet Escriba
f021bad1d5 Thread: update changes.
[SVN r83951]
2013-04-18 06:45:01 +00:00
Vicente J. Botet Escriba
ecd97ec4ea Thread: make invoke/async_tuple/tuple_indices more portable.
[SVN r83950]
2013-04-18 06:44:09 +00:00
Vicente J. Botet Escriba
c71882816c Thread: add missing joinable in scoped_thread #8451 + construction from F, Args.
[SVN r83949]
2013-04-18 06:43:19 +00:00
Vicente J. Botet Escriba
ef5d43fac9 Thread: make unnifor definition of BOOST_PTHREAD_HAS_TIMEDLOCK #8443.
[SVN r83948]
2013-04-18 06:41:42 +00:00
Vicente J. Botet Escriba
fb5404947e Thread: update history.
[SVN r83910]
2013-04-14 23:07:10 +00:00
Vicente J. Botet Escriba
f24086fe89 Thread: #6966.
[SVN r83908]
2013-04-14 22:34:10 +00:00
Vicente J. Botet Escriba
3e64214e68 Thread: Added Move traits include file.
[SVN r83906]
2013-04-14 21:34:09 +00:00
Vicente J. Botet Escriba
ed4f0f7b6d Thread: apply patch for #6843.
[SVN r83904]
2013-04-14 21:29:02 +00:00
Vicente J. Botet Escriba
50c18d6274 Detail: Added undef/redef atomic intel macros #6842/#6843.
[SVN r83903]
2013-04-14 21:23:39 +00:00
Vicente J. Botet Escriba
d5cf734a21 Thread: remove noexcept on operations that can unlock the mutex.
[SVN r83902]
2013-04-14 20:31:40 +00:00
Vicente J. Botet Escriba
43f0c059d3 Thread: Added test from [Boost-users] [boost][thread] Future returning 0xfeeefeee.
[SVN r83895]
2013-04-14 12:40:44 +00:00
Vicente J. Botet Escriba
e775ef5c27 Thread: update ref doc for future::then.
[SVN r83817]
2013-04-08 20:10:47 +00:00
Vicente J. Botet Escriba
06b7a41add Thread: update ref doc for concurrent queues.
[SVN r83815]
2013-04-08 19:14:31 +00:00
Vicente J. Botet Escriba
06d2a11127 Thread: rollback BOOST_THREAD_PROVIDES_ONCE_CXX11 define. Force minwg to use BOOST_THREAD_USE_LIB.
[SVN r83796]
2013-04-07 19:01:22 +00:00
Vicente J. Botet Escriba
6dd195bbc6 Thread: Added tennis example to regression tests.
[SVN r83795]
2013-04-07 18:43:53 +00:00
Vicente J. Botet Escriba
8a259612cd Thread: renamed all the examples as ex_; Added some lambda test.
[SVN r83762]
2013-04-04 00:04:16 +00:00
Vicente J. Botet Escriba
9fb88b8f47 Thread: don't define BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET on future::then tests.
[SVN r83678]
2013-04-01 17:47:17 +00:00
Vicente J. Botet Escriba
528fcbde56 Thread: major rewrite of future::then.
[SVN r83676]
2013-04-01 16:17:05 +00:00
Vicente J. Botet Escriba
a0397315b2 Thread: minor update in future.hpp to rework future::then.
[SVN r83672]
2013-04-01 07:41:32 +00:00
Vicente J. Botet Escriba
44ec248340 Thread: Added shared_future<>::wait... tests.
[SVN r83667]
2013-03-31 15:16:25 +00:00
Vicente J. Botet Escriba
7eba48576c Thread: added future<>::wait... tests.
[SVN r83666]
2013-03-31 14:47:11 +00:00
Vicente J. Botet Escriba
451027deec Thread: doc updated with sync queues draft and sections reorganization.
[SVN r83654]
2013-03-30 18:39:35 +00:00
Vicente J. Botet Escriba
16b42b6c63 Thread: added non-interleaved externally_locked stream example to regression tests.
[SVN r83653]
2013-03-30 18:38:03 +00:00
Vicente J. Botet Escriba
a543b918f0 Thread: check for time_points in the past on try_join_until to take care of #8323.
[SVN r83652]
2013-03-30 18:28:29 +00:00
Vicente J. Botet Escriba
619ddf54b9 Thread: remove what() function from future_error to take care of #8337.
[SVN r83649]
2013-03-30 14:36:41 +00:00
Vicente J. Botet Escriba
116c947af9 Thread: replace wait_and_ope by ope in sync_queues and pop by pull.
[SVN r83648]
2013-03-30 14:33:42 +00:00
Vicente J. Botet Escriba
a0931c117d Thread: return 0.
[SVN r83645]
2013-03-30 09:37:43 +00:00
Vicente J. Botet Escriba
79e1e88f2e Thread: more refactoring on pthread/shared_mutex.hpp.
[SVN r83553]
2013-03-24 23:45:33 +00:00
Vicente J. Botet Escriba
af3b5f3227 Thread: limit dependency on boost/thread/thread.hpp.
[SVN r83552]
2013-03-24 22:05:50 +00:00
Vicente J. Botet Escriba
7bebf0a062 Thread: fix typo __Lockable.
[SVN r83551]
2013-03-24 22:02:44 +00:00
Vicente J. Botet Escriba
6dad044ab7 Thread: avoid the use of boost/thread/thread.hpp to limit dependencies.
[SVN r83548]
2013-03-24 18:30:55 +00:00
Vicente J. Botet Escriba
19bd0d5eba Thread: Added first version of sync_queue.
[SVN r83547]
2013-03-24 18:29:03 +00:00
Vicente J. Botet Escriba
f922fa56e4 Thread: Added assertions on pthread/shared_mutex.hpp; fixed two shared_mutex tests that were wrong.
[SVN r83546]
2013-03-24 17:18:21 +00:00
Vicente J. Botet Escriba
290faf192d Thread: Added first version of sync_bounded_queue.
[SVN r83538]
2013-03-24 12:24:22 +00:00
Vicente J. Botet Escriba
054bbad65a Thread: update doc addin the missing traits is_recursive_lockable and is_recursive_basic_lockable; Added lock/try_lock requires clause; Added call_once restrictions.
[SVN r83534]
2013-03-23 18:05:10 +00:00
Vicente J. Botet Escriba
df7fbe085a Thread: Added constexpr to future default constructor; protect code incompatible with MSVC8.
[SVN r83521]
2013-03-22 21:50:20 +00:00
Vicente J. Botet Escriba
b03cebff7b Thread: protect some tests with BOOST_THREAD_PROVIDES_VARIADIC_THREAD.
[SVN r83503]
2013-03-19 22:35:50 +00:00
Vicente J. Botet Escriba
c9c46e87b5 Thread: Adapt win32/once.hpp to last changes to invoke..
[SVN r83471]
2013-03-17 08:07:40 +00:00
Vicente J. Botet Escriba
d4e6332eca Thread: add invoke when no variadic templates are available; adapt call_once.
[SVN r83466]
2013-03-16 15:36:21 +00:00
Vicente J. Botet Escriba
80594adcbb Thread: fixed some typos on win32/once.hpp and made use bind when there are some arguments and specialize the algorithm when there are no parameters to avoid errors with bind.
[SVN r83465]
2013-03-16 15:35:10 +00:00
Vicente J. Botet Escriba
4ea14fb9da Thread: rollback one of the changes in [83425].
[SVN r83456]
2013-03-16 08:32:22 +00:00
Vicente J. Botet Escriba
5a22af7639 Thread: force BOOST_THREAD_USES_DATETIME on windows #8198.
[SVN r83426]
2013-03-14 17:23:05 +00:00
Vicente J. Botet Escriba
7b157ab5f4 Thread: Apply patch for #8212.
[SVN r83425]
2013-03-14 17:19:59 +00:00
Vicente J. Botet Escriba
a73425eb00 Thread: use invoke/bind whenever there is atleast one parameter on call_once.
[SVN r83422]
2013-03-13 23:01:49 +00:00
Vicente J. Botet Escriba
b254afc229 Thread: use Boost/Move in invoke.
[SVN r83421]
2013-03-13 22:58:12 +00:00
Vicente J. Botet Escriba
a1edda3437 Thread: Added changes for 1.54.
[SVN r83420]
2013-03-13 22:49:22 +00:00
Vicente J. Botet Escriba
c784369f76 Thread: try to fix call_once for MSVC 8.0,9.0
[SVN r83400]
2013-03-10 17:36:40 +00:00
Vicente J. Botet Escriba
0b7462c4f2 Thread: notify win32/shared_mutex when setting new_state.exclusive_waiting_blocked=false;
[SVN r83397]
2013-03-10 15:17:50 +00:00
Vicente J. Botet Escriba
23ff6e0120 Thread: Added noexcep to some synchronized_value constructors + doc.
[SVN r83396]
2013-03-10 14:54:59 +00:00
Vicente J. Botet Escriba
06491889ea Thread: Try workaround for #8212.
[SVN r83370]
2013-03-09 16:00:22 +00:00
Vicente J. Botet Escriba
abf441ee63 Thread: try to fix double definition of GetTickCount64.
[SVN r83318]
2013-03-05 18:57:34 +00:00
Vicente J. Botet Escriba
9615a51123 Thread: #8237, 8239
[SVN r83312]
2013-03-05 18:05:48 +00:00
Vicente J. Botet Escriba
a0bfa7faeb Thread: activate synchronized_value tests
[SVN r83295]
2013-03-04 18:15:27 +00:00
Vicente J. Botet Escriba
44b741e445 Thread: make use of _WIN32_WINNT instead of WINNT.
[SVN r83294]
2013-03-04 17:52:49 +00:00
Vicente J. Botet Escriba
41d336e7fb Thread: added test for #7755.
[SVN r83286]
2013-03-03 19:13:58 +00:00
Vicente J. Botet Escriba
fc177914e1 Thread: take care of #8136
[SVN r83282]
2013-03-03 14:07:28 +00:00
Vicente J. Botet Escriba
d0056e0cc8 Thread: fix typo on synchronized_value.hp and initialize id_ on testable_mutex.
[SVN r83281]
2013-03-03 13:56:40 +00:00
Vicente J. Botet Escriba
6075cf2df6 Thread: Added test for synchronized_value + synchronize free function
[SVN r83266]
2013-03-03 11:02:31 +00:00
Vicente J. Botet Escriba
1eacb8c71d Thread: Added comments to synchronized_value + synchronize free function
[SVN r83265]
2013-03-03 11:01:07 +00:00
Vicente J. Botet Escriba
7476f71af6 Thread: go towards testable_mutex
[SVN r83264]
2013-03-03 10:55:13 +00:00
Vicente J. Botet Escriba
d86b5d2c0d Thread: Added some synchronized_value tests
[SVN r83262]
2013-03-03 10:22:35 +00:00
Vicente J. Botet Escriba
09f86d603e Thread: fix typo on return value
[SVN r83261]
2013-03-03 10:14:16 +00:00
Vicente J. Botet Escriba
ca3d7dab0b Thread: remove warning
[SVN r83260]
2013-03-03 09:53:25 +00:00
Vicente J. Botet Escriba
7e35a60650 Thread: remove warning
[SVN r83259]
2013-03-03 09:50:26 +00:00
Vicente J. Botet Escriba
2b5bd7275e Thread: Make use of GetTickCount64 when available
[SVN r83258]
2013-03-03 09:45:48 +00:00
Vicente J. Botet Escriba
ca37d07184 Thread: Added value semantics to synchronized value
[SVN r83086]
2013-02-22 17:42:44 +00:00
Vicente J. Botet Escriba
6f2efbcb32 Thread: Added doc on call_once + synchronized_value + lockable_adapter.
[SVN r83085]
2013-02-22 17:25:20 +00:00
Vicente J. Botet Escriba
1ce6a90f95 Thread: see if the use of lightweight_test removes the error: double free or corruption.
[SVN r83040]
2013-02-19 22:45:10 +00:00
Vicente J. Botet Escriba
0a101e15d1 Thread: commit proposed patch for #7720.
[SVN r82973]
2013-02-18 12:11:09 +00:00
Vicente J. Botet Escriba
d2f7766f8a Thread: inhibit msvc warning
[SVN r82955]
2013-02-17 16:16:24 +00:00
Vicente J. Botet Escriba
ba7a0935f2 Thread: added missing include for #7720.
[SVN r82954]
2013-02-17 16:13:54 +00:00
Vicente J. Botet Escriba
7277a94411 Thread: refactor may_alias on once_atomic.hpp.
[SVN r82951]
2013-02-17 15:04:06 +00:00
Vicente J. Botet Escriba
197bbc1fd3 Thread: remove warnings.
[SVN r82950]
2013-02-17 14:59:57 +00:00
Vicente J. Botet Escriba
b9e2d7b13d Thread: prepare for HH shared_mutex.
[SVN r82946]
2013-02-17 10:11:46 +00:00
Hartmut Kaiser
579501d98e Thread: Fixing annoying Windows compilation warning
[SVN r82943]
2013-02-17 04:44:05 +00:00
Vicente J. Botet Escriba
dc352450ca Thread: added load test for shared_mutex.
[SVN r82925]
2013-02-16 15:11:19 +00:00
Vicente J. Botet Escriba
21b2bbc8ca Thread: make use of atomic on the header of once_atomic to avoid not needed cast that report some warnings.
[SVN r82905]
2013-02-15 17:05:49 +00:00
Vicente J. Botet Escriba
bd9105a104 Thread: try to fix some vacpp errors on regression tests.
[SVN r82861]
2013-02-13 22:01:33 +00:00
Vicente J. Botet Escriba
935d851cdf Thread: move local static variable to file scope in future_category.
[SVN r82843]
2013-02-12 20:14:11 +00:00
Vicente J. Botet Escriba
68142e8ff8 Thread: cleanup perf_shared_mutex.cpp.
[SVN r82842]
2013-02-12 20:12:20 +00:00
Anthony Williams
1dad495280 Modify mark_waiting_and_try_lock to return modified count if mutex already locked
[SVN r82828]
2013-02-12 08:21:40 +00:00
Vicente J. Botet Escriba
fb2310b48a Thread: Add vacpp-12.1 to the compilers using chrono.
[SVN r82826]
2013-02-11 22:52:52 +00:00
Vicente J. Botet Escriba
247e9a4f09 Thread: Fixed null_mutex initialization + added tests some tests.
[SVN r82823]
2013-02-11 18:43:33 +00:00
Vicente J. Botet Escriba
c1ec1ada0e Thread: remove no more needed and failing function remove_unused_warning.
[SVN r82809]
2013-02-10 21:37:50 +00:00
Vicente J. Botet Escriba
d030dbd61c Thread: fix some issues with futures of MoveOnly types + complete the variadic async function.
[SVN r82808]
2013-02-10 18:14:49 +00:00
Vicente J. Botet Escriba
bebd56ee21 Thread: fix synchronized_value move constructor.
[SVN r82795]
2013-02-09 14:05:55 +00:00
Vicente J. Botet Escriba
75586eec0e Thread: manage #7980
[SVN r82777]
2013-02-07 18:43:50 +00:00
Vicente J. Botet Escriba
659343d287 Thread: link with Boost.Atomic when compiling for vacpp
[SVN r82776]
2013-02-07 17:06:10 +00:00
Vicente J. Botet Escriba
8e63c72867 Thread: Added timed_lock functions to HH shared_mutex implementation so that we can replace the current shared_mutex by the HH one.
[SVN r82762]
2013-02-06 17:57:16 +00:00
Vicente J. Botet Escriba
65416bb8b6 Thread: make the pthread binary to don't depend on shared_mutex.hpp + #7982
[SVN r82757]
2013-02-06 06:40:30 +00:00
Vicente J. Botet Escriba
71a647b66b Thread: make shared_mutext HH implementation header-only.
[SVN r82746]
2013-02-04 20:22:13 +00:00
Vicente J. Botet Escriba
fc57e9dde0 Thread: Update win32/once.hpp to take care of variadin rvalu call_once parameters.
[SVN r82649]
2013-01-27 21:30:51 +00:00
Vicente J. Botet Escriba
4acfe0975c Thread: Update win32/once.hpp to take care of variadin rvalu call_once parameters.
[SVN r82648]
2013-01-27 21:28:59 +00:00
Vicente J. Botet Escriba
158e8ead50 Thread: update perf shared_mutex file
[SVN r82647]
2013-01-27 21:24:38 +00:00
Vicente J. Botet Escriba
0fc69c4d9e Thread: update H.Hinnant implementation to make it work on Windows.
[SVN r82646]
2013-01-27 21:22:58 +00:00
Vicente J. Botet Escriba
e314bf03ce Thread: fix issue when BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS is defined on win32/pthread.cpp
[SVN r82645]
2013-01-27 20:16:54 +00:00
Vicente J. Botet Escriba
6f2decdacf Thread: added shred mutex impl based on H. Hinnant one
[SVN r82638]
2013-01-27 17:55:00 +00:00
Vicente J. Botet Escriba
4bd3e09a0d Thread: Added performance test for shared_mutex.
[SVN r82637]
2013-01-27 17:29:24 +00:00
Vicente J. Botet Escriba
a16f508b8a Thread: Added two more test cases for call_once for thread I/F.
[SVN r82624]
2013-01-26 16:20:05 +00:00
Vicente J. Botet Escriba
1642db3441 Thread: enable BOOST_THREAD_PROVIDES_ONCE_CXX11 on cal_once_pass test
[SVN r82613]
2013-01-25 20:53:49 +00:00
Vicente J. Botet Escriba
b389079417 Thread: improve call_once using invoke/bind and rvalue references
[SVN r82566]
2013-01-20 17:06:33 +00:00
Vicente J. Botet Escriba
8f7be637b2 Thread: comment BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN define to make evident the bug.
[SVN r82551]
2013-01-19 18:08:20 +00:00
Vicente J. Botet Escriba
94c15aa0cc Thread: changes to fix PGI compiler adding lib atomic.
[SVN r82548]
2013-01-19 08:33:06 +00:00
Vicente J. Botet Escriba
951c8952ff Thread: Added variadic call_once for windows
[SVN r82543]
2013-01-18 22:36:28 +00:00
Vicente J. Botet Escriba
59f91a2405 Thread: extend the timeout in test async_pass.
[SVN r82542]
2013-01-18 22:04:27 +00:00
Vicente J. Botet Escriba
f4a3d52654 Thread: fix call_once when atomic is not used.
[SVN r82530]
2013-01-18 07:18:55 +00:00
Vicente J. Botet Escriba
517e177d7a Thread: minor changes to fix PGI compiler adding lib atomic
[SVN r82529]
2013-01-17 21:09:55 +00:00
Vicente J. Botet Escriba
e72184e9ee Thread: Added atomic once implementation + variadi call_once for pthread
[SVN r82513]
2013-01-16 21:49:59 +00:00
Vicente J. Botet Escriba
73348d69d2 Thread: added specific macros to state if some lock factories are not provided
[SVN r82471]
2013-01-12 22:21:58 +00:00
Vicente J. Botet Escriba
15eff9e412 Thread: adjust some durations on tests
[SVN r82459]
2013-01-12 09:48:54 +00:00
Vicente J. Botet Escriba
dd70cd5b40 Thread: change text associated to exceptions #7882.
[SVN r82457]
2013-01-12 09:05:55 +00:00
Vicente J. Botet Escriba
b290f995d0 Thread: try to remove warning for #7874
[SVN r82456]
2013-01-12 09:03:19 +00:00
Vicente J. Botet Escriba
c1dd0e1e43 Thread: comment not thread-safe check for the time been. atomic<> should be used insted.
[SVN r82455]
2013-01-12 08:52:26 +00:00
Vicente J. Botet Escriba
44a02c1f5f Thread: don't set BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED by default.
[SVN r82436]
2013-01-10 21:35:13 +00:00
Vicente J. Botet Escriba
a0071b301b Thread: Added BOOST_THREAD_NO_CXX11_HDR_TUPLE to wrokarround msvc 10.0 behavior providing <tuple> without move semantics
[SVN r82410]
2013-01-08 22:00:02 +00:00
Vicente J. Botet Escriba
c77281f724 Thread: make the mutex type of externally_locked_stream a template parameter. Polymorfic recursive mutex will be needed if the stream mutex map needs to be external.
[SVN r82397]
2013-01-08 01:28:28 +00:00
Vicente J. Botet Escriba
8a0578c93c Thread: improve external lock for externally_locked_stream.
[SVN r82392]
2013-01-07 23:13:43 +00:00
Vicente J. Botet Escriba
c7dcb1daae Thread: fix typo
[SVN r82375]
2013-01-06 10:06:40 +00:00
Vicente J. Botet Escriba
af330fb61b Thread: try to not run some tests when threadapi is win32.
[SVN r82370]
2013-01-05 22:59:07 +00:00
Vicente J. Botet Escriba
ab64afa2a7 Thread: extend the vacpp versions where boost-cheono is accepted
[SVN r82369]
2013-01-05 22:57:03 +00:00
Vicente J. Botet Escriba
85792f9946 Thread: try to see if this solves some vacpp issues
[SVN r82368]
2013-01-05 22:55:50 +00:00
Vicente J. Botet Escriba
e0d4e63e48 Thread: constraint make_unique_locks when BOOST_NO_CXX11_RVALUE_REFERENCES is not defined
[SVN r82367]
2013-01-05 22:54:55 +00:00
Vicente J. Botet Escriba
b2bd9f4ca9 Thread: fix typo in make_unique_locks without ariadic templates
[SVN r82342]
2013-01-03 22:10:34 +00:00
Vicente J. Botet Escriba
189356680b Thread: make use of BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX.
[SVN r82329]
2013-01-03 11:19:14 +00:00
Vicente J. Botet Escriba
0e0cd2c950 Thread: complete externally_locked_stream.
[SVN r82318]
2013-01-02 14:14:03 +00:00
Vicente J. Botet Escriba
a849a41367 Thread: fix typo on condition BOOST_NO_CXX11_HDR_TUPLE.
[SVN r82317]
2013-01-02 11:17:13 +00:00
Vicente J. Botet Escriba
4b1c13e5cb Thread: replace BOOST_NO_CXX11_HDR_INITIALIZER_LIST by specific BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST that takes in account that gcc up to 4.6 doens't supports it as expected
[SVN r82311]
2013-01-02 00:04:33 +00:00
Vicente J. Botet Escriba
f3777b9306 Thread: extend the workaround on intel compilers up to version 13.0
[SVN r82308]
2013-01-01 10:01:56 +00:00
Vicente J. Botet Escriba
3e5e12e1ac Thread: update configuration variables taking in accont the version rollback
[SVN r82307]
2013-01-01 09:45:38 +00:00
Vicente J. Botet Escriba
a50176c259 Thread: rollback default version 3 change.
[SVN r82302]
2012-12-31 15:10:17 +00:00
Vicente J. Botet Escriba
94e524a1e6 Thread: Fix condition_variable/any::wait_for pred with boost::move
[SVN r82301]
2012-12-31 14:49:41 +00:00
Vicente J. Botet Escriba
cb3259b23f Thread: fix issue with wait_for predicate
[SVN r82299]
2012-12-31 12:42:32 +00:00
Vicente J. Botet Escriba
ec811d3c4a Thread: change resource_deadlock_would_occur from precondition to exception.
[SVN r82298]
2012-12-31 10:03:55 +00:00
Vicente J. Botet Escriba
bf67321336 Thread: wait_for description
[SVN r82297]
2012-12-31 10:02:13 +00:00
Vicente J. Botet Escriba
4b71ef9354 Thread: Added noexcept to scoped_thread
[SVN r82296]
2012-12-31 09:57:10 +00:00
Vicente J. Botet Escriba
23bf16a638 Thread: update doc
[SVN r82283]
2012-12-30 18:24:01 +00:00
Vicente J. Botet Escriba
c3ada352f4 Thread: updated history
[SVN r82162]
2012-12-21 22:52:11 +00:00
Vicente J. Botet Escriba
610bdc4aca Thread: update doc ref #7812
[SVN r82107]
2012-12-19 22:58:36 +00:00
Vicente J. Botet Escriba
6675f4645f Thread: #7422: don't use internal_mutex when interruptions not enabled
[SVN r82094]
2012-12-19 10:50:23 +00:00
Vicente J. Botet Escriba
2895bfe269 Thread: #7808
[SVN r82093]
2012-12-19 06:38:56 +00:00
Vicente J. Botet Escriba
27e2d632cd Thread: #7808
[SVN r82082]
2012-12-18 17:18:17 +00:00
Vicente J. Botet Escriba
abdaa7b5b3 Thread: update doc with internal and external locking
[SVN r82036]
2012-12-16 22:40:10 +00:00
Vicente J. Botet Escriba
e0ed1d6d61 Thread: make set_wait_callback thread-safe.
[SVN r81975]
2012-12-15 17:44:38 +00:00
Vicente J. Botet Escriba
f8b1287153 Thread: workaroun for clang-2.8
[SVN r81968]
2012-12-15 13:13:37 +00:00
Vicente J. Botet Escriba
5ed50d68f2 Thread: replace BOOST_SYSTEM_NOEXCEPT by BOOST_NOEXCEPT
[SVN r81963]
2012-12-14 23:58:46 +00:00
Vicente J. Botet Escriba
2f0a6c01c2 Thread: comment missing file
[SVN r81864]
2012-12-11 18:58:43 +00:00
Vicente J. Botet Escriba
c8edd6c795 Thread: minor refactorings
[SVN r81842]
2012-12-10 22:02:16 +00:00
Vicente J. Botet Escriba
2b8930a5bf System/FileSystem/Asio/Thread: ref #7278 Added noexcept to Boost.System to conform with C++11
[SVN r81808]
2012-12-09 14:47:39 +00:00
Vicente J. Botet Escriba
7c89563108 Thread: Fix comments -use instead BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
[SVN r81804]
2012-12-09 10:52:34 +00:00
Vicente J. Botet Escriba
fcb94bcecf Thread: Add more tests for _at_thread_exit functions when the source is moved.
[SVN r81792]
2012-12-08 14:05:52 +00:00
Vicente J. Botet Escriba
593e9e0f2f Thread: fix shared_ptr implicit conversion to bool introduced in [81780]
[SVN r81788]
2012-12-08 11:01:15 +00:00
Vicente J. Botet Escriba
4209dfaa7f Thread: Added make_strict_lock.
[SVN r81784]
2012-12-08 08:15:49 +00:00
Vicente J. Botet Escriba
0fac7be5b9 Thread: rename _synchronizer as _lock_ptr, and move them outside of synchronized_value so that they can be used in other contexts + update and show usage of unique_lock_ptr.
[SVN r81779]
2012-12-07 23:45:09 +00:00
Vicente J. Botet Escriba
0936913bf6 Thread: Added tests for strict_lock, nested_strict_lock
[SVN r81753]
2012-12-07 07:48:36 +00:00
Vicente J. Botet Escriba
03ebc320f1 Thread: set default version to 3
[SVN r81704]
2012-12-04 16:32:33 +00:00
Vicente J. Botet Escriba
ea11670593 Thread: fix strinct_synchronizer move error and update the example to be run on all compilers.
[SVN r81680]
2012-12-02 21:30:39 +00:00
Vicente J. Botet Escriba
607080857b Thread: uncomment unwanted comments:(.
[SVN r81674]
2012-12-02 20:17:08 +00:00
Vicente J. Botet Escriba
6728fdb3b1 Thread: make synchronized_value use Boost.Move and add some value based operations
[SVN r81673]
2012-12-02 18:30:00 +00:00
Vicente J. Botet Escriba
580c1b7be4 Thread: fix some issues when BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS is defined and add tests
[SVN r81672]
2012-12-02 14:14:09 +00:00
Vicente J. Botet Escriba
03a43d09a4 Thread: update unique_synchronizer
[SVN r81659]
2012-12-01 22:47:10 +00:00
Vicente J. Botet Escriba
7f043d7b07 Thread: uncomment failing indirection in synchronized_value
[SVN r81650]
2012-12-01 12:28:55 +00:00
Vicente J. Botet Escriba
77a8c6667f Thread: update sleep_for algo depending on whether BOOST_THREAD_SLEEP_FOR_IS_STEADY is defined or not
[SVN r81649]
2012-12-01 11:12:01 +00:00
Vicente J. Botet Escriba
418a3f6978 Thread: Added no interruption header-only tests for shared_mutex/shared_lock
[SVN r81648]
2012-12-01 11:10:43 +00:00
Vicente J. Botet Escriba
6b300d2e4c Thread: force BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
[SVN r81647]
2012-12-01 11:08:03 +00:00
Vicente J. Botet Escriba
50ae9d93a6 Thread: Use BOOST_THREAD_LOG
[SVN r81646]
2012-12-01 11:07:10 +00:00
Vicente J. Botet Escriba
168ee37d30 Thread: remove warnings
[SVN r81645]
2012-12-01 11:04:25 +00:00
Vicente J. Botet Escriba
81528d64d5 Thread: Added const_strict_synchronizer.
[SVN r81644]
2012-12-01 11:02:16 +00:00
Marshall Clow
e6b8a133a8 Removed missed usage of deprecated macros in Boost.Thread
[SVN r81593]
2012-11-27 17:26:10 +00:00
Vicente J. Botet Escriba
047ca43b72 Thread: don't use thread_data if no interruptions
[SVN r81583]
2012-11-26 22:58:00 +00:00
Vicente J. Botet Escriba
3c6509184a Thread: improve is_convertible workaround to take care bug for of gcc-4.4 and intel 10.1
[SVN r81534]
2012-11-25 18:38:42 +00:00
Vicente J. Botet Escriba
ec1ce4cf98 Thread: improve is_convertible workaround to take care bug for of gcc-4.4 and intel 10.1
[SVN r81533]
2012-11-25 18:30:19 +00:00
Vicente J. Botet Escriba
526478338d Thread: update log so that we can choose to don't use the this_thread::get_id.
[SVN r81532]
2012-11-25 18:27:06 +00:00
Vicente J. Botet Escriba
f49e6e8dc3 Thread: fix conversion when sizeof(intmax_t)>sizeof(ts.tv_sec).
[SVN r81531]
2012-11-25 18:25:35 +00:00
Vicente J. Botet Escriba
186d58eef7 Thread: update docs and some licenses
[SVN r81525]
2012-11-25 08:19:40 +00:00
Vicente J. Botet Escriba
d2bbc1b7c1 Thread: fix error introduced by 81514
[SVN r81522]
2012-11-24 21:33:11 +00:00
Ion Gaztañaga
2a503b5c81 Replace undocumented Boost.Move usage with new official Boost.Move utilities.
[SVN r81514]
2012-11-24 20:51:32 +00:00
Vicente J. Botet Escriba
a25b918a67 Thread: Added unique lock factories
[SVN r81508]
2012-11-24 16:24:27 +00:00
Vicente J. Botet Escriba
821376f552 Thread: Added make_lock_guard
[SVN r81506]
2012-11-24 12:36:46 +00:00
Vicente J. Botet Escriba
4387de4be8 Thread: add traces to future_then
[SVN r81505]
2012-11-24 08:08:10 +00:00
Vicente J. Botet Escriba
0663b30528 Thread: added internal thread-safe log utility
[SVN r81504]
2012-11-24 07:20:21 +00:00
Vicente J. Botet Escriba
37b0eb2c48 Thread: update is_convertible workaround to try to avoid a regression on intel.12.0
[SVN r81503]
2012-11-24 07:07:48 +00:00
Vicente J. Botet Escriba
de0272abcf Thread: patch #7716
[SVN r81490]
2012-11-23 06:29:30 +00:00
Vicente J. Botet Escriba
cfc3634108 Thread: format text
[SVN r81489]
2012-11-23 06:26:30 +00:00
Vicente J. Botet Escriba
1c62b1599d Thread: manage with #7575 for c++11 compliant compilers + try to fix issue with is_convertible on gcc-4.4.
[SVN r81410]
2012-11-18 10:09:12 +00:00
Vicente J. Botet Escriba
1d2ec17d52 Thread: Towards removing DateTime dependency on the library binary file.
[SVN r81398]
2012-11-17 13:46:49 +00:00
Vicente J. Botet Escriba
0d9e8a0c3c Thread: Towards removing DateTime dependency on the library binary file.
[SVN r81383]
2012-11-17 09:00:16 +00:00
Vicente J. Botet Escriba
9b28bb59c9 Thread: refactor time related conversions + move datetime deprecation to version 4
[SVN r81381]
2012-11-17 07:50:56 +00:00
Vicente J. Botet Escriba
0fce559711 Thread: towards future<>::then(launch, ...
[SVN r81291]
2012-11-11 01:05:55 +00:00
Vicente J. Botet Escriba
de191d213e Thread: deprecate BOOST_THREAD_USES_DATETIME only since version 4.
[SVN r81290]
2012-11-11 01:04:47 +00:00
Vicente J. Botet Escriba
ae89c307bf Thread: ref #7669
[SVN r81289]
2012-11-11 00:57:07 +00:00
Vicente J. Botet Escriba
0dba7ba99b Thread: update doc with history, configuration table
[SVN r81288]
2012-11-10 20:35:07 +00:00
Vicente J. Botet Escriba
1b67c83359 Thread: set default version to 2
[SVN r81283]
2012-11-10 10:34:42 +00:00
Vicente J. Botet Escriba
d28465b656 Thread: update doc with lockable traits, yuturial, compliance.
[SVN r81282]
2012-11-10 10:32:06 +00:00
Vicente J. Botet Escriba
bb3493bdf0 Thread: Added test for #7666
[SVN r81281]
2012-11-10 10:30:05 +00:00
Vicente J. Botet Escriba
0cd8326f21 Thread: deprecate nested scoped locks and DateTime based timed fuctions
[SVN r81279]
2012-11-10 10:25:33 +00:00
Vicente J. Botet Escriba
5c5c818bc5 Thread: manage with ref #7668
[SVN r81270]
2012-11-09 20:26:42 +00:00
Vicente J. Botet Escriba
124b99b2a4 Thread: Added missing include
[SVN r81264]
2012-11-09 16:56:36 +00:00
Vicente J. Botet Escriba
1cabac151a Thread: fix typo.
[SVN r81263]
2012-11-09 16:46:47 +00:00
Vicente J. Botet Escriba
df48b734a2 Thread: rollback to manage with #7657
[SVN r81254]
2012-11-08 20:26:32 +00:00
Vicente J. Botet Escriba
039d744960 Thread added packaged_task__make_ready_at_thread_exit_pass test
[SVN r81225]
2012-11-06 17:20:17 +00:00
Vicente J. Botet Escriba
004e8a4fcf Thread: Added packaged_task::make_ready_at_thread_exit
[SVN r81205]
2012-11-05 17:41:09 +00:00
Vicente J. Botet Escriba
d8f8acbe38 Thread: cleanup + moving lockable traits specializations to the specific files.
[SVN r81175]
2012-11-04 20:37:25 +00:00
Vicente J. Botet Escriba
8a01f9ee09 Thread: cleanup+uncomment catch all
[SVN r81173]
2012-11-04 17:38:09 +00:00
Vicente J. Botet Escriba
315af061cd Thread: Added promise::set_..._at_thread_exit
[SVN r81172]
2012-11-04 16:47:02 +00:00
Vicente J. Botet Escriba
18491c933d Thread added missing file
[SVN r81155]
2012-11-03 00:58:25 +00:00
Vicente J. Botet Escriba
d01c0232da Thread: Added asynch deferred on a specifc configuration+ prepare the work for async futures joining the producer thread
[SVN r81152]
2012-11-02 21:30:36 +00:00
Vicente J. Botet Escriba
91e32e3f02 Thread: extract invoke and make_tuple_indeces on specific files+change the condition to BOOST_NO_CXX11_DECLTYPE_N3276+ fix a warning when BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined
[SVN r81145]
2012-11-02 07:31:19 +00:00
Vicente J. Botet Escriba
88294f4161 Thread: Add the function pointer overloads with MSVC even if it supports rvalue references.
[SVN r81136]
2012-11-01 21:49:20 +00:00
Vicente J. Botet Escriba
9cdc23159a Thread: rollaback unintended default version change
[SVN r81132]
2012-11-01 09:52:13 +00:00
Vicente J. Botet Escriba
c95f1d95af Thread: update doc with warnigs for deprecated features + history
[SVN r81130]
2012-10-31 21:17:49 +00:00
Vicente J. Botet Escriba
45c87d392f Thread: Refactor futures by adding a basic_future common class + added some tests for shared_future
[SVN r81129]
2012-10-31 21:16:00 +00:00
Vicente J. Botet Escriba
1c0a4999b8 Thread: rework async and packaged task.
[SVN r81117]
2012-10-31 01:37:57 +00:00
Vicente J. Botet Escriba
30bfc7bcea Thread: remove some rvalue-references limitations for future::then and make_shared.
[SVN r81111]
2012-10-30 09:36:22 +00:00
Vicente J. Botet Escriba
48f8c1c1c8 Thread Split lock.hpp + towards allowing to disable interruptions
[SVN r81106]
2012-10-29 19:57:01 +00:00
Vicente J. Botet Escriba
c47ea136b6 Thread Split lock.hpp + towards allowing to disable interruptions
[SVN r81105]
2012-10-29 19:19:40 +00:00
Vicente J. Botet Escriba
a3d30b2a89 Thread: Added polymorphic lockables
[SVN r81104]
2012-10-29 19:13:32 +00:00
Vicente J. Botet Escriba
11e15ff0f2 Thread: Added an example using externally_locked_stream
[SVN r81103]
2012-10-29 19:09:47 +00:00
Vicente J. Botet Escriba
fb4b4fb14a Thread: Added externally_locked_stream
[SVN r81102]
2012-10-29 19:09:28 +00:00
Vicente J. Botet Escriba
0ede82e059 Thread: change strict_lock is_locking by own_lock and update lockable concepts
[SVN r81101]
2012-10-29 19:05:51 +00:00
Vicente J. Botet Escriba
708b660c0b Thread: change strict_lock is_locking by own_lock and update lockable concepts
[SVN r81100]
2012-10-29 19:05:35 +00:00
Vicente J. Botet Escriba
9f27bba490 Thread: Added test for #7571
[SVN r81097]
2012-10-29 12:37:53 +00:00
Vicente J. Botet Escriba
095da2890e Thread: deprecate boost::condition
[SVN r81090]
2012-10-29 01:27:53 +00:00
Vicente J. Botet Escriba
389d76cbc1 Thread: document the split of locks.hpp, StrictLock, strict_lock, null_mutex, configuration
[SVN r81089]
2012-10-29 01:25:12 +00:00
Vicente J. Botet Escriba
493cbc030c Thread: Added testable_mutex
[SVN r81088]
2012-10-29 01:12:57 +00:00
Vicente J. Botet Escriba
2f7b936cd6 Thread: Added externally_locked
[SVN r81087]
2012-10-29 01:09:58 +00:00
Vicente J. Botet Escriba
6f3ee1eebf Thread: Added scoped_thread doc
[SVN r81086]
2012-10-29 01:07:36 +00:00
Vicente J. Botet Escriba
32f7b212bd Thread: Added strict locks
[SVN r81084]
2012-10-29 01:03:31 +00:00
Vicente J. Botet Escriba
4fcdabca90 Thread: Added lockable concept checkers
[SVN r81083]
2012-10-29 00:59:57 +00:00
Vicente J. Botet Escriba
b03de37155 Thread: Added files needed to split locks.hpp in several files to limit depedencies
[SVN r81082]
2012-10-29 00:55:31 +00:00
Vicente J. Botet Escriba
73af713503 Thread: Added null_mutex
[SVN r81081]
2012-10-29 00:50:53 +00:00
Vicente J. Botet Escriba
a903532cef Thread: make use of the extracted thread functiors and added default constructor
[SVN r81080]
2012-10-29 00:39:59 +00:00
Vicente J. Botet Escriba
d6178b3139 Thread: update thread_guard to make it a template parameterized by thread functors
[SVN r81079]
2012-10-29 00:36:06 +00:00
Vicente J. Botet Escriba
ec1241a6d8 Thread: Added thread_joiner
[SVN r81074]
2012-10-28 17:55:32 +00:00
Vicente J. Botet Escriba
ae819901ab Thread: Added scoped_thread
[SVN r81073]
2012-10-28 17:53:42 +00:00
Vicente J. Botet Escriba
3c0294cf3a Thread: added first version of synchronized_value
[SVN r81072]
2012-10-28 17:43:40 +00:00
Vicente J. Botet Escriba
21bc767445 Thread: remove include iostream
[SVN r81034]
2012-10-21 09:26:58 +00:00
Vicente J. Botet Escriba
47b6368ef7 Thread: merge 81024
[SVN r81032]
2012-10-21 06:37:51 +00:00
Vicente J. Botet Escriba
a3098b5dfd Thread: Added BOOST_THREAD_DONT_PROVIDE_THREAD_EQ, BOOST_THREAD_DONT_USE_DATETIME and forbid their use when defined + Added BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION and future<>::then + Go towards don't throwing from the cpp files (refactor start_thread, join + Added #define BOOST_THREAD_VERSION 2 for the tests that runs only with version 2
[SVN r81023]
2012-10-20 14:05:32 +00:00
Vicente J. Botet Escriba
bd69c9382f Thread: ref #7461
[SVN r80986]
2012-10-14 16:32:41 +00:00
Vicente J. Botet Escriba
b47f43df59 Thread: Rollback SIG_ATOMIC_MAX change for once.hpp. ref #7499
[SVN r80966]
2012-10-12 00:01:30 +00:00
Vicente J. Botet Escriba
e9217d02f0 Thread: remove some minor warnings
[SVN r80854]
2012-10-04 21:57:18 +00:00
Vicente J. Botet Escriba
6741c8420a Thread: define BOOST_THREAD_PLATFORM_PTHREAD also in windows and restrict it BOOST_NO_SFINAE_EXPR is not defined
[SVN r80853]
2012-10-04 21:55:03 +00:00
Vicente J. Botet Escriba
fe45847841 Thread: remove warning
[SVN r80848]
2012-10-04 17:09:22 +00:00
Vicente J. Botet Escriba
5d13b87dd3 Thread: constraint these test to run only when BOOST_THREAD_USES_CHRONO is defined
[SVN r80847]
2012-10-04 17:08:23 +00:00
Vicente J. Botet Escriba
e1f5fbdc33 Thread: fix typo introduced while making get_id inline on posix
[SVN r80845]
2012-10-04 16:50:46 +00:00
Vicente J. Botet Escriba
b342cf683b Thread: Protect the static assert to catch bug with gcc-4.4
[SVN r80832]
2012-10-03 20:14:15 +00:00
Vicente J. Botet Escriba
e94946cc8c Thread: Added static assert to catch bug with gcc-4.4
[SVN r80830]
2012-10-03 18:47:53 +00:00
Vicente J. Botet Escriba
8604ca1b85 Thread: Fix bug with gcc4.4, prepare change to v3 by default
[SVN r80824]
2012-10-03 05:45:35 +00:00
Vicente J. Botet Escriba
9847f57ce7 Thread: Update doc
[SVN r80823]
2012-10-03 05:43:38 +00:00
Vicente J. Botet Escriba
74e2c4cbcb Thread: Fixed cout access issue
[SVN r80821]
2012-10-02 21:11:29 +00:00
Vicente J. Botet Escriba
7b54159af3 Thread: Make use of BOOST_TRY family macros on win32 code
[SVN r80799]
2012-09-30 23:46:00 +00:00
Vicente J. Botet Escriba
16ad9c868e Thread: make the code of tests set_rvalue and make_future more portable
[SVN r80789]
2012-09-30 17:33:56 +00:00
Vicente J. Botet Escriba
26f4ad3db2 Thread: try to fix some issues with packaged_task with signature parameters
[SVN r80783]
2012-09-30 14:31:52 +00:00
Vicente J. Botet Escriba
715928e143 Thread: Allow BOOST_THREAD_PROVIDES_VARIADIC_THREAD only if BOOST_NO_CXX11_HDR_TUPLE is defined + remove some -ansi flags tha make EXPERIMENTAL_CXX0X to be not defined
[SVN r80766]
2012-09-29 23:35:29 +00:00
Hartmut Kaiser
40d694e893 Thread: adding inline keyword to avoid linker errors
[SVN r80765]
2012-09-29 21:42:36 +00:00
Vicente J. Botet Escriba
4d84fb97c9 Thread: constrain make_future example to run when rvalues references are supported.
[SVN r80763]
2012-09-29 20:54:24 +00:00
Vicente J. Botet Escriba
ab7bb7a82d Thread: try to fix regression on test_once
[SVN r80759]
2012-09-29 18:22:21 +00:00
Vicente J. Botet Escriba
171be40a1f Thread: rollback preceding change and apply patch spliting the assembles so that each instruction is on one line.
[SVN r80757]
2012-09-29 16:53:11 +00:00
Vicente J. Botet Escriba
18d4a8a0f8 Thread: Added missing file
[SVN r80756]
2012-09-29 16:36:19 +00:00
Vicente J. Botet Escriba
dedaa7e617 Thread: version 4: Added variadic templates for packed_task cons, async, thread cons + added make_future + future::get() can be called just once
[SVN r80755]
2012-09-29 16:31:27 +00:00
Jürgen Hunold
6173ae42a9 Fix: C4251 warnings from msvc
Suppress those from the standard library.
Make handle_manager visible via BOOST_THREAD_DECL.

[SVN r80669]
2012-09-23 14:33:50 +00:00
Vicente J. Botet Escriba
792604127e Thread: Added missing what() virtual function of future_error
[SVN r80594]
2012-09-19 00:16:08 +00:00
Vicente J. Botet Escriba
81d0aaf7bc Thread: Added missing what() virtual function of future_error
[SVN r80593]
2012-09-18 23:10:51 +00:00
Vicente J. Botet Escriba
26c495e5b3 Thread: Complete future reference documentation
[SVN r80570]
2012-09-18 06:08:11 +00:00
Vicente J. Botet Escriba
a1f8717170 Thread: fix some typos
[SVN r80565]
2012-09-17 21:30:48 +00:00
Vicente J. Botet Escriba
460a38b994 Thread: (posix) Make use of BOOST_TRY family macros
[SVN r80544]
2012-09-16 18:50:17 +00:00
Vicente J. Botet Escriba
dbefae706c Thread: Fixed windows part of 7360
[SVN r80533]
2012-09-15 14:28:49 +00:00
Vicente J. Botet Escriba
a33e82af60 Thread: fix type on UpgradeLockable requirements
[SVN r80517]
2012-09-13 19:02:37 +00:00
Vicente J. Botet Escriba
8f283b3c2b Thread: fixe typo using std instead of boost.
[SVN r80498]
2012-09-11 22:14:52 +00:00
Vicente J. Botet Escriba
b1ae3a98e8 Thread: Remove temporarly the check on n_alive until I use a movable class
[SVN r80497]
2012-09-11 21:54:06 +00:00
Vicente J. Botet Escriba
fcaaa68f87 Thread: Apply patch for 7360
[SVN r80496]
2012-09-11 21:52:52 +00:00
Vicente J. Botet Escriba
b7622b7407 Thread: complete update for 7345 on windows.
[SVN r80475]
2012-09-09 19:26:47 +00:00
Vicente J. Botet Escriba
a56358c8f8 Thread: Apply patch for 6931.
[SVN r80474]
2012-09-09 19:25:03 +00:00
Vicente J. Botet Escriba
dafe4bea1a Thread: force SIG_ATOMIC_MAX with __STDC_LIMIT_MACROS
[SVN r80466]
2012-09-09 14:48:18 +00:00
Vicente J. Botet Escriba
408a6cb70e Thread: fix typo s/Rational/Rationale/
[SVN r80464]
2012-09-09 13:09:15 +00:00
Vicente J. Botet Escriba
97c0ddbee4 Thread: updated history
[SVN r80461]
2012-09-09 12:46:49 +00:00
Vicente J. Botet Escriba
330502ea1e Thread: Manage with statefull allocators and call destroy on the task object: #7349 and #7350
[SVN r80460]
2012-09-09 12:41:31 +00:00
Vicente J. Botet Escriba
662118b5c6 Thread: Remove BOOST_THREAD_DONT_USE_SYSTEM and update documentation to manage with 7336
[SVN r80459]
2012-09-09 12:35:37 +00:00
Vicente J. Botet Escriba
8bee2291fd Thread: start adding noexcept to recursive_mutex::try_lock. Uncomment needed after checking on windows
[SVN r80449]
2012-09-08 14:18:43 +00:00
Vicente J. Botet Escriba
39c4db3e66 Thread: cleanup include
[SVN r80448]
2012-09-08 14:18:14 +00:00
Vicente J. Botet Escriba
749b1034f9 Thread: test async with moveonly functors.
[SVN r80447]
2012-09-08 14:16:07 +00:00
Vicente J. Botet Escriba
735102d4a0 Thread: update doc with async and notify_all_at_thread_exit referece doc
[SVN r80446]
2012-09-08 14:12:05 +00:00
Vicente J. Botet Escriba
5e30d7486e Thread: Try to fix move limitation on hpux: 7329
[SVN r80439]
2012-09-08 06:43:07 +00:00
Vicente J. Botet Escriba
71f864bc5c Thread: Added notify_all_at_thread_exit+join can throw conditionally if not joinable + detach is no more noexcept
[SVN r80351]
2012-09-01 17:10:16 +00:00
Vicente J. Botet Escriba
b31c1a11d5 Thread: Avoid double definition of BOOST_THREAD_DONT_USE_CHRONO
[SVN r80342]
2012-08-31 23:27:20 +00:00
Vicente J. Botet Escriba
bf03f733a6 Thread: Avoid ambiguity on thread symbol
[SVN r80323]
2012-08-30 17:30:25 +00:00
Vicente J. Botet Escriba
ca04d699bc Thread:7280: Added noexcep to future_category
[SVN r80238]
2012-08-26 18:18:03 +00:00
Vicente J. Botet Escriba
530aaaae38 Thread: 7045: make boost_thread don't depend on boost_chrono for win and 2797: armonize win behavior with posix one.
[SVN r80236]
2012-08-26 15:17:39 +00:00
Vicente J. Botet Escriba
36970f3240 Thread: take care of #7272 warning removal
[SVN r80235]
2012-08-26 13:05:10 +00:00
Vicente J. Botet Escriba
7c97dc8131 Thread: take care of #7272 warning removal
[SVN r80203]
2012-08-25 13:21:21 +00:00
Vicente J. Botet Escriba
a7336c2c5e Thread: update doc
[SVN r80202]
2012-08-25 13:07:54 +00:00
Vicente J. Botet Escriba
8866935d0b Thread: doc shared mutex lack of priority 7284
[SVN r80201]
2012-08-25 13:06:41 +00:00
Vicente J. Botet Escriba
4f06c2392b Thread: update tss doc to take care of #2361 and #3837
[SVN r80198]
2012-08-25 12:28:42 +00:00
Vicente J. Botet Escriba
677113cfbe Thread: fix win regression
[SVN r80152]
2012-08-23 06:25:07 +00:00
Vicente J. Botet Escriba
a01faf1bb8 Thread: fix win regression
[SVN r80134]
2012-08-22 06:12:46 +00:00
Vicente J. Botet Escriba
050b43757f Thread: remove includes using lib/thread
[SVN r80125]
2012-08-21 21:30:00 +00:00
Vicente J. Botet Escriba
448c4b21b5 Thread: added test_3837
[SVN r80124]
2012-08-21 21:29:04 +00:00
Vicente J. Botet Escriba
84d8dea5ba Thread: Add dependency from boost_thread to boost_date_time.
[SVN r80123]
2012-08-21 21:22:35 +00:00
Vicente J. Botet Escriba
5fa5b680f0 Thread: remove dependency from boo_thread to boost_chrono
[SVN r80122]
2012-08-21 21:20:41 +00:00
Vicente J. Botet Escriba
5b26427079 Thread: It seems that the csignal inclusion is failing in all testers, so comment it
[SVN r80082]
2012-08-19 15:41:26 +00:00
Vicente J. Botet Escriba
d426d2ca88 Thread: try to fix 5752
[SVN r80078]
2012-08-18 14:43:06 +00:00
Vicente J. Botet Escriba
2e5bc32b33 Thread: try to fix 7238
[SVN r80076]
2012-08-18 11:26:51 +00:00
Vicente J. Botet Escriba
b0b975e8ef Thread fixes some doc typos
[SVN r80075]
2012-08-18 10:33:31 +00:00
Vicente J. Botet Escriba
1f4df63577 Thread: manage with #5274
[SVN r80053]
2012-08-15 21:29:14 +00:00
Vicente J. Botet Escriba
cf7c218a65 Thread: manage #7173
[SVN r80052]
2012-08-15 20:25:03 +00:00
Vicente J. Botet Escriba
1a1751b45d Thread fix inspecion report errors
[SVN r80049]
2012-08-15 13:11:47 +00:00
Vicente J. Botet Escriba
0354c2fcc3 Thread: apply fix for 7220
[SVN r80041]
2012-08-15 09:59:32 +00:00
Vicente J. Botet Escriba
1679cd2fff Thread: Added date trace for 6130 test
[SVN r80002]
2012-08-13 12:04:17 +00:00
Vicente J. Botet Escriba
32db9f2e71 Thread: Added date trace for 6130 test
[SVN r80001]
2012-08-13 12:03:39 +00:00
Vicente J. Botet Escriba
6b98bee683 Thread: Added test for 7160 ticket
[SVN r79991]
2012-08-12 19:20:35 +00:00
Vicente J. Botet Escriba
7de77cf13c Thread: fixes for inspection report
[SVN r79985]
2012-08-12 18:33:11 +00:00
Vicente J. Botet Escriba
8334f4e68a Thread: name type for pthread/once epoch so that we can choose better an /atomic/ type for it
[SVN r79984]
2012-08-12 18:31:09 +00:00
Vicente J. Botet Escriba
1ac7e7129d Thread: refix 6174
[SVN r79980]
2012-08-12 16:36:40 +00:00
Vicente J. Botet Escriba
daec1268f9 Thread: Added async function
[SVN r79979]
2012-08-12 16:31:21 +00:00
Hartmut Kaiser
c47bd34760 Threads: fixing a bad preprocessor directive
[SVN r79782]
2012-07-28 14:06:27 +00:00
Andrey Semashev
0d9ebfc820 Fixed compilation when Boost.Chrono is disabled by user.
[SVN r79753]
2012-07-26 08:08:06 +00:00
Vicente J. Botet Escriba
3332d8df66 Thread: fix typo - 7117
[SVN r79407]
2012-07-10 20:50:40 +00:00
Vicente J. Botet Escriba
852c173c96 Thread: fix typo - 7117
[SVN r79406]
2012-07-10 20:47:52 +00:00
Vicente J. Botet Escriba
bcf30f2dfc Thread: cleanup no-exceptions on windows
[SVN r79384]
2012-07-09 16:50:35 +00:00
Vicente J. Botet Escriba
2ea1aec7fd Thread: cleanup no-exceptions on windows
[SVN r79383]
2012-07-09 16:46:01 +00:00
Vicente J. Botet Escriba
dc5a26c5d3 Thread: Jamfile cleanup
[SVN r79366]
2012-07-08 19:10:37 +00:00
Vicente J. Botet Escriba
3c8f164371 Thread: no-exception cleanup
[SVN r79365]
2012-07-08 18:53:34 +00:00
Vicente J. Botet Escriba
93c14be188 Thread: no-exceptions cleanup
[SVN r79361]
2012-07-08 17:38:18 +00:00
Vicente J. Botet Escriba
b305cc29fc Thread: Added some changes to make it work with BOOST_NO_EXCEPTIONS
[SVN r79347]
2012-07-08 09:33:13 +00:00
Vicente J. Botet Escriba
c2001fb9d2 Thread: changed assembler for interlocked_bit_test_and_set compatible hp
[SVN r79337]
2012-07-07 14:43:18 +00:00
Vicente J. Botet Escriba
d3a8321be0 Thread: remove warning wait_until
[SVN r79336]
2012-07-07 14:41:02 +00:00
Vicente J. Botet Escriba
8bfd588b4c Thread: remove warning attribute size
[SVN r79335]
2012-07-07 14:38:53 +00:00
Vicente J. Botet Escriba
5268fd3749 Thread: Added __MINGW64_VERSION_MAJOR when __MINGW64__ is not defined
[SVN r79334]
2012-07-07 14:37:07 +00:00
Vicente J. Botet Escriba
19bbd85d9d Thread: rollback bad workaround BOOST_THREAD_WAIT_BUG - 7089
[SVN r79327]
2012-07-07 10:20:39 +00:00
Vicente J. Botet Escriba
deca987299 Thread: Fix 7074
[SVN r79288]
2012-07-05 16:42:01 +00:00
Anthony Williams
1a4eed3b69 Initialization of current_thread_tls_key is direct from macro again to re-enable static initialization
[SVN r79239]
2012-07-03 08:10:41 +00:00
Vicente J. Botet Escriba
1214f99227 Thread: apply patch in 7052
[SVN r79237]
2012-07-02 21:58:56 +00:00
Vicente J. Botet Escriba
51530e03a5 Thread: Added possible missing vector file in some platforms
[SVN r79185]
2012-06-30 09:59:57 +00:00
Vicente J. Botet Escriba
66263dd7b3 Thread: Added other fixed tickets
[SVN r79030]
2012-06-21 21:23:35 +00:00
Vicente J. Botet Escriba
6b0ce64d5e Thread: Fix max macro issue on Windows
[SVN r78920]
2012-06-13 06:34:22 +00:00
Vicente J. Botet Escriba
3b080058ed Thread: rolled back breaking changes on windows.
[SVN r78919]
2012-06-13 06:00:38 +00:00
Vicente J. Botet Escriba
00996a2a02 Thread: rollback unchecked an errored change
[SVN r78863]
2012-06-09 10:09:51 +00:00
Vicente J. Botet Escriba
c0299f4a1e Thread: Added missing BOOST_THREAD_DECL
[SVN r78823]
2012-06-05 21:19:06 +00:00
Vicente J. Botet Escriba
e09105de98 Thread: fix TIME_UTC, WINVER, constexpr for tags, and don't use local files
[SVN r78802]
2012-06-03 18:11:52 +00:00
246 changed files with 28454 additions and 5171 deletions

40
.gitignore vendored Normal file
View File

@@ -0,0 +1,40 @@
#mac
.DS_Store
#projects
.project
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
bin/*
test/bin/*
*.exe
*.out
*.app
#doc
doc/html

8
README.md Normal file
View File

@@ -0,0 +1,8 @@
thread
======
Portable C++ multi-threading. C++11, C++14.
### License
Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).

View File

@@ -36,6 +36,7 @@ import os ;
import feature ;
import indirect ;
import path ;
import configure ;
project boost/thread
: source-location ../src
@@ -77,19 +78,19 @@ project boost/thread
<toolset>pathscale:<cxxflags>-pedantic
<toolset>clang:<cxxflags>-Wextra
<toolset>clang:<cxxflags>-pedantic
#<toolset>clang:<cxxflags>-ansi
#<toolset>clang:<cxxflags>-fpermissive
<toolset>clang:<cxxflags>-Wno-long-long
<toolset>clang:<cxxflags>-Wunused-function
<toolset>clang:<cxxflags>-Wno-variadic-macros
<toolset>clang:<warnings>on
<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>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>gcc:<cxxflags>-Wno-missing-field-initializers
<toolset>darwin-4.6.2:<cxxflags>-Wno-delete-non-virtual-dtor
@@ -140,6 +141,8 @@ local rule default_threadapi ( )
feature.feature threadapi : pthread win32 : propagated ;
feature.set-default threadapi : [ default_threadapi ] ;
exe has_atomic_flag_lockfree : ../build/has_atomic_flag_lockfree_test.cpp ;
rule tag ( name : type ? : property-set )
{
local result = $(name) ;
@@ -236,10 +239,10 @@ rule usage-requirements ( properties * )
}
}
if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties) || <toolset-vacpp:version>12.1.0.1 in $(properties) || <toolset-vacpp:version>12.1 in $(properties)
{
#if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties) || <toolset-vacpp:version>12.1.0.1 in $(properties) || <toolset-vacpp:version>12.1 in $(properties)
#{
result += <library>/boost/chrono//boost_chrono ;
}
#}
return $(result) ;
}
@@ -263,12 +266,14 @@ rule requirements ( properties * )
result = <build>no ;
}
}
}
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
if <toolset>pgi in $(properties) || <toolset>vacpp in $(properties)
{
result += <library>/boost/atomic//boost_atomic ;
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
if ! [ configure.builds has_atomic_flag_lockfree
: $(properties) : "lockfree boost::atomic_flag" ] {
result += <library>/boost/atomic//boost_atomic ;
}
} else {
result += <define>BOOST_THREAD_USES_CHRONO ;
result += <library>/boost/chrono//boost_chrono ;
}
return $(result) ;

View File

@@ -0,0 +1,13 @@
// Copyright (c) 2013, Petr Machata, Red Hat Inc.
//
// Use modification and distribution are subject to the boost Software
// License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).
#include "../../../boost/atomic.hpp"
#include "../../../boost/static_assert.hpp"
int main(int argc, char *argv[])
{
BOOST_STATIC_ASSERT(BOOST_ATOMIC_FLAG_LOCK_FREE);
return 0;
}

1215
doc/async_executors.qbk Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,12 @@
[/
(C) Copyright 2007-8 Anthony Williams.
(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).
]
[section:barriers Barriers]
[section:barriers Barriers -- EXTENSION]
A barrier is a simple concept. Also known as a ['rendezvous], it is a synchronization point between multiple threads. The barrier is
configured for a particular number of threads (`n`), and as threads reach the barrier they must wait until all `n` threads have
@@ -22,14 +23,18 @@ arrived. Once the `n`-th thread has reached the barrier, all the waiting threads
barrier& operator=(barrier const&) = delete;
barrier(unsigned int count);
template <typename F>
barrier(unsigned int count, F&&);
~barrier();
bool wait();
void count_down_and_wait();
};
Instances of __barrier__ are not copyable or movable.
[heading Constructor]
[section Constructor `barrier(unsigned int)`]
barrier(unsigned int count);
@@ -41,7 +46,24 @@ Instances of __barrier__ are not copyable or movable.
]
[heading Destructor]
[endsect]
[section Constructor `barrier(unsigned int, F&&)`]
barrier(unsigned int count, F&& completion);
[variablelist
[[Requires:] [The result type of the completion function call `completion()` is `void` or `unsigned int`.]]
[[Effects:] [Construct a barrier for `count` threads and a completion function `completion`.]]
[[Throws:] [__thread_resource_error__ if an error occurs.]]
]
[endsect]
[section Destructor `~barrier()`]
~barrier();
@@ -55,24 +77,55 @@ Instances of __barrier__ are not copyable or movable.
]
[heading Member function `wait`]
[endsect]
[section Member Function `wait()`]
bool wait();
[variablelist
[[Effects:] [Block until `count` threads have called `wait` on `*this`. When the `count`-th thread calls `wait`, all waiting threads
are unblocked, and the barrier is reset. ]]
[[Effects:] [Block until `count` threads have called `wait` or `count_down_and_wait` on `*this`. When the `count`-th thread calls `wait`, the barrier is reset and all waiting threads are unblocked.
The reset depends on whether the barrier was constructed with a completion function or not. If there is no completion function or if the completion function result is void, the reset consists in restoring the original count. Otherwise the rest consist in assigning the result of the completion function (which must not be 0).]]
[[Returns:] [`true` for exactly one thread from each batch of waiting threads, `false` otherwise.]]
[[Throws:] [__thread_resource_error__ if an error occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
[[Throws:] [
- __thread_resource_error__ if an error occurs.
- __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.
]]
[[Notes:] [`wait()` is an ['interruption point].]]
]
[endsect]
[section Member Function `count_down_and_wait()`]
void count_down_and_wait();
[variablelist
[[Effects:] [Block until `count` threads have called `wait` or `count_down_and_wait` on `*this`. When the `count`-th thread calls `wait`, the barrier is reset and all waiting threads are unblocked.
The reset depends on whether the barrier was constructed with a completion function or not. If there is no completion function or if the completion function result is void, the reset consists in restoring the original count. Otherwise the rest consist in assigning the result of the completion function (which must not be 0).]]
[[Throws:] [
- __thread_resource_error__ if an error occurs.
- __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.
]]
[[Notes:] [`count_down_and_wait()` is an ['interruption point].]]
]
[endsect]
[endsect]
[endsect]

View File

@@ -1,6 +1,6 @@
[/
(C) Copyright 2007-11 Anthony Williams.
(C) Copyright 2011-12 Vicente J. Botet Escriba.
(C) Copyright 2011-14 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
@@ -8,18 +8,171 @@
[section:changes History]
[/
[heading Version 4.2.0 - boost 1.55]
[heading Version 4.4.0 - boost 1.57]
[*New Features:]
[*Know Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Add externally locked streams
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Add concurrent queue
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Sync: Add a latch class
* [@http://svn.boost.org/trac/boost/ticket/2442 #2442] Application statically linked with Boost.Thread crashes when Google Desktop is installed (Windows XP)
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
* [@http://svn.boost.org/trac/boost/ticket/4833 #4833] MinGW/test_tss_lib: Support of automatic tss cleanup for native threading API not available
* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue
* [@http://svn.boost.org/trac/boost/ticket/8600 #8600] wait_for_any hangs, if called with multiple copies of shared_future referencing same task
* [@http://svn.boost.org/trac/boost/ticket/9118 #9118] Seg fault on thread join when llvm and libc++ are used
* [@http://svn.boost.org/trac/boost/ticket/9309 #9309] test_latch fails often on clang-darwin-tot11
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
* [@http://svn.boost.org/trac/boost/ticket/10537 #10537] Application crash on throw exception
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last snapshot.
[*Sever limitations:]
There are some severe bugs that prevent the use of the library on concrete contexts, in particular:
* on thread specific storage that prevent the library to be used with dynamic libraries,
[*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/6227 #6227] Synchro: Use of variadic templates on Generic Locking Algorithms on compilers providing them
* [@http://svn.boost.org/trac/boost/ticket/10298 #10298] Synchro: Added queue views.
* [@http://svn.boost.org/trac/boost/ticket/10300 #10300] Async: Added generic_executor_ref.
* [@http://svn.boost.org/trac/boost/ticket/10552 #10552] Add make_valid_future
[*Fixed Bugs:]
]
* [@http://svn.boost.org/trac/boost/ticket/6782 #6782] call_once uses incorrect barrier intrinsic on Visual Studio
* [@http://svn.boost.org/trac/boost/ticket/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
* [@http://svn.boost.org/trac/boost/ticket/7665 #7665] this_thread::sleep_for no longer uses steady_clock in thread
* [@http://svn.boost.org/trac/boost/ticket/9307 #9307] future::fallback_to assert with ERRORRRRR boost: mutex lock failed in pthread_mutex_lock: Invalid argument
* [@http://svn.boost.org/trac/boost/ticket/9308 #9308] future::async fails with terminate called throwing an exception when called with a lambda - clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9425 #9425] Boost promise & future does not use supplied allocator for value storage
* [@http://svn.boost.org/trac/boost/ticket/9558 #9558] future continuations unit test hangs in get()/pthread_cond_wait() on Mac 10.7/32-bit/x86/darwin-4.2.1
* [@http://svn.boost.org/trac/boost/ticket/9787 #9787] [windows] Small duration value passed down to basic_timed_mutex::try_lock_until and condition_variable::wait_until can cause infinite or near infinite wait for win32
* [@http://svn.boost.org/trac/boost/ticket/9880 #9880] [windows] boost::condition_variable.timed_wait() exception if system time < 1970
* [@http://svn.boost.org/trac/boost/ticket/10159 #10159] GCC 4.4 error sorry, unimplemented
* [@http://svn.boost.org/trac/boost/ticket/10196 #10196] thread_specific_ptr does not support void*
* [@http://svn.boost.org/trac/boost/ticket/10296 #10296] Boost.Thread 1.56 rc1 does not compile on Mingw
* [@http://svn.boost.org/trac/boost/ticket/10297 #10297] Boost.Thread 1.56 rc1 hangs when built with clang on armhf
* [@http://svn.boost.org/trac/boost/ticket/10340 #10340] No boost::promise<T>::set_value(const T&) overload present in C++03 mode
* [@http://svn.boost.org/trac/boost/ticket/10425 #10425] Missing documentation for when_all/when_any.
* [@http://svn.boost.org/trac/boost/ticket/10426 #10426] Take in account the deferred futures in when_all.
* [@http://svn.boost.org/trac/boost/ticket/10427 #10427] Take in account the deferred and ready futures in when_any.
* [@http://svn.boost.org/trac/boost/ticket/10428 #10428] Adapt to new unique_ptr interface in Boost.Move
* [@http://svn.boost.org/trac/boost/ticket/10465 #10465] Missing implementation of when_all/when_any when the result is a tuple.
* [@http://svn.boost.org/trac/boost/ticket/10476 #10476] classes using BOOST_THREAD_MOVABLE_ONLY<T> dont satisfy is_copy_constructible<T>::value == false
* [@http://svn.boost.org/trac/boost/ticket/10478 #10478] Data race in boost/thread/future.hpp
* [@http://svn.boost.org/trac/boost/ticket/10529 #10529] The pthread/condition_variable_any constructor reports incorrect error code for pthread_cond_init
* [@http://svn.boost.org/trac/boost/ticket/10563 #10563] shared_future<R>::then should be const
[heading Version 4.3.0 - boost 1.56]
[*Know Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/2442 #2442] Application statically linked with Boost.Thread crashes when Google Desktop is installed (Windows XP)
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
* [@http://svn.boost.org/trac/boost/ticket/4833 #4833] MinGW/test_tss_lib: Support of automatic tss cleanup for native threading API not available
* [@http://svn.boost.org/trac/boost/ticket/6782 #6782] call_once uses incorrect barrier intrinsic on Visual Studio
* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue
* [@http://svn.boost.org/trac/boost/ticket/8600 #8600] wait_for_any hangs, if called with multiple copies of shared_future referencing same task
* [@http://svn.boost.org/trac/boost/ticket/9307 #9307] future::fallback_to assert with ERRORRRRR boost: mutex lock failed in pthread_mutex_lock: Invalid argument
* [@http://svn.boost.org/trac/boost/ticket/9308 #9308] future::async fails with terminate called throwing an exception when called with a lambda - clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
* [@http://svn.boost.org/trac/boost/ticket/9425 #9425] Boost promise & future does not use supplied allocator for value storage
* [@http://svn.boost.org/trac/boost/ticket/9558 #9558] future continuations unit test hangs in get()/pthread_cond_wait() on Mac 10.7/32-bit/x86/darwin-4.2.1
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last snapshot.
[*Sever limitations:]
There are some severe bugs that prevent the use of the library on concrete contexts, in particular:
* on thread specific storage that prevent the library to be used with dynamic libraries,
* The experimental features of boost::future have some severe holes that make the program crash unexpectedly.
[*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/7446 #7446] Async: Add when_any.
* [@http://svn.boost.org/trac/boost/ticket/7447 #7447] Async: Add when_all.
* [@http://svn.boost.org/trac/boost/ticket/7448 #7448] Async: Add async taking a scheduler parameter.
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Synchro: Add concurrent queue
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Synchro: Add a latch class.
* [@http://svn.boost.org/trac/boost/ticket/8513 #8513] Async: Add a basic thread_pool executor.
* [@http://svn.boost.org/trac/boost/ticket/8516 #8516] Async: Add future/shared_future::then taking a scheduler as parameter.
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/8070 #8070] prefer GetTickCount64 over GetTickCount
* [@http://svn.boost.org/trac/boost/ticket/9333 #9333] ex_scoped_thread compile fails on msvc-12.0
* [@http://svn.boost.org/trac/boost/ticket/9366 #9366] async(Executor, ...) fails to compile with msvc-10,11,12
* [@http://svn.boost.org/trac/boost/ticket/9402 #9402] test_excutor regression on msvc-10,11,12
* [@http://svn.boost.org/trac/boost/ticket/9404 #9404] ex_make_future regression error
* [@http://svn.boost.org/trac/boost/ticket/9471 #9471] Synchronization documentation nits
* [@http://svn.boost.org/trac/boost/ticket/9535 #9535] Missing exception safety might result in crash
* [@http://svn.boost.org/trac/boost/ticket/9618 #9618] try_join_for problem: program is not terminate.
* [@http://svn.boost.org/trac/boost/ticket/9673 #9673] thread compilation with MingW/gcc on Windows gives errors
* [@http://svn.boost.org/trac/boost/ticket/9708 #9708] boost::condition_variable::timed_wait unexpectedly wakes up while should wait infinite
* [@http://svn.boost.org/trac/boost/ticket/9711 #9711] future continuation called twice
[heading Version 4.2.0 - boost 1.55]
[*Know Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/2442 #2442] Application statically linked with Boost.Thread crashes when Google Desktop is installed (Windows XP)
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
* [@http://svn.boost.org/trac/boost/ticket/4833 #4833] MinGW/test_tss_lib: Support of automatic tss cleanup for native threading API not available
* [@http://svn.boost.org/trac/boost/ticket/6782 #6782] call_once uses incorrect barrier intrinsic on Visual Studio
* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue
* [@http://svn.boost.org/trac/boost/ticket/8600 #8600] wait_for_any hangs, if called with multiple copies of shared_future referencing same task
* [@http://svn.boost.org/trac/boost/ticket/9307 #9307] future::fallback_to assert with ERRORRRRR boost: mutex lock failed in pthread_mutex_lock: Invalid argument
* [@http://svn.boost.org/trac/boost/ticket/9308 #9308] future::async fails with terminate called throwing an exception when called with a lambda - clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread trunk regression test] to see the current state.
[*Sever limitations:]
There are some severe bugs that prevent the use of the library on concrete contexts, in particular:
* on thread specific storage that prevent the library to be used with dynamic libraries,
* The experimental features of boost::future have some severe holes that make the program crash unexpectedly.
[*New Features:]
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Synchro: Update class barrier with a completion function.
* [@http://svn.boost.org/trac/boost/ticket/8515 #8515] Async: Add shared_future::then.
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Synchro: Update class barrier with a completion function
* [@http://svn.boost.org/trac/boost/ticket/8615 #8615] Async: Replace make_future/make_shared_future by make_ready_future.
* [@http://svn.boost.org/trac/boost/ticket/8627 #8627] Async: Add future<>::unwrap and unwrapping constructor.
* [@http://svn.boost.org/trac/boost/ticket/8677 #8677] Async: Add future<>::get_or.
* [@http://svn.boost.org/trac/boost/ticket/8678 #8678] Async: Add future<>::fallback_to.
* [@http://svn.boost.org/trac/boost/ticket/8891 #8891] upgrade_to_unique_lock: missing mutex() function.
* [@http://svn.boost.org/trac/boost/ticket/8955 #8955] Request for more efficient way to get exception_ptr from future.
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/7461 #7461] detail::win32::ReleaseSemaphore may be called with count_to_release equal to 0
* [@http://svn.boost.org/trac/boost/ticket/8070 #8070] prefer GetTickCount64 over GetTickCount
* [@http://svn.boost.org/trac/boost/ticket/8768 #8768] win32 condition_variable::wait_until infinite wait in rare cases.
* [@http://svn.boost.org/trac/boost/ticket/8817 #8817] Boost Thread Windows CE _createthreadex handling breaks mingw w64.
* [@http://svn.boost.org/trac/boost/ticket/8943 #8943] Failed to compile code using boost::call_once with Intel C++ Composer XE 2013 on Windows.
* [@http://svn.boost.org/trac/boost/ticket/8931 #8931] Typos in external_locking reference.
* [@http://svn.boost.org/trac/boost/ticket/9029 #9029] Misprint in documentation.
* [@http://svn.boost.org/trac/boost/ticket/9037 #9037] gcc -Wshadow gives warnings in condition_variable{,_fwd}.hpp.
* [@http://svn.boost.org/trac/boost/ticket/9041 #9041] Boost.Thread DSO's may need to link with Boost.Atomic.
* [@http://svn.boost.org/trac/boost/ticket/9048 #9048] boost::scoped_thread useless ctor with variadic template arguments.
* [@http://svn.boost.org/trac/boost/ticket/9079 #9079] Condition variable will wait forever for some timepoint values (Win).
[heading Version 4.1.0 - boost 1.54]
@@ -50,10 +203,19 @@
* [@http://svn.boost.org/trac/boost/ticket/8323 #8323] boost::thread::try_join_for/try_join_until may block indefinitely due to a combination of problems in Boost.Thread and Boost.Chrono
* [@http://svn.boost.org/trac/boost/ticket/8337 #8337] The internal representation of "std::string(this->code()->message())" escapes, but is destroyed when it exits scope.
* [@http://svn.boost.org/trac/boost/ticket/8371 #8371] C++11 once_flag enabled when constexpr is not available
* [@http://svn.boost.org/trac/boost/ticket/8422 #8422] Assertion in win32::WaitForSingleObject()
* [@http://svn.boost.org/trac/boost/ticket/8443 #8443] Header file inclusion order may cause crashes
* [@http://svn.boost.org/trac/boost/ticket/8451 #8451] Missing documented function 'boost::scoped_thread::joinable'
* [@http://svn.boost.org/trac/boost/ticket/8458 #8458] -DBOOST_THREAD_DONT_USE_CHRONO in thread.obj.rsp but not explicitly set
* [@http://svn.boost.org/trac/boost/ticket/8530 #8530] [Coverity] Unused variable thread_handle, uninitialized variable cond_mutex in thread/pthread/thread_data.hpp
* [@http://svn.boost.org/trac/boost/ticket/8550 #8550] static linking of Boost.Thread with an MFC-Dll
* [@http://svn.boost.org/trac/boost/ticket/8576 #8576] "sur parolle" should be "sur parole".
* [@http://svn.boost.org/trac/boost/ticket/8596 #8596] With C++0x enabled, boost::packaged_task stores a reference to function objects, instead of a copy.
* [@http://svn.boost.org/trac/boost/ticket/8626 #8626] Reintroduce BOOST_VERIFY on pthread_mutex_destroy return type
* [@http://svn.boost.org/trac/boost/ticket/8645 #8645] Typo in Strict lock definition
* [@http://svn.boost.org/trac/boost/ticket/8671 #8671] promise: set_..._at_thread_exit
* [@http://svn.boost.org/trac/boost/ticket/8672 #8672] future<>::then(void()) doesn't works
* [@http://svn.boost.org/trac/boost/ticket/8674 #8674] Futures as local named objects can't be returned with implicit move.
[heading Version 4.0.0 - boost 1.53]
@@ -402,23 +564,15 @@ The following features will be included in next releases.
* [@http://svn.boost.org/trac/boost/ticket/7589 #7589] Synchro: Add polymorphic lockables.
# Add some features based on C++ proposals, in particular
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Add externally locked streams
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Add concurrent queue
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Sync: Add a latch class
* [@http://svn.boost.org/trac/boost/ticket/XXXX #XXXX] Sync: Add a completion_latch class
* [@http://svn.boost.org/trac/boost/ticket/8513 #8513] Async: Add a basic thread_pool executor.
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Synchro: Add externally locked streams.
* [@http://svn.boost.org/trac/boost/ticket/8514 #8514] Async: Add a thread_pool executor with work stealing.
# Add some of the extension proposed in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3428.pdf A Standardized Representation of Asynchronous Operations] or extension to them, in particular
* [@http://svn.boost.org/trac/boost/ticket/7446 #7446] Async: Add when_any.
* [@http://svn.boost.org/trac/boost/ticket/7447 #7447] Async: Add when_all.
* [@http://svn.boost.org/trac/boost/ticket/7448 #7448] Async: Add async taking a scheduler parameter.
* [@http://svn.boost.org/trac/boost/ticket/8515 #8515] Async: Add shared_future::then
* [@http://svn.boost.org/trac/boost/ticket/8516 #8516] Async: Add future/shared_future::then taking a scheduler as parameter.
* [@http://svn.boost.org/trac/boost/ticket/8517 #8517] Async: Add a variadic future/shared_future::then
# Add extensions related to fork-join as:
* [@http://svn.boost.org/trac/boost/ticket/9600 #9600] Async: Add task_region/task_run.
# And some additional extensions related to futures as:
* [@http://svn.boost.org/trac/boost/ticket/8517 #8517] Async: Add a variadic shared_future::then.
[endsect]

View File

@@ -1,5 +1,5 @@
[/
(C) Copyright 2011-12 Vicente J. Botet Escriba.
(C) Copyright 2011-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).
@@ -9,7 +9,7 @@
[section:cpp11 C++11 standard Thread library]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 standard]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 - Standard for Programming Language C++]]]
[table C++11 standard Conformance
@@ -53,7 +53,7 @@
[[30.4.2.2.1] [unique_lock constructors, destructor, and assignment] [Yes] [-] [-]]
[[30.4.2.2.2] [unique_lock locking] [Yes] [-] [-]]
[[30.4.2.2.3] [unique_lock modifiers] [Yes] [-] [-]]
[[30.4.2.2.4] [unique_lock observers] [Yes] [] [-]]
[[30.4.2.2.4] [unique_lock observers] [Yes] [ - ] [-]]
[[30.4.3] [Generic locking algorithms] [Partial] [variadic] [#6227]]
[[30.4.4] [Call once] [Yes] [-] [-]]
[[30.4.4.1] [Struct once_flag] [Yes] [-] [-]]
@@ -73,24 +73,23 @@
[[30.6.9] [Class template packaged_task] [Yes] [-] [-]]
]
[/
[table Extension
[[Section] [Description] [Comments]]
[[30.3.1.5.x] [interrupt] [-]]
[[30.3.2.x] [Interruption] [-]]
[[30.3.2.y] [at_thread_exit] [-]]
[[30.4.3.x] [Generic locking algorithms begin/end] [-]]
[[30.x] [Barriers] [-]]
[[30.y] [Thread Local Storage] [-]]
[[30.z] [Class thread_group] [-]]
]
[/
[[30.x] [Thread Local Storage] [-]]
[[30.y] [Class thread_group] [-]]
]
[endsect]
[section:cxx14 C++14 standard Thread library - accepted changes]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.html C++14 on-going standard]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.html Working Draft, Standard for Programming Language C++]]
[table [@http://isocpp.org/files/papers/N3659.html N3659 Shared locking in C++ revision 2] Conformance
@@ -102,11 +101,36 @@
[endsect]
[section:cxx1y C++1y TS Concurrency - On going proposals]
[section:cxx1y C++14 TS Extensions for Concurrency V1 ]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4107.html N4107-Extensions for Concurrency]]
[table Improvements to std::future<T> and related APIs]
[[Section] [Description] [Status] [Comments]]
[[2.1] [ - ] [ - ] [ - ]]
[[2.2] [Class template future] [Partial] [ - ]]
[[2.2] [then] [ Partial ] [ without implicit unwrapping #10550 and blocking #10551 ]]
[[2.2] [is_ready] [ Yes ] [ - ]]
[[2.3] [Class template shared_future] [Partial] [ - ]]
[[2.3] [then] [ Partial ] [ Without implicit unwrapping #10550 and blocking #10551 ]]
[[2.3] [is_ready] [ Yes ] [ - ]]
[[2.4] [Function template when_all] [Partial] [ interface not complete #10426 and blocking #10551 ]]
[[2.5] [Function template when_any] [Partial] [ interface not complete #10427 and blocking #10551 ]]
[[2.6] [Function template when_any_back] [No] [ #XXXX ]]
[[2.7] [Function template make_ready_future] [Yes] [ - ]]
]
[endsect]
[section:cxx1y C++1z TS Concurrency - On going proposals]
[section:latch C++ Latches and Barriers]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3659 C++ Latches and Barriers]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3600 C++ Latches and Barriers]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3817.html N3817 C++ Latches and Barriers]]
[table C++ Latches and Barriers Conformance
[[Section] [Description] [Status] [Comments]]
@@ -123,104 +147,84 @@
[[Section] [Description] [Status] [Comments]]
[[X.1] [Conceptual interface] [Partial] [ The interface provided has some differences respect to this proposal. All the functions having a queue_op_status are not provided. No lock-free concrete classes ]]
[[X.1.1] [Basic Operations] [Partial] [ - ]]
[[X.1.1.1] [push] [yes] [ - ]]
[[X.1.1.2] [value_pop] [no] [ renamed pull with two flavors + a ptr_pull that returns a sharted_ptr<>. ]]
[[X.1.2] [Non-waiting operations] [] [ - ]]
[[X.1.2.1] [try_push] [Partial] [ return bool instead ]]
[[X.1.2.2] [try_pop] [Partial] [ renamed try_pull, returns null ]]
[[X.1.3] [Non-blocking operations] [] [ - ]]
[[X.1.3.1] [nonblocking_push] [Partial] [ renamed try_push(no_block, ]]
[[X.1.3.2] [nonblocking_pop] [Partial] [ renamed try_pop(no_block, ]]
[[X.1.1.1] [push] [yes] [ renamed push_back. ]]
[[X.1.1.2] [value_pop] [no] [ renamed pull_front with two flavors. ]]
[[X.1.2] [Non-waiting operations] [ - ] [ - ]]
[[X.1.2.1] [try_push] [yes] [ renamed try_push_back ]]
[[X.1.2.2] [try_pop] [yes] [ renamed try_pull_back ]]
[[X.1.3] [Non-blocking operations] [ - ] [ - ]]
[[X.1.3.1] [nonblocking_push] [Yes] [ renamed nonblocking_push_back ]]
[[X.1.3.2] [nonblocking_pop] [Yes] [ renamed nonblocking_pull_front ]]
[[X.1.4] [Push-front operations] [No] [ - ]]
[[X.1.5] [Closed queues] [Partial] [ - ]]
[[X.1.5.1] [close] [Yes] [ - ]]
[[X.1.5.2] [is_closed] [Yes] [ - ]]
[[X.1.5.3] [wait_push] [Partial] [ - ]]
[[X.1.5.4] [wait_pop] [Partial] [ - ]]
[[X.1.5.2] [is_closed] [Yes] [ renamed closed ]]
[[X.1.5.3] [wait_push] [Yes] [ renamed wait_push_back ]]
[[X.1.5.4] [wait_pop] [Yes] [ renamed wait_pull_front ]]
[[X.1.5.5] [wait_push_front] [no] [ - ]]
[[X.1.5.6] [wait_pop] [Partial] [ - ]]
[[X.1.5.6] [wait_pop_back] [no] [ - ]]
[[X.1.5.6] [open] [no] [ - ]]
[[X.1.6] [Empty and Full Queues] [Yes] [ - ]]
[[X.1.6.1] [is_empty] [Yes] [ - ]]
[[X.1.6.2] [is_full] [Yes] [ Added capacity ]]
[[X.1.7] [Queue Names] [No] [ Not considere a must for the time been. ]]
[[X.1.7] [Queue Names] [No] [ Not considered a must for the time been. ]]
[[X.1.8] [Element Type Requirements] [Yes?] [ - ]]
[[X.1.9] [Exception Handling] [Yes?] [ - ]]
[[X.1.10] [Queue Ordering] [Yes?] [ - ]]
[[X.1.11] [Lock-Free Implementations] [No] [ waiting to stabilize the lock-based interface. Will use Boost.LockFree once it is Move aware. ]]
[[X.2] [Concrete queues] [Partial] [ ]]
[[X.1.11] [Lock-Free Implementations] [No] [ waiting to stabilize the lock-based interface. Will use Boost.LockFree once it is Boost.Move aware. ]]
[[X.2] [Concrete queues] [Partial] [ - ]]
[[X.2.1] [Locking Buffer Queue] [Partial] [ classes sync_queue and a sync_bounded_queue. ]]
[[X.2.1] [Lock-Free Buffer Queue] [No] [ ]]
[[X.3] [Additional Conceptual Tools] [No] [ ]]
[[X.3.1] [Fronts and Backs] [No] [ ]]
[[X.3.2] [Streaming Iterators] [No] [ ]]
[[X.3.3] [Storage Iterators] [No] [ ]]
[[X.3.4] [Binary Interfaces] [No] [ ]]
[[X.3.4] [Managed Indirection] [No] [ ]]
[[X.2.1] [Lock-Free Buffer Queue] [No] [ waiting to stabilize the lock-based interface. Will use Boost.LockFree once it is Boost.Move aware. ]]
[[X.3] [Additional Conceptual Tools] [No] [ - ]]
[[X.3.1] [Fronts and Backs] [No] [ - ]]
[[X.3.2] [Streaming Iterators] [No] [ - ]]
[[X.3.3] [Storage Iterators] [No] [ - ]]
[[X.3.4] [Binary Interfaces] [No] [ - ]]
[[X.3.4] [Managed Indirection] [No] [ - ]]
]
[endsect]
[section:executors Asynchronous Executors]
While Boost.Thread implementation of executors would not use dynamic polymorphism, it is worth comparing with the current trend on the standard.
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3378.pdf N3378 A preliminary proposal for work executors]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3785.pdf N3785 Executors and Schedulers]]
[table Asynchronous Executors
[[Section] [Description] [Status] [Comments]]
[[30.X.1] [Class executor] [No] [ - ]]
[[30.X.1.1] [add] [No] [ renamed with a function template submit ]]
[[30.X.1.1] [num_of_pendin_closures] [??] [ ]]
[[30.X.2] [Class sceduled_executor] [No] [ - ]]
[[30.X.2.1] [add_at] [No] [ renamed with a function template submit_at ]]
[[30.X.2.2] [add_after] [No] [ renamed with a function template submit_after ]]
[[30.X.3] [Executor utilities functions] [No] [ - ]]
[[30.X.3.1] [default_executor] [No] [ - ]]
[[30.X.3.2] [set_default_executor] [No] [ - ]]
[[30.X.3.3] [singleton_inline_executor] [No] [ - ]]
[[30.X.4] [Concrete executor classes] [No] [ - ]]
[[30.X.4.1] [loop_executor] [No] [ - ]]
[[30.X.4.1] [serial_executor] [No] [ - ]]
[[30.X.4.1] [thread_pool] [No] [ #8513 ]]
[[V.1.1] [Class executor] [Yes] [ - ]]
[[V.1.1] [add] [Yes] [ renamed with a function template submit ]]
[[V.1.1] [num_of_pendin_closures] [No] [ ]]
[[V.1.2] [Class sceduled_executor] [No] [ - ]]
[[V.1.2] [add_at] [No] [ renamed with a function template submit_at ]]
[[V.1.2] [add_after] [No] [ renamed with a function template submit_after ]]
[[V.2] [Concrete executor classes] [No] [ - ]]
[[V.2.1] [thread_pool] [Yes] [ static version Basic_thread_pool, dynamic one execduler_adaptor<basic_thread_pool> ]]
[[V.2.2] [serial_executor] [yes] [ - ]]
[[V.2.3] [loop_executor] [Yes] [ static version loop_scheduler, dynamic one execduler_adaptor<loop_scheduler> ]]
[[V.2.4] [inline_executor] [Yes] [ static version inline_executor, dynamic one execduler_adaptor<inline_executor> ]]
[[V.2.5] [thread_executor] [Yes] [ static version thread_executor, dynamic one execduler_adaptor<thread_executor> ]]
]
[endsect]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3784.pdf N3784-Improvements to `std::future<T> and Related APIs]]
[section:async A Standardized Representation of Asynchronous Operations]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3558.pdf N3558 A Standardized Representation of Asynchronous Operations]]
[table A Standardized Representation of Asynchronous Operations Conformance
[table `async, future/shared_future::then`and Executors
[[Section] [Description] [Status] [Comments]]
[[30.6.6] [Class template future] [Partial] [ - ]]
[[30.6.6.1] [then] [Partial] [ executor interface missing #8516 ]]
[[30.6.6.2] [unwrap] [No] [ #XXXX ]]
[[30.6.6.3] [ready] [yes] [ is_ready ]]
[[30.6.7] [Class template shared_future] [Partial] [ - ]]
[[30.6.7.1] [then] [No] [ #8515 ]]
[[30.6.7.2] [unwrap] [No] [ #XXXX ]]
[[30.6.7.3] [ready] [Yes] [ is_ready ]]
[[30.6.X] [Function template when_any] [No] [ #7446 ]]
[[30.6.X] [Function template when_all] [No] [ #7447 ]]
[[30.6.X] [Function template make_ready_future] [Yes] [ - ]]
[[30.6.8] [Function template async ] [No] [ executor interface missing #7448 ]]
[[30.6.6] [`future<T>::then`] [Yes] [ ]]
[[30.6.7] [`shared_future<T>::then`] [Yes] [ ]]
[[30.6.8] [`async`] [Yes] [ - ]]
]
[endsect]
[section:stream_mutex C++ Stream Mutexes]
[section:stream_mutex C++ Stream Mutexes - C++ Stream Guards]
While Boost.Thread implementation of stream mutexes differ in the approach, it is worth comparing with the current trend on the standard.
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3535.html N3535 - C++ Stream Mutexes]]
[note These functions are based on [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3535.html [*N3535 - C++ Stream Mutexes]] by Lawrence Crowl.]
[table C++ C++ Stream MutexesConformance
[note This proposal has been replaced already by [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html N3678 - C++ Stream Guards], which has been replaced by [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html N3665 - Uninterleaved String Output Streaming] and [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html N3750 - C++ Ostream Buffers]]
[table C++ Stream Mutexes Conformance
[[Section] [Description] [Status] [Comments]]
[[X.1] [Class template stream_mutex] [Partial] [ externally_locked_stream<> ]]
[[X.2.1] [constructor] [Partial] [ externally_locked_stream needs a mutex in addition as argumement. ]]
[[X.1] [Class template stream_mutex] [Partial] [ Renamed externally_locked_stream<> ]]
[[X.2.1] [constructor] [Partial] [ externally_locked_stream needs a mutex in addition as argument. ]]
[[X.2.2] [lock] [yes] [ - ]]
[[X.2.3] [unlock] [yes] [ - ]]
[[X.2.4] [try_lock] [yes] [ - ]]
@@ -230,10 +234,11 @@ While Boost.Thread implementation of stream mutexes differ in the approach, it i
[[X.2.1] [stream_guard] [Yes] [ - ]]
[[X.2.2] [~stream_guard] [Yes] [ - ]]
[[X.2.3] [bypass] [Yes] [ - ]]
[[X.3] [Stream Operators] [Yes] [.]]
[[X.4] [Predefined Objects] [No] [.]]
[[X.3] [Stream Operators] [Yes] [-]]
[[X.4] [Predefined Objects] [No] [-]]
]
[endsect]

View File

@@ -11,7 +11,7 @@
[table Default Values for Configurable Features
[[Feature] [Anti-Feature] [V2] [V3] [V4] ]
[[USES_CHRONO] [DONT_USE_CHRONO] [YES] [YES] [YES] ]
[[USES_CHRONO] [DONT_USE_CHRONO] [YES/NO] [YES/NO] [YES/NO] ]
[[PROVIDES_INTERRUPTIONS] [DONT_PROVIDE_INTERRUPTIONS] [YES] [YES] [YES] ]
[[THROW_IF_PRECONDITION_NOT_SATISFIED] [-] [NO] [NO] [NO] ]
@@ -31,7 +31,7 @@
[[PROVIDES_ONCE_CXX11] [DONT_PROVIDE_ONCE_CXX11] [NO] [YES] [YES] ]
[[USES_MOVE] [DONT_USE_MOVE] [NO] [YES] [YES] ]
[[USES_DATETIME] [DONT_USE_DATETIME] [YES] [YES] [YES/NO] ]
[[USES_DATETIME] [DONT_USE_DATETIME] [YES/NO] [YES/NO] [YES/NO] ]
[[PROVIDES_THREAD_EQ] [DONT_PROVIDE_THREAD_EQ] [YES] [YES] [NO] ]
[[PROVIDES_CONDITION] [DONT_PROVIDE_CONDITION] [YES] [YES] [NO] ]
[[PROVIDES_NESTED_LOCKS] [DONT_PROVIDE_NESTED_LOCKS] [YES] [YES] [NO] ]
@@ -47,6 +47,8 @@
Boost.Thread uses by default Boost.Chrono for the time related functions and define `BOOST_THREAD_USES_CHRONO` if `BOOST_THREAD_DONT_USE_CHRONO` is not defined. The user should define `BOOST_THREAD_DONT_USE_CHRONO` for compilers that don't work well with Boost.Chrono.
[warning When defined BOOST_THREAD_PLATFORM_WIN32 BOOST_THREAD_USES_CHRONO is defined independently of user settings.]
[endsect]
@@ -72,24 +74,32 @@ The Boost.DateTime time related functions introduced in Boost 1.35.0, using the
When `BOOST_THREAD_VERSION<=3` && defined BOOST_THREAD_PLATFORM_PTHREAD define `BOOST_THREAD_DONT_USE_DATETIME` if you don't want to use Boost.DateTime related interfaces.
When `BOOST_THREAD_VERSION>3` && defined BOOST_THREAD_PLATFORM_PTHREAD define `BOOST_THREAD_USES_DATETIME` if you want to use Boost.DateTime related interfaces.
When defined BOOST_THREAD_PLATFORM_WIN32 BOOST_THREAD_USES_DATETIME is defined by default.
[warning When defined BOOST_THREAD_PLATFORM_WIN32 BOOST_THREAD_USES_DATETIME is defined independently of user settings.]
[endsect]
[section:move Boost.Atomic]
[section:thread_eq `boost::thread::oprator==` deprecated]
Boost.Thread uses by default an Boost.Atomic in POSIX platforms to implement call_once..
The following nested typedefs are deprecated:
Define `BOOST_THREAD_USES_ATOMIC ` if you want to use Boost.Atomic.
Define `BOOST_THREAD_DONT_USE_ATOMIC ` if you don't want to use Boost.Atomic or if it is not supported in your platform.
* `boost::thread::oprator==`
* `boost::thread::oprator!=`
[endsect]
[section:thread_eq `boost::thread::operator==` deprecated]
The following operators are deprecated:
* `boost::thread::operator==`
* `boost::thread::operator!=`
When `BOOST_THREAD_PROVIDES_THREAD_EQ` is defined Boost.Thread provides these deprecated feature.
Use instead
* `boost::thread::id::oprator==`
* `boost::thread::id::oprator!=`
* `boost::thread::id::operator==`
* `boost::thread::id::operator!=`
[warning This is a breaking change respect to version 1.x.]
@@ -294,8 +304,12 @@ When `BOOST_THREAD_VERSION>=4` define `BOOST_THREAD_DONT_PROVIDE_SIGNATURE_PACKA
C++11 thread constructor accep a variable number of rvalue argumentshas. When `BOOST_THREAD_PROVIDES_VARIADIC_THREAD ` is defined Boost.Thread provides this C++ feature if the following are not defined
* BOOST_NO_SFINAE_EXPR
* BOOST_NO_CXX11_VARIADIC_TEMPLATES
* BOOST_NO_CXX11_DECLTYPE
* BOOST_NO_CXX11_DECLTYPE_N3276
* BOOST_NO_CXX11_RVALUE_REFERENCES
* BOOST_NO_CXX11_TRAILING_RESULT_TYPES
* BOOST_NO_CXX11_RVALUE_REFERENCES
* BOOST_NO_CXX11_HDR_TUPLE

View File

@@ -1,5 +1,5 @@
[/
/ Copyright (c) 2008,2012 Vicente J. Botet Escriba
/ Copyright (c) 2008,2012,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)
@@ -8,7 +8,7 @@
[section External Locking -- `strict_lock` and `externally_locked` classes]
[note This tutorial is an adaptation of the paper of Andrei Alexandrescu "Multithreading and the C++ Type System"
[note This tutorial is an adaptation of the paper by Andrei Alexandrescu "Multithreading and the C++ Type System"
to the Boost library.]
[/
@@ -163,7 +163,7 @@ Obviously, the caller-ensured locking approach has a safety problem. BankAccount
To conclude, if in designing a multi-threaded class you settle on internal locking, you expose yourself to inefficiency or deadlocks. On the other hand, if you rely on caller-provided locking, you make your class error-prone and difficult to use. Finally, external locking completely avoids the issue by leaving it all to the client code.
[endsect]
]
[section Locks as Permits]
[section Locks as permits]
So what to do? Ideally, the BankAccount class should do the following:
@@ -182,10 +182,12 @@ For now, let's make a couple of enhancements to the `lock_guard` class template
We'll call the enhanced version `strict_lock`. Essentially, a `strict_lock`'s role is only to live on the stack as an automatic variable.
`strict_lock` must adhere to a non-copy and non-alias policy.
`strict_lock` disables copying by making the copy constructor and the assignment operator private.
While we're at it, let's disable operator new and operator delete;
[/
While we're at it, let's disable operator new and operator delete.
`strict_lock` are not intended to be allocated on the heap.
`strict_lock` avoids aliasing by using a slightly less orthodox and less well-known technique: disable address taking.
]
template <typename Lockable>
class strict_lock {
@@ -215,7 +217,7 @@ Silence can be sometimes louder than words-what's forbidden to do with a `strict
* You can create a `strict_lock<T>` only starting from a valid T object. Notice that there is no other way you can create a `strict_lock<T>`.
BankAccount myAccount("John Doe", "123-45-6789");
strict_locerk<BankAccount> myLock(myAccount); // ok
strict_lock<BankAccount> myLock(myAccount); // ok
* You cannot copy `strict_lock`s to one another. In particular, you cannot pass `strict_lock`s by value to functions or have them returned by functions:
@@ -229,6 +231,7 @@ Silence can be sometimes louder than words-what's forbidden to do with a `strict
// ok, Bar takes a reference to strict_lock<BankAccount>
extern void Bar(strict_lock<BankAccount>&);
[/
* You cannot allocate a `strict_lock` on the heap. However, you still can put `strict_lock`s on the heap if they're members of a class.
strict_lock<BankAccount>* pL =
@@ -250,8 +253,9 @@ Silence can be sometimes louder than words-what's forbidden to do with a `strict
strict_lock<BankAccount>& rAlias = myLock; // ok
Fortunately, references don't engender as bad aliasing as pointers because they're much less versatile (references cannot be copied or reseated).
* You can even make `strict_lock` final; that is, impossible to derive from. This task is left in the form of an exercise to the reader.
]
[/* You can even make `strict_lock` final; that is, impossible to derive from. This task is left in the form of an exercise to the reader.
]
All these rules were put in place with one purpose-enforcing that owning a `strict_lock<T>` is a reasonably strong guarantee that
@@ -289,7 +293,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n
}
};
Now, if you want the benefit of internal locking, you simply call Deposit(int) and Withdraw(int). If you want to use external locking, you lock the object by constructing a `strict_lock<BankAccount>` and then you call `Deposit(int, strict_lock<BankAccount>&)` and `Withdraw(int, strict_lock<BankAccount>&)`. For example, here's the `ATMWithdrawal` function implemented correctly:
Now, if you want the benefit of internal locking, you simply call `Deposit(int)` and `Withdraw(int)`. If you want to use external locking, you lock the object by constructing a `strict_lock<BankAccount>` and then you call `Deposit(int, strict_lock<BankAccount>&)` and `Withdraw(int, strict_lock<BankAccount>&)`. For example, here's the `ATMWithdrawal` function implemented correctly:
void ATMWithdrawal(BankAccount& acct, int sum) {
strict_lock<BankAccount> guard(acct);
@@ -398,8 +402,8 @@ The solution is to use a little bridge template `externally_locked` that control
T& get(strict_lock<Lockable>& lock) {
#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME // define BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME if you don't want to check locker check the same lockable
if (!lock.is_locking(&lockable_)) throw lock_error(); run time check throw if not locks the same
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
if (!lock.owns_lock(&lockable_)) throw lock_error(); run time check throw if not locks the same
#endif
return obj_;
}
@@ -449,7 +453,7 @@ We achieved two important goals. First, the declaration of `checkingAcct_` and `
[section Allowing other strict locks]
Now imagine that the AccountManager function needs to take a `unique_lock` in order to reduce the critical regions. And at some time it needs to access to the `checkingAcct_`. As `unique_lock` is not a strict lock the following code doesn't compiles:
Now imagine that the AccountManager function needs to take a `unique_lock` in order to reduce the critical regions. And at some time it needs to access to the `checkingAcct_`. As `unique_lock` is not a strict lock the following code doesn't compile:
void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
unique_lock<AccountManager> guard(*this, defer_lock);
@@ -461,10 +465,10 @@ Now imagine that the AccountManager function needs to take a `unique_lock` in or
do_something_else();
}
We need a way to transfer the ownership from the `unique_lock` to a `strict_lock` the time we are working with `savingsAcct_` and then restore the ownership on `unique_lock`.
We need a way to transfer the ownership from the `unique_lock` to a `strict_lock` during the time we are working with `savingsAcct_` and then restore the ownership on `unique_lock`.
void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
unique_lock<AccountManager> guard(*this, defer_lock);
unique_lock<AccountManager> guard1(*this, defer_lock);
if (some_condition()) {
guard1.lock();
}
@@ -476,9 +480,9 @@ We need a way to transfer the ownership from the `unique_lock` to a `strict_lock
guard1.unlock();
}
In order to make this code compilable we need to store either a Lockable or a `unique_lock<Lockable>` reference depending on the constructor. Store which kind of reference we have stored,and in the destructor call either to the Lockable `unlock` or restore the ownership.
In order to make this code compilable we need to store either a Lockable or a `unique_lock<Lockable>` reference depending on the constructor. We also need to store which kind of reference we have stored, and in the destructor call either to the Lockable `unlock` or restore the ownership.
This seams too complicated to me. Another possibility is to define a nested strict lock class. The drawback is that instead of having only one strict lock we have two and we need either to duplicate every function taking a `strict\_lock` or make these function templates functions. The problem with template functions is that we don't profit anymore of the C++ type system. We must add some static metafunction that check that the Locker parameter is a strict lock. The problem is that we can not really check this or can we?. The `is_strict_lock` metafunction must be specialized by the strict lock developer. We need to belive it "sur parolle". The advantage is that now we can manage with more than two strict locks without changing our code. Ths is really nice.
This seems too complicated to me. Another possibility is to define a nested strict lock class. The drawback is that instead of having only one strict lock we have two and we need either to duplicate every function taking a `strict_lock` or make these function templates. The problem with template functions is that we don't profit anymore of the C++ type system. We must add some static metafunction that checks that the Locker parameter is a strict lock. The problem is that we can not really check this or can we?. The `is_strict_lock` metafunction must be specialized by the strict lock developer. We need to believe it "sur parole". The advantage is that now we can manage with more than two strict locks without changing our code. This is really nice.
Now we need to state that both classes are `strict_lock`s.
@@ -492,9 +496,9 @@ Now we need to state that both classes are `strict_lock`s.
struct is_strict_lock<nested_strict_lock<Locker> > : mpl::true_ {}
Well let me show how this `nested_strict_lock` class looks like and the impacts on the `externally_locked` class and the `AccountManager::AMoreComplicatedFunction` function.
Well let me show what this `nested_strict_lock` class looks like and the impacts on the `externally_locked` class and the `AccountManager::AMoreComplicatedFunction` function.
First `nested_strict_lock` class will store on a temporary lock the `Locker`, and transfer the lock ownership on the constructor. On destruction he will restore the ownership. Note also that the Locker needs to have already a reference to the mutex otherwise an exception is thrown and the use of the `lock_traits`.
First `nested_strict_lock` class will store on a temporary lock the `Locker`, and transfer the lock ownership on the constructor. On destruction it will restore the ownership. Note the use of `lock_traits` and that the `Locker` needs to have a reference to the mutex otherwise and exception is thrown.
template <typename Locker >
class nested_strict_lock
@@ -508,7 +512,7 @@ First `nested_strict_lock` class will store on a temporary lock the `Locker`, an
: lock_(lock) // Store reference to locker
, tmp_lock_(lock.move()) // Move ownership to temporaty locker
{
#ifndef BOOST_THREAD_STRCIT_LOCKER_DONT_CHECK_OWNERSHIP // Define BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_OWNERSHIP if you don't want to check locker ownership
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
if (tmp_lock_.mutex()==0) {
lock_=tmp_lock_.move(); // Rollback for coherency purposes
throw lock_error();
@@ -519,24 +523,29 @@ First `nested_strict_lock` class will store on a temporary lock the `Locker`, an
~nested_strict_lock() {
lock_=tmp_lock_.move(); // Move ownership to nesting locker
}
typedef bool (nested_strict_lock::*bool_type)() const;
operator bool_type() const { return &nested_strict_lock::owns_lock; }
bool operator!() const { return false; }
bool owns_lock() const { return true; }
const lockable_type* mutex() const { return tmp_lock_.mutex(); }
bool is_locking(lockable_type* l) const { return l==mutex(); }
lockable_type* mutex() const { return tmp_lock_.mutex(); }
bool owns_lock(lockable_type* l) const { return l==mutex(); }
BOOST_ADRESS_OF_DELETE(nested_strict_lock)
BOOST_HEAP_ALLOCATEION_DELETE(nested_strict_lock)
BOOST_DEFAULT_CONSTRUCTOR_DELETE(nested_strict_lock) 8
BOOST_COPY_CONSTRUCTOR_DELETE(nested_strict_lock) 9
BOOST_COPY_ASSIGNEMENT_DELETE(nested_strict_lock) 10
private:
Locker& lock_;
Locker tmp_lock_;
};
[/
typedef bool (nested_strict_lock::*bool_type)() const;
operator bool_type() const { return &nested_strict_lock::owns_lock; }
bool operator!() const { return false; }
BOOST_ADRESS_OF_DELETE(nested_strict_lock)
BOOST_HEAP_ALLOCATEION_DELETE(nested_strict_lock)
BOOST_DEFAULT_CONSTRUCTOR_DELETE(nested_strict_lock)
BOOST_COPY_CONSTRUCTOR_DELETE(nested_strict_lock)
BOOST_COPY_ASSIGNEMENT_DELETE(nested_strict_lock)
]
The `externally_locked` get function is now a template function taking a Locker as parameters instead of a `strict_lock`.
We can add test in debug mode that ensure that the Lockable object is locked.
@@ -548,14 +557,14 @@ We can add test in debug mode that ensure that the Lockable object is locked.
T& get(Locker& lock) {
BOOST_CONCEPT_ASSERT((StrictLockerConcept<Locker>));
BOOST_STATIC_ASSERT((is_strict_lock<Locker>::value)); // locker is a strict locker "sur parolle"
BOOST_STATIC_ASSERT((is_strict_lock<Locker>::value)); // locker is a strict locker "sur parole"
BOOST_STATIC_ASSERT((is_same<Lockable,
typename lockable_type<Locker>::type>::value)); // that locks the same type
#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_OWNERSHIP // define BOOST_THREAD_EXTERNALLY_LOCKED_NO_CHECK_OWNERSHIP if you don't want to check locker ownership
if (! lock ) throw lock_error(); // run time check throw if no locked
#endif
#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME
if (!lock.is_locking(&lockable_)) throw lock_error();
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
if (!lock.owns_lock(&lockable_)) throw lock_error();
#endif
return obj_;
}

File diff suppressed because it is too large Load Diff

View File

@@ -293,7 +293,7 @@ that is to allow multiple concurrent get operations.
[heading Multiple get]
The second `get()` call in the following example future
The second `get()` call in the following example is undefined.
void bad_second_use( type arg ) {
@@ -308,7 +308,7 @@ The second `get()` call in the following example future
use3( ftr.get() ); // second use is undefined
}
Using a `shared_mutex` solves the issue
Using a `shared_future` solves the issue
void good_second_use( type arg ) {
@@ -341,7 +341,7 @@ Here `share()` could be used to simplify the code
use3( ftr.get() ); // second use is defined
}
[heading Writting on get()]
[heading Writing on get()]
The user can either read or write the future avariable.
@@ -369,17 +369,17 @@ and a `shared_future` that can be shared between several threads, but there were
[endsect]
[section:make_future Making immediate futures easier]
[section:make_ready_future Making immediate futures easier]
Some functions may know the value at the point of construction. In these cases the value is immediately available,
but needs to be returned as a future or shared_future. By using make_future (make_shared_future) a future (shared_future)
but needs to be returned as a future or shared_future. By using make_ready_future a future
can be created which holds a pre-computed result in its shared state.
Without these features it is non-trivial to create a future directly from a value.
First a promise must be created, then the promise is set, and lastly the future is retrieved from the promise.
This can now be done with one operation.
[heading make_future / make_shared_future]
[heading make_ready_future]
This function creates a future for a given value. If no value is given then a future<void> is returned.
This function is primarily useful in cases where sometimes, the return value is immediately available, but sometimes
@@ -389,16 +389,14 @@ the function must return an eventual value represented as a future.
boost::future<int> compute(int x)
{
if (x == 0) return boost::make_future(0);
if (x < 0) return boost::make_future(-1);
if (x == 0) return boost::make_ready_future(0);
if (x < 0) return boost::make_ready_future<int>(std::logic_error("Error"));
boost::future<int> f1 = boost::async([]() { return x+1; });
return f1;
}
There are two variations of this function. The first takes a value of any type, and returns a future of that type.
The input value is passed to the shared state of the returned future. The second version takes no input and returns a future<void>.
make_shared_future has the same functionality as make_future, except has a return type of shared_future.
The input value is passed to the shared state of the returned future. The second version takes no input and returns a future<void>.
[endsect]
@@ -406,16 +404,16 @@ make_shared_future has the same functionality as make_future, except has a retur
In asynchronous programming, it is very common for one asynchronous operation, on completion, to invoke a second
operation and pass data to it. The current C++ standard does not allow one to register a continuation to a future.
With .then, instead of waiting for the result, a continuation is "attached" to the asynchronous operation, which is
invoked when the result is ready. Continuations registered using the .then function will help to avoid blocking waits
With `.then`, instead of waiting for the result, a continuation is "attached" to the asynchronous operation, which is
invoked when the result is ready. Continuations registered using the `.then` function will help to avoid blocking waits
or wasting threads on polling, greatly improving the responsiveness and scalability of an application.
future.then provides the ability to sequentially compose two futures by declaring one to be the continuation of another.
With .then the antecedent future is ready (has a value or exception stored in the shared state) before the continuation
`future.then()` provides the ability to sequentially compose two futures by declaring one to be the continuation of another.
With `.then()` the antecedent future is ready (has a value or exception stored in the shared state) before the continuation
starts as instructed by the lambda function.
In the example below the future<int> f2 is registered to be a continuation of future<int> f1 using the .then member
function. This operation takes a lambda function which describes how f2 should proceed after f1 is ready.
In the example below the `future<string>` `f2` is registered to be a continuation of `future<int>` `f1` using the `.then()` member
function. This operation takes a lambda function which describes how `f2` should proceed after `f1` is ready.
#include <boost/thread/future.hpp>
@@ -428,7 +426,7 @@ function. This operation takes a lambda function which describes how f2 should p
One key feature of this function is the ability to chain multiple asynchronous operations. In asynchronous programming,
it's common to define a sequence of operations, in which each continuation executes only when the previous one completes.
In some cases, the antecedent future produces a value that the continuation accepts as input. By using future.then,
In some cases, the antecedent future produces a value that the continuation accepts as input. By using `future.then()`,
creating a chain of continuations becomes straightforward and intuitive:
myFuture.then(...).then(...).then(...).
@@ -441,21 +439,20 @@ Some points to note are:
Input Parameters:
* Lambda function2: One option which was considered was to follow JavaScript's approach and take two functions, one for
success and one for error handling. However this option is not viable in C++ as there is no single base type for
exceptions as there is in JavaScript. The lambda function takes a future as its input which carries the exception
* Lambda function: One option which can be considered is to take two functions, one for
success and one for error handling. However this option has not been retained for the moment.
The lambda function takes a future as its input which carries the exception
through. This makes propagating exceptions straightforward. This approach also simplifies the chaining of continuations.
* Scheduler: Providing an overload to .then, to take a scheduler reference places great flexibility over the execution
* Scheduler: Providing an overload to `.then`, to take a scheduler reference places great flexibility over the execution
of the future in the programmer's hand. As described above, often taking a launch policy is not sufficient for powerful
asynchronous operations. The lifetime of the scheduler must outlive the continuation.
* Launch policy: if the additional flexibility that the scheduler provides is not required.
Return values: The decision to return a future was based primarily on the ability to chain multiple continuations using
.then. This benefit of composability gives the programmer incredible control and flexibility over their code. Returning
a future object rather than a shared_future is also a much cheaper operation thereby improving performance. A
shared_future object is not necessary to take advantage of the chaining feature. It is also easy to go from a future
to a shared_future when needed using future::share().
`.then()`. This benefit of composability gives the programmer incredible control and flexibility over their code. Returning
a `future` object rather than a `shared_future` is also a much cheaper operation thereby improving performance. A
`shared_future` object is not necessary to take advantage of the chaining feature. It is also easy to go from a `future`
to a `shared_future` when needed using future::share().
[endsect]

View File

@@ -1,5 +1,5 @@
[/
/ Copyright (c) 2008 Vicente J. Botet Escriba
/ Copyright (c) 2008,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)
@@ -14,7 +14,7 @@ Consider, for example, modeling a bank account class that supports simultaneous
From here a component is a model of the `Callable` concept.
On C++11 (Boost) concurrent execution of a component is obtained by means of the `std::thread`(`boost::thread`):
I C++11 (Boost) concurrent execution of a component is obtained by means of the `std::thread`(`boost::thread`):
boost::thread thread1(S);
@@ -53,12 +53,12 @@ The following example includes a bank account of a person (Joe) and two componen
return 0;
}
From time to time, the `bankAgent` will deposit $500 in `JoesAccount`. Joe will similarly withdraw $100 from his account. These sentences describe that the bankAgent and Joe are executed concurrently.
From time to time, the `bankAgent` will deposit $500 in `JoesAccount`. `Joe` will similarly withdraw $100 from his account. These sentences describe that the `bankAgent` and `Joe` are executed concurrently.
[endsect]
[section Internal locking]
The above example works well as long as the bankAgent and Joe doesn't access JoesAccount at the same time. There is, however, no guarantee that this will not happen. We may use a mutex to guarantee exclusive access to each bank.
The above example works well as long as the components `bankAgent` and `Joe` doesn't access `JoesAccount` at the same time. There is, however, no guarantee that this will not happen. We may use a mutex to guarantee exclusive access to each bank.
class BankAccount {
boost::mutex mtx_;
@@ -82,11 +82,11 @@ The above example works well as long as the bankAgent and Joe doesn't access Joe
}
};
Execution of the Deposit and Withdraw operations will no longer be able to make simultaneous access to balance.
Execution of the `Deposit` and `Withdraw` operations will no longer be able to make simultaneous access to balance.
Mutex is a simple and basic mechanism for obtaining synchronization. In the above example it is relatively easy to be convinced that the synchronization works correctly (in the absence of exception). In a system with several concurrent objects and several shared objects, it may be difficult to describe synchronization by means of mutexes. Programs that make heavy use of mutexes may be difficult to read and write. Instead, we shall introduce a number of generic classes for handling more complicated forms of synchronization and communication.
A mutex is a simple and basic mechanism for obtaining synchronization. In the above example it is relatively easy to be convinced that the synchronization works correctly (in the absence of exception). In a system with several concurrent objects and several shared objects, it may be difficult to describe synchronization by means of mutexes. Programs that make heavy use of mutexes may be difficult to read and write. Instead, we shall introduce a number of generic classes for handling more complicated forms of synchronization and communication.
With the RAII idiom we can simplify a lot this using the scoped locks. In the code below, guard's constructor locks the passed-in object this, and guard's destructor unlocks this.
With the RAII idiom we can simplify a lot this using the scoped locks. In the code below, guard's constructor locks the passed-in object `mtx_`, and guard's destructor unlocks `mtx_`.
class BankAccount {
boost::mutex mtx_; // explicit mutex declaration
@@ -135,10 +135,10 @@ In an attempt to solve this problem, let's lock the account from the outside dur
acct.Withdraw(2);
}
Notice that the code above doesn't compiles, the `mtx_` field is private.
Notice that the code above doesn't compile, the `mtx_` field is private.
We have two possibilities:
* make `mtx_` public which seams odd
* make `mtx_` public which seems odd
* make the `BankAccount` lockable by adding the lock/unlock functions
We can add these functions explicitly

View File

@@ -7,13 +7,19 @@
[section:latches Latches -- EXPERIMENTAL]
[////////////////////]
[section Introdcution]
Latches are a thread co-ordination mechanism that allow one or more threads to block until one or more threads have reached a point. An individual latch is a reusable object; once the operation has been completed, the threads can re-use the same barrier. It is thus useful for managing repeated tasks handled by multiple threads.
Latches are a thread co-ordination mechanism that allow one or more threads to block until one or more threads have reached a point.
[/
An individual latch is a reusable object; once the operation has been completed, the threads can re-use the same barrier. It is thus useful for managing repeated tasks handled by multiple threads.
A completion latch is like a latch that allows to associate a completion function which will be called once the internal counter reaches the value 0 and all the consumer threads have taken care of the notification.
]
[endsect]
[////////////////]
[section Examples]
Sample use cases for the latch include:
@@ -38,7 +44,6 @@ An example of the first use case would be as follows:
An example of the second use case is shown below. We need to load data and then process it using a number of threads. Loading the data is I/O bound, whereas starting threads and creating data structures is CPU bound. By running these in parallel, throughput can be increased.
void DoWork() {
latch start_latch(1);
vector<thread*> workers;
@@ -57,6 +62,7 @@ An example of the second use case is shown below. We need to load data and then
start_latch.count_down();
}
[/
The completion latches can be used to co-ordinate also a set of threads carrying out a repeated task. The number of threads can be adjusted dynamically to respond to changing requirements.
In the example below, a number of threads are performing a multi-stage task. Some tasks may require fewer steps than others, meaning that some threads may finish before others. We reduce the number of threads waiting on the latch when this happens.
@@ -96,8 +102,10 @@ In the example below, a number of threads are performing a multi-stage task. Som
GetNextStage(tasks);
}
}
]
[endsect]
[///////////////////////////]
[section:latch Class `latch`]
#include <boost/thread/latch.hpp>
@@ -119,16 +127,20 @@ In the example below, a number of threads are performing a multi-stage task. Som
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time);
void count_down();
void count_down_and_wait();
void reset(std::size_t count);
};
[/
void reset(std::size_t count);
]
A latch maintains an internal counter that is initialized when the latch is created. One or more threads may block waiting until the counter is decremented to 0.
Instances of __latch__ are not copyable or movable.
[section Constructor]
[///////////////////]
[section Constructor `latch(std::size_t)`]
latch(std::size_t count);
@@ -136,14 +148,15 @@ Instances of __latch__ are not copyable or movable.
[[Effects:] [Construct a latch with is initial value for the internal counter.]]
[[Note:] [The counter could be zero and reset later.]]
[[Note:] [The counter could be zero.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section Destructor]
[//////////////////]
[section Destructor `~latch()`]
~latch();
@@ -158,7 +171,8 @@ Instances of __latch__ are not copyable or movable.
]
[endsect]
[section:wait Member function `wait()`]
[/////////////////////////////////////]
[section:wait Member Function `wait()`]
void wait();
@@ -178,8 +192,8 @@ are unblocked. ]]
]
[endsect]
[section:try_wait Member function `try_wait()`]
[/////////////////////////////////////////////]
[section:try_wait Member Function `try_wait()`]
bool try_wait();
@@ -194,8 +208,8 @@ are unblocked. ]]
]
[endsect]
[section:wait_for Member function `wait_for() `]
[//////////////////////////////////////////////]
[section:wait_for Member Function `wait_for() `]
template <class Rep, class Period>
cv_status wait_for(const chrono::duration<Rep, Period>& rel_time);
@@ -216,7 +230,8 @@ are unblocked. ]]
]
[endsect]
[section:wait_until Member function `wait_until()`]
[/////////////////////////////////////////////////]
[section:wait_until Member Function `wait_until()`]
template <class lock_type, class Clock, class Duration>
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time);
@@ -237,7 +252,8 @@ are unblocked. ]]
]
[endsect]
[section:count_down Member function `count_down()`]
[/////////////////////////////////////////////////]
[section:count_down Member Function `count_down()`]
void count_down();
@@ -256,7 +272,8 @@ are unblocked. ]]
]
[endsect]
[section:count_down_and_wait Member function `count_down_and_wait()`]
[///////////////////////////////////////////////////////////////////]
[section:count_down_and_wait Member Function `count_down_and_wait()`]
void count_down_and_wait();
@@ -275,8 +292,9 @@ are unblocked. ]]
]
[endsect]
[section:reset Member function `reset()`]
[///////////////////////////////////////]
[
[section:reset Member Function `reset()`]
reset( size_t );
@@ -293,9 +311,11 @@ are unblocked. ]]
]
[endsect]
]
[endsect] [/ latch]
[/
[//////////////////////////////////////////////////]
[section:completion_latch Class `completion_latch `]
#include <boost/thread/completion_latch.hpp>
@@ -333,6 +353,7 @@ Instances of completion_latch are not copyable or movable.
Only the additional functions are documented.
[/////////////////////]
[section:c Constructor]
completion_latch(std::size_t count);
@@ -348,6 +369,7 @@ Only the additional functions are documented.
]
[endsect]
[///////////////////////////////////////////////]
[section:cf Constructor with completion function]
template <typename F>
@@ -368,7 +390,8 @@ Only the additional functions are documented.
]
[endsect]
[section:then Member function `then`]
[///////////////////////////////////]
[section:then Member Function `then`]
template <typename F>
completion_function then(F&& funct);
@@ -391,6 +414,6 @@ Only the additional functions are documented.
[endsect]
[endsect] [/ completion_latch]
]
[endsect] [/ Latches]

View File

@@ -176,7 +176,7 @@ This trait is true_type if the parameter L meets the __Lockable requirements.
The user could require that the mutex passed to an algorithm is a recursive one. Whether a lockable is recursive or not can not be checked using template meta-programming. This is the motivation for the following trait.
[section:is_recursive_mutex_sur_parolle `is_recursive_mutex_sur_parolle` trait -- EXTENSION]
[section:is_recursive_mutex_sur_parole `is_recursive_mutex_sur_parole` trait -- EXTENSION]
// #include <boost/thread/lockable_traits.hpp>
@@ -185,15 +185,15 @@ The user could require that the mutex passed to an algorithm is a recursive one.
namespace sync
{
template<typename L>
class is_recursive_mutex_sur_parolle: false_type; // EXTENSION
class is_recursive_mutex_sur_parole: false_type; // EXTENSION
template<>
class is_recursive_mutex_sur_parolle<recursive_mutex>: true_type; // EXTENSION
class is_recursive_mutex_sur_parole<recursive_mutex>: true_type; // EXTENSION
template<>
class is_recursive_mutex_sur_parolle<timed_recursive_mutex>: true_type; // EXTENSION
class is_recursive_mutex_sur_parole<timed_recursive_mutex>: true_type; // EXTENSION
}
}
The trait `is_recursive_mutex_sur_parolle` is `false_type` by default and is specialized for the provide `recursive_mutex` and `timed_recursive_mutex`.
The trait `is_recursive_mutex_sur_parole` is `false_type` by default and is specialized for the provide `recursive_mutex` and `timed_recursive_mutex`.
It should be specialized by the user providing other model of recursive lockable.
@@ -211,7 +211,7 @@ It should be specialized by the user providing other model of recursive lockable
}
}
This traits is true_type if is_basic_lockable and is_recursive_mutex_sur_parolle.
This traits is true_type if is_basic_lockable and is_recursive_mutex_sur_parole.
[endsect]
[section:is_recursive_lockable `is_recursive_lockable` trait -- EXTENSION]
@@ -226,7 +226,7 @@ This traits is true_type if is_basic_lockable and is_recursive_mutex_sur_parolle
}
}
This traits is true_type if is_lockable and is_recursive_mutex_sur_parolle.
This traits is true_type if is_lockable and is_recursive_mutex_sur_parole.
[endsect]
@@ -298,8 +298,6 @@ reached. If the specified time has already passed, behaves as __try_lock_ref__.]
[warning
DEPRECATED since 4.00. The following expressions were required on version 2, but are now deprecated.
Available only up to Boost 1.58.
Use instead __try_lock_for, __try_lock_until.
]
@@ -344,14 +342,14 @@ reached. If the specified time has already passed, behaves as __try_lock_ref__.]
[endsect]
[section:shared_lockable `SharedLockable` Concept -- EXTENSION]
[section:shared_lockable `SharedLockable` Concept -- C++14]
// #include <boost/thread/lockable_concepts.hpp>
namespace boost
{
template<typename L>
class SharedLockable; // EXTENSION
class SharedLockable; // C++14
}
@@ -460,8 +458,6 @@ ownership of `m`.]]
[warning
DEPRECATED since 3.00. The following expressions were required on version 2, but are now deprecated.
Available only up to Boost 1.56.
Use instead __try_lock_shared_for, __try_lock_shared_until.
]
@@ -1119,6 +1115,44 @@ object passed to the constructor.]]
]
[endsect]
[endsect]
[section:with_lock_guard With Lock Guard]
// #include <boost/thread/with_lock_guard.hpp>
namespace boost
{
template <class Lockable, class Function, class... Args>
auto with_lock_guard(Lockable& m, Function&& func, Args&&... args) -> decltype(func(boost::forward<Args>(args)...));
}
[section:with_lock_guard Non Member Function `with_lock_guard`]
template <class Lockable, class Function, class... Args>
auto with_lock_guard(
Lockable& m,
Function&& func,
Args&&... args
) -> decltype(func(boost::forward<Args>(args)...));
[variablelist
[[Precondition:] [`m` must be in unlocked state]]
[[Effects:] [call `func` in scope locked by `m`]]
[[Returns:] [Result of `func(args...)` call]]
[[Throws:] [Any exception thrown by the call to `m.lock` and `func(args...)`]]
[[Postcondition:] [`m` is in unlocked state]]
[[Limitations:] [Without c++11 variadic templates support number of arguments is limited to `4`]]
[[] [Without rvalue references support calling class method with `boost::bind` must be const]]
[[] [For correct work with lambda macro `BOOST_RESULT_OF_USE_DECLTYPE` may be needed to define]]
]
[endsect]
[endsect]
@@ -1135,7 +1169,7 @@ object passed to the constructor.]]
}
A StrictLock is a lock that ensures that the associated mutex is locked during the lifetime if the lock.
A StrictLock is a lock that ensures that the associated mutex is locked during the lifetime of the lock.
A type `L` meets the StrictLock requirements if the following expressions are well-formed and have the specified semantics
@@ -1156,13 +1190,13 @@ The type L::mutex_type denotes the mutex that is locked by this lock.
[endsect] [/ mutex_type]
[section:is_strict_lock_sur_parolle `is_strict_lock_sur_parolle<L>`]
[section:is_strict_lock_sur_parole `is_strict_lock_sur_parole<L>`]
As the semantic "ensures that the associated mutex is locked during the lifetime if the lock. " can not be described by syntactic requirements a `is_strict_lock_sur_parolle` trait must be specialized by the user defining the lock so that the following assertion is true:
As the semantic "ensures that the associated mutex is locked during the lifetime of the lock. " can not be described by syntactic requirements a `is_strict_lock_sur_parole` trait must be specialized by the user defining the lock so that the following assertion is true:
is_strict_lock_sur_parolle<L>::value == true
is_strict_lock_sur_parole<L>::value == true
[endsect] [/ is_strict_lock_sur_parolle]
[endsect] [/ is_strict_lock_sur_parole]
[section:owns_lock `cl.owns_lock(m);`]
@@ -1183,8 +1217,8 @@ As the semantic "ensures that the associated mutex is locked during the lifetime
The following classes are models of `StrictLock`:
* strict_lock: ensured by construction,
* nested_strict_lock: "sur parolle" as the user could use adopt_lock_t on unique_lock constructor overload without having locked the mutex,
* __lock_guard__: "sur parolle" as the user could use adopt_lock_t constructor overload without having locked the mutex.
* nested_strict_lock: "sur parole" as the user could use adopt_lock_t on unique_lock constructor overload without having locked the mutex,
* __lock_guard__: "sur parole" as the user could use adopt_lock_t constructor overload without having locked the mutex.
[endsect] [/ Models]
@@ -1205,9 +1239,9 @@ The following classes are models of `StrictLock`:
template<typename Mutex>
void swap(unique_lock <Mutex>& lhs, unique_lock <Mutex>& rhs);
template<typename Lockable>
class shared_lock; // EXTENSION
class shared_lock; // C++14
template<typename Mutex>
void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs); // EXTENSION
void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs); // C++14
template<typename Lockable>
class upgrade_lock; // EXTENSION
template<typename Mutex>
@@ -1235,13 +1269,13 @@ The following classes are models of `StrictLock`:
unique_lock(Lockable& m_,try_to_lock_t);
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
unique_lock(shared_lock<mutex_type>&& sl, try_to_lock_t)
unique_lock(shared_lock<mutex_type>&& sl, try_to_lock_t); // C++14
template <class Clock, class Duration>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::time_point<Clock, Duration>& abs_time);
const chrono::time_point<Clock, Duration>& abs_time); // C++14
template <class Rep, class Period>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::duration<Rep, Period>& rel_time)
const chrono::duration<Rep, Period>& rel_time); // C++14
#endif
template <class Clock, class Duration>
@@ -1253,7 +1287,7 @@ The following classes are models of `StrictLock`:
unique_lock(unique_lock const&) = delete;
unique_lock& operator=(unique_lock const&) = delete;
unique_lock(unique_lock<Lockable>&& other) noexcept;
explicit unique_lock(upgrade_lock<Lockable>&& other) noexcept;
explicit unique_lock(upgrade_lock<Lockable>&& other) noexcept; // EXTENSION
unique_lock& operator=(unique_lock<Lockable>&& other) noexcept;
@@ -1273,7 +1307,7 @@ The following classes are models of `StrictLock`:
explicit operator bool() const noexcept;
bool owns_lock() const noexcept;
Lockable* mutex() const noexcept;
mutex_type* mutex() const noexcept;
#if defined BOOST_THREAD_USE_DATE_TIME || defined BOOST_THREAD_DONT_USE_CHRONO
unique_lock(Lockable& m_,system_time const& target_time);
@@ -1535,7 +1569,7 @@ object associated with `*this`.]]
[endsect]
[section:mutex `Lockable* mutex() const`]
[section:mutex `Lockable* mutex() const noexcept`]
[variablelist
@@ -1583,7 +1617,7 @@ __owns_lock_ref__ returns `false`.]]
[endsect]
[section:shared_lock Class template `shared_lock` - EXTENSION]
[section:shared_lock Class template `shared_lock` - C++14]
// #include <boost/thread/locks.hpp>
// #include <boost/thread/lock_types.hpp>
@@ -1621,7 +1655,7 @@ __owns_lock_ref__ returns `false`.]]
void unlock();
// Conversion from upgrade locking
explicit shared_lock(upgrade_lock<Lockable> && other);
explicit shared_lock(upgrade_lock<Lockable> && other); // EXTENSION
// Conversion from exclusive locking
explicit shared_lock(unique_lock<Lockable> && other);
@@ -1907,7 +1941,7 @@ state (including the destructor) must be called by the same thread that acquired
[endsect]
[section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock`]
[section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock` -- EXTENSION]
// #include <boost/thread/locks.hpp>
// #include <boost/thread/lock_types.hpp>
@@ -1930,6 +1964,8 @@ state (including the destructor) must be called by the same thread that acquired
explicit operator bool() const;
bool owns_lock() const;
mutex_type* mutex() const;
};
__upgrade_to_unique_lock__ allows for a temporary upgrade of an __upgrade_lock__ to exclusive ownership. When constructed with a
@@ -1939,7 +1975,7 @@ __lockable_concept_type__ is downgraded back to ['upgrade ownership].
[endsect]
[section:scoped_try_lock Mutex-specific class `scoped_try_lock`]
[section:scoped_try_lock Mutex-specific class `scoped_try_lock` -- DEPRECATED]
class MutexType::scoped_try_lock
{
@@ -2026,9 +2062,9 @@ __reverse_mutex reverse the operations of a __BasicLockable, that unlocks the lo
template <typename Lock>
class nested_strict_lock;
template <typename Lockable>
struct is_strict_lock_sur_parolle<strict_lock<Lockable> >;
struct is_strict_lock_sur_parole<strict_lock<Lockable> >;
template <typename Lock>
struct is_strict_lock_sur_parolle<nested_strict_lock<Lock> >;
struct is_strict_lock_sur_parole<nested_strict_lock<Lock> >;
#if ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK
template <typename Lockable>

View File

@@ -34,9 +34,10 @@ Scoped Threads are wrappers around a thread that allows the user to state what t
The difference between strict_scoped_thread and scoped_thread is that the strict_scoped_thread hides completely the owned thread and so the user can do nothing with the owned thread other than the specific action given as parameter, while scoped_thread provide the same interface than __thread and forwards all the operations.
boost::strict_scoped_thread<> t1((boost::thread(F)));
boost::strict_scoped_thread<> t2((boost::thread(F)));
t2.interrupt();
boost::strict_scoped_thread<> t1((boost::thread(f)));
//t1.detach(); // compile fails
boost::scoped_thread<> t2((boost::thread(f)));
t2.detach();
[endsect]
@@ -190,7 +191,7 @@ This wrapper can be used to join the thread before destroying it seems a natural
explicit scoped_thread(thread&& th) noexcept;
template <typename F&&, typename ...Args>
explicit strict_scoped_thread(F&&, Args&&...);
explicit scoped_thread(F&&, Args&&...);
~scoped_thread();
@@ -216,6 +217,7 @@ This wrapper can be used to join the thread before destroying it seems a natural
void detach();
static unsigned hardware_concurrency() noexcept;
static unsigned physical_concurrency() noexcept;
typedef thread::native_handle_type native_handle_type;
native_handle_type native_handle();
@@ -323,7 +325,7 @@ any) to `*this`.
[section:call_constructor Move Constructor from a Callable]
template <typename F&&, typename ...Args>
explicit strict_scoped_thread(F&&, Args&&...);
explicit scoped_thread(F&&, Args&&...);
[variablelist
@@ -458,6 +460,20 @@ any) to `*this`.
[endsect]
[section:physical_concurrency Static member function `physical_concurrency()`]
unsigned physical_concurrency() noexecpt;
[variablelist
[[Effects:] [Equivalent to return `thread::physical_concurrency()`.]]
]
[endsect]
[section:nativehandle Member function `native_handle()`]
typedef thread::native_handle_type native_handle_type;

View File

@@ -5,7 +5,7 @@
http://www.boost.org/LICENSE_1_0.txt).
]
[section:shared_mutex Class `shared_mutex` -- EXTENSION]
[section:shared_mutex Class `shared_mutex` -- C++14]
#include <boost/thread/shared_mutex.hpp>
@@ -36,18 +36,18 @@
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
// use upgrade_mutex instead.
void lock_upgrade();
void unlock_upgrade();
void lock_upgrade(); // EXTENSION
void unlock_upgrade(); // EXTENSION
void unlock_upgrade_and_lock();
void unlock_and_lock_upgrade();
void unlock_and_lock_shared();
void unlock_upgrade_and_lock_shared();
void unlock_upgrade_and_lock(); // EXTENSION
void unlock_and_lock_upgrade(); // EXTENSION
void unlock_and_lock_shared(); // EXTENSION
void unlock_upgrade_and_lock_shared(); // EXTENSION
#endif
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock_shared(system_time const& timeout);
bool timed_lock(system_time const& timeout);
bool timed_lock_shared(system_time const& timeout); // DEPRECATED
bool timed_lock(system_time const& timeout); // DEPRECATED
#endif
};

File diff suppressed because it is too large Load Diff

View File

@@ -16,6 +16,7 @@
[endsect] [/tutorial]
[/////////////////////]
[section:ref Reference]
#include <boost/thread/externally_locked_stream.hpp>
@@ -26,7 +27,7 @@
template <class Stream, typename RecursiveMutex=recursive_mutex>
class stream_guard;
template <typename Stream, typename RecursiveMutex>
struct is_strict_lock_sur_parolle<stream_guard<Stream, RecursiveMutex> > : true_type {};
struct is_strict_lock_sur_parole<stream_guard<Stream, RecursiveMutex> > : true_type {};
// Stream-like operators
template <typename Stream, typename RecursiveMutex, typename T>
@@ -48,7 +49,7 @@
operator>>(externally_locked_stream<Stream, RecursiveMutex>& mtx, T& arg);
}
[/////////////////////////////////////////]
[section:stream_guard Class `stream_guard`]
#include <boost/thread/externally_locked_stream.hpp>
@@ -78,6 +79,7 @@
`stream_guard` is a model of __StrictLock.
[//////////////////////////////////////////////////]
[section:constructor `stream_guard(mutex_type & m)`]
[variablelist
@@ -89,7 +91,7 @@
]
[endsect]
[////////////////////////////////////////////////////////////////////////////]
[section:constructor_adopt `stream_guard(mutex_type & m,boost::adopt_lock_t)`]
[variablelist
@@ -105,8 +107,7 @@ obtained by a call to [lock_ref_link `m.lock()`].]]
]
[endsect]
[//////////////////////////////////////////////////////////]
[section:move_constructor `stream_guard(stream_guard && m)`]
@@ -119,8 +120,7 @@ obtained by a call to [lock_ref_link `m.lock()`].]]
]
[endsect]
[////////////////////////////////////]
[section:destructor `~stream_guard()`]
[variablelist
@@ -134,8 +134,8 @@ object passed to the constructor.]]
[endsect]
[endsect]
[//////////////////////////////////////////////////////////////////]
[section:externally_locked_stream Class `externally_locked_stream `]
#include <boost/thread/externally_locked_stream.hpp>
@@ -152,7 +152,6 @@ object passed to the constructor.]]
// Modifiers
stream_guard<Stream, RecursiveMutex> hold();
Stream& bypass() const;
};
}
@@ -162,6 +161,7 @@ provides full access to that object through the `get` member functions, provided
pass a reference to a strict lock object.
[////////////////////////////////////////////////////////////////////////]
[section:constructor `externally_locked_stream(Stream&, RecursiveMutex&)`]
[variablelist
@@ -172,6 +172,7 @@ pass a reference to a strict lock object.
[endsect]
[/////////////////////]
[section:hold `hold()`]
[variablelist
@@ -182,6 +183,8 @@ pass a reference to a strict lock object.
[endsect]
[endsect]

View File

@@ -20,24 +20,44 @@ In addition to the C++11 standard locks, Boost.Thread provides other locks and s
[section:with Executing Around a Function]
In particular, the library provides some lock factories.
In particular, the library provides a way to lock around the execution of a function.
template <class Lockable, class Function>
auto with_lock_guard(Lockable& m, Function f) -> decltype(fn())
{
auto&& _ = boost::make_lock_guard(f);
f();
template <class Lockable, class Function, class... Args>
auto with_lock_guard(
Lockable& m,
Function&& func,
Args&&... args
) -> decltype(func(boost::forward<Args>(args)...)) {
boost::lock_guard<Lockable> lock(m);
return func(boost::forward<Args>(args)...);
}
that can be used with regular functions:
that can be used as
int func(int, int&);
//...
boost::mutex m;
int a;
int result = boost::with_lock_guard(m, func, 1, boost::ref(a));
int i = with_lock_guard(mtx, {}() -> bool
{
// access the protected state
return true;
});
with boost::bind:
int result = boost::with_lock_guard(
m, boost::bind(func, 2, boost::ref(a))
);
or with lambda expression:
int a;
int result = boost::with_lock_guard(
m,
[&a](int x) {
// this scope is protected by mutex m
a = 3;
return x + 4;
},
5
);
[endsect] [/ With]

View File

@@ -6,7 +6,7 @@
/]
[section:synchronized_valuesxxx Synchronized values - EXPERIMENTAL]
[section:synchronized_valuesxxx Synchronized Values - EXPERIMENTAL]
[warning These features are experimental and subject to change in future versions. There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]

View File

@@ -1,3 +1,10 @@
[/
/ 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)
/]
[section:synchronized_value_ref Reference ]

View File

@@ -8,10 +8,10 @@
[library Thread
[quickbook 1.5]
[version 4.1.0]
[version 4.4.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
[copyright 2011-13 Vicente J. Botet Escriba]
[copyright 2011-14 Vicente J. Botet Escriba]
[purpose C++ Library for launching threads and synchronizing data between them]
[category text]
[license
@@ -239,9 +239,9 @@
[include condition_variables.qbk]
[include once.qbk]
[include barrier.qbk]
[/include latch.qbk]
[include latch.qbk]
[include async_executors.qbk]
[include futures.qbk]
[/include async_executors.qbk]
[endsect]
@@ -249,7 +249,7 @@
[section:sds Synchronized Data Structures]
[include synchronized_value.qbk]
[/include sync_queues_ref.qbk]
[include sync_queues_ref.qbk]
[/include sync_streams.qbk]
[endsect]

View File

@@ -26,7 +26,13 @@
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
namespace no_interruption_point // EXTENSION
{
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
}
template<typename Callable>
void at_thread_exit(Callable func); // EXTENSION
@@ -470,6 +476,7 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
void detach();
static unsigned hardware_concurrency() noexcept;
static unsigned physical_concurrency() noexcept;
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
@@ -532,24 +539,14 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
thread& operator=(thread&& other) noexcept;
[warning
DEPRECATED since 3.0.0: BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE behavior.
Available only up to Boost 1.56.
Join the thread before moving.
]
[variablelist
[[Effects:] [Transfers ownership of the thread managed by `other` (if
any) to `*this`.
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If there was a thread previously associated with `*this` then that thread is detached, DEPRECATED
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable call __detach__, DEPRECATED
- if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to std::terminate.
- if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to `std::terminate()`.
]]
[[Postconditions:] [`other->get_id()==thread::id()` and `get_id()` returns the value of `other.get_id()` prior to the assignment.]]
@@ -568,7 +565,7 @@ any) to `*this`.
[variablelist
[[Requires:] [`Callable` must by Copyable and `func()` must be a valid expression.]]
[[Requires:] [`Callable` must be Copyable and `func()` must be a valid expression.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -595,7 +592,7 @@ not of type __thread_interrupted__, then `std::terminate()` will be called. Any
[variablelist
[[Preconditions:] [`Callable` must by copyable.]]
[[Preconditions:] [`Callable` must be copyable.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -623,7 +620,7 @@ If the attributes declare the native thread as detached, the boost::thread will
[variablelist
[[Preconditions:] [`Callable` must by Movable.]]
[[Preconditions:] [`Callable` must be Movable.]]
[[Effects:] [`func` is moved into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -650,7 +647,7 @@ not of type __thread_interrupted__, then `std::terminate()` will be called. Any
[variablelist
[[Preconditions:] [`Callable` must by copyable.]]
[[Preconditions:] [`Callable` must be copyable.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -679,7 +676,7 @@ If the attributes declare the native thread as detached, the boost::thread will
[variablelist
[[Preconditions:] [`F` and each `A`n must by copyable or movable.]]
[[Preconditions:] [`F` and each `A`n must be copyable or movable.]]
[[Effects:] [As if [link
thread.thread_management.thread.callable_constructor
@@ -706,24 +703,17 @@ are copied into internal storage for access by the new thread.]]]
~thread();
[warning
DEPRECATED since 3.0.0: BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE behavior.
Available only up to Boost 1.56.
Join the thread before destroying or use a scoped thread.
]
[variablelist
[[Effects:] [
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If `*this` has an associated thread of execution, calls __detach__, DEPRECATED
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls __detach__, DEPRECATED
- BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to std::terminate. Destroys `*this`.]]
- if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to `std::terminate`. Destroys `*this`.]]
[[Throws:] [Nothing.]]
[[Note:] [Either implicitly detaching or joining a `joinable()` thread in its destructor could result in difficult to debug correctness (for `detach`) or performance (for `join`) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable.]]
[[Note:] [The reason to moving to std::terminate is that either implicitly detaching or joining a `joinable()` thread in its destructor could result in difficult to debug correctness (for `detach`) or performance (for `join`) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable. Join the thread before destroying or use an scoped thread.]]
]
@@ -768,7 +758,7 @@ corresponding successful `join()` return. ]]
[*resource_deadlock_would_occur]: if deadlock is detected or `this->get_id() == boost::this_thread::get_id()`.
[*invalid_argument]: if the thread is not joinable and `BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED` is defined.
[*invalid_argument]: if the thread is not joinable and `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined.
[/
@@ -794,8 +784,6 @@ corresponding successful `join()` return. ]]
[warning
DEPRECATED since 3.00.
Available only up to Boost 1.56.
Use instead __try_join_for, __try_join_until.
]
@@ -819,7 +807,7 @@ unchanged.]]
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[/
@@ -859,7 +847,7 @@ unchanged.]]
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[/
@@ -899,7 +887,7 @@ unchanged.]]
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[/
@@ -935,7 +923,7 @@ unchanged.]]
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
]]
@@ -991,6 +979,21 @@ or 0 if this information is not available.]]
[endsect]
[section:physical_concurrency Static member function `physical_concurrency()`]
unsigned physical_concurrency() noexecpt;
[variablelist
[[Returns:] [The number of physical cores available on the current system. In contrast to `hardware_concurrency()` it does not return
the number of virtual cores, but it counts only physical cores.]]
[[Throws:] [Nothing]]
]
[endsect]
[section:nativehandle Member function `native_handle()`]
typedef platform-specific-type native_handle_type;
@@ -1014,8 +1017,6 @@ implementation. If no such instance exists, `native_handle()` and `native_handle
[warning
DEPRECATED since 4.0.0.
Available only up to Boost 1.58.
Use `a.__get_id()==b.__get_id()` instead`.
]
@@ -1036,8 +1037,6 @@ Use `a.__get_id()==b.__get_id()` instead`.
[warning
DEPRECATED since 4.0.0.
Available only up to Boost 1.58.
Use `a.__get_id()!=b.__get_id()` instead`.
]
@@ -1056,8 +1055,6 @@ Use `a.__get_id()!=b.__get_id()` instead`.
[warning
DEPRECATED since 3.0.0.
Available only up to Boost 1.56.
Use `this_thread::__sleep_for()` or `this_thread::__sleep_until()`.
]
@@ -1081,8 +1078,6 @@ Use `this_thread::__sleep_for()` or `this_thread::__sleep_until()`.
[warning
DEPRECATED since 3.0.0.
Available only up to Boost 1.56.
Use `this_thread::__yield()`.
]
@@ -1474,8 +1469,6 @@ thread attributes implementation. If no such instance exists, `native_handle()`
[warning
DEPRECATED since 3.0.0.
Available only up to Boost 1.56.
Use `__sleep_for()` and `__sleep_until()` instead.
]
@@ -1502,6 +1495,11 @@ specified by `rel_time` has elapsed or the time point specified by
{
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
namespace no_interruption_point
{
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
}
}
[variablelist
@@ -1513,6 +1511,7 @@ specified by `rel_time` has elapsed or the time point specified by
do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted. ]]
[[Notes:] [`sleep_until()` is one of the predefined __interruption_points__.]]
[[Notes:] [`no_interruption_point::sleep_until()` is NOT one of the __interruption_points__.]]
]
@@ -1526,6 +1525,11 @@ do not throw exceptions. __thread_interrupted__ if the current thread of executi
{
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
namespace no_interruption_point
{
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
}
}
[variablelist
@@ -1536,6 +1540,7 @@ by `rel_time` has elapsed.]]
[[Throws:] [Nothing if operations of chrono::duration<Rep, Period> do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted.]]
[[Notes:] [`sleep_for()` is one of the predefined __interruption_points__.]]
[[Notes:] [`no_interruption_point:: sleep_for()` is NOT one of the __interruption_points__.]]
]

View File

@@ -16,7 +16,7 @@ class bounded_buffer : private boost::noncopyable
public:
typedef boost::unique_lock<boost::mutex> lock;
bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }
bounded_buffer(int n) : boost::noncopyable(), begin(0), end(0), buffered(0), circular_buf(n) { }
void send (int m) {
lock lk(monitor);

150
example/executor.cpp Normal file
View File

@@ -0,0 +1,150 @@
// 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)
#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
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/caller_context.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executors/loop_executor.hpp>
#include <boost/thread/executors/serial_executor.hpp>
#include <boost/thread/executors/inline_executor.hpp>
#include <boost/thread/executors/thread_executor.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/thread/executors/executor_adaptor.hpp>
#include <boost/thread/executor.hpp>
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <string>
#include <iostream>
void p1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
//boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
}
void p2()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
//boost::this_thread::sleep_for(boost::chrono::seconds(10));
}
int f1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
return 1;
}
int f2(int i)
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(2));
return i + 1;
}
void submit_some(boost::executor& tp)
{
for (int i = 0; i < 3; ++i) {
tp.submit(&p2);
}
for (int i = 0; i < 3; ++i) {
tp.submit(&p1);
}
}
void at_th_entry(boost::basic_thread_pool& )
{
}
int test_executor_adaptor()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
{
boost::executor_adaptor < boost::basic_thread_pool > ea(4);
submit_some( ea);
{
boost::future<int> t1 = boost::async(ea, &f1);
boost::future<int> t2 = boost::async(ea, &f1);
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
submit_some(ea);
{
boost::basic_thread_pool ea3(1);
boost::future<int> t1 = boost::async(ea3, &f1);
boost::future<int> t2 = boost::async(ea3, &f1);
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
submit_some(ea);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::loop_executor > ea2;
submit_some( ea2);
ea2.underlying_executor().run_queued_closures();
}
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::basic_thread_pool > ea1(4);
boost::executor_adaptor < boost::serial_executor > ea2(ea1);
submit_some(ea2);
}
#endif
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::inline_executor > ea1;
submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::thread_executor > ea1;
submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea(4, at_th_entry);
boost::future<int> t1 = boost::async(ea, &f1);
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
}
}
catch (std::exception& ex)
{
std::cout << "ERROR= " << ex.what() << "" << std::endl;
return 1;
}
catch (...)
{
std::cout << " ERROR= exception thrown" << std::endl;
return 2;
}
}
// std::cout << BOOST_CONTEXTOF << std::endl;
return 0;
}
int main()
{
return test_executor_adaptor();
}

View File

@@ -0,0 +1,103 @@
// 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)
#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_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/detail/log.hpp>
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <exception>
#include <string>
#include <iostream>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
int p1_ex()
{
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
throw std::logic_error("kk");
}
int p1()
{
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
return 1;;
}
int main()
{
const int number_of_tests = 100;
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
{
for (int i=0; i< number_of_tests; i++)
try
{
//boost::future<int> f1 = boost::async(boost::launch::async, &p1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(&p1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f2 = f1.fallback_to(-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f2.wait();
BOOST_ASSERT(f2.get()==1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
{
for (int i=0; i< number_of_tests; i++)
try
{
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1_ex);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f2 = f1.fallback_to(-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f2.wait();
BOOST_ASSERT(f2.get()==-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
return 0;
}
#else
int main()
{
return 0;
}
#endif

View File

@@ -3,8 +3,14 @@
// Distributed under the 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_USES_LOG
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/detail/log.hpp>
@@ -19,15 +25,16 @@ int p1()
return 123;
}
int p2(boost::future<int>& f)
int p2(boost::future<int> f)
{
BOOST_THREAD_LOG << "<P2" << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG << "P2<" << BOOST_THREAD_END_LOG;
try
{
return 2 * f.get();
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
@@ -37,26 +44,81 @@ int p2(boost::future<int>& f)
BOOST_ASSERT(false);
}
BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG;
return 0;
}
int main()
int p2s(boost::shared_future<int> f)
{
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG << "<P2S" << BOOST_THREAD_END_LOG;
try
{
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = f1.then(&p2);
(void)f2.get();
return 2 * f.get();
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
BOOST_ASSERT(false);
}
catch (...)
{
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
BOOST_ASSERT(false);
}
BOOST_THREAD_LOG << "P2S>" << BOOST_THREAD_END_LOG;
return 0;
}
int main()
{
const int number_of_tests = 100;
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
{
for (int i=0; i< number_of_tests; i++)
try
{
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(&p1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f2 = f1.then(&p2);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
(void)f2.get();
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
{
for (int i=0; i< number_of_tests; i++)
try
{
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::shared_future<int> f1 = boost::async(&p1).share();
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f2 = f1.then(&p2s);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
(void)f2.get();
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
return 0;

70
example/future_unwrap.cpp Normal file
View File

@@ -0,0 +1,70 @@
// 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)
#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_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/detail/log.hpp>
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <string>
#include <iostream>
#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
int p1()
{
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
return 123;
}
boost::future<int> p2()
{
BOOST_THREAD_LOG << "<P2" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG;
return boost::move(f1);
}
int main()
{
const int number_of_tests = 100;
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
for (int i=0; i< number_of_tests; i++)
try
{
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
boost::future<int> inner_future = outer_future.unwrap();
int ii = inner_future.get();
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
return 0;
}
#else
int main()
{
return 0;
}
#endif

323
example/future_when_all.cpp Normal file
View File

@@ -0,0 +1,323 @@
// 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)
#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_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/future.hpp>
#include <boost/thread/csbl/vector.hpp>
#include <boost/assert.hpp>
#include <boost/thread/detail/log.hpp>
#include <string>
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
int p1()
{
BOOST_THREAD_LOG
<< "P1" << BOOST_THREAD_END_LOG;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
return 123;
}
int p1b()
{
BOOST_THREAD_LOG
<< "P1b" << BOOST_THREAD_END_LOG;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
return 321;
}
int p2(boost::future<int> f)
{
BOOST_THREAD_LOG
<< " P2 " << BOOST_THREAD_END_LOG;
try
{
return 2 * f.get();
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
BOOST_THREAD_LOG
<< "P2>" << BOOST_THREAD_END_LOG;
}
int p2s(boost::shared_future<int> f)
{
BOOST_THREAD_LOG
<< "<P2" << BOOST_THREAD_END_LOG;
try
{
return 2 * f.get();
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
BOOST_THREAD_LOG
<< "P2>" << BOOST_THREAD_END_LOG;
}
int main()
{
BOOST_THREAD_LOG
<< "<MAIN" << BOOST_THREAD_END_LOG;
{
try
{
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::tuple<> > all0 = boost::when_all();
BOOST_THREAD_LOG
<< BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#endif
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::make_ready_future(1);
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
//(void) all.wait();
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<std::string> f2 = boost::make_ready_future(std::string("nnnnnnn"));;
boost::future<boost::csbl::tuple<boost::future<int>, boost::future<std::string> > > all = boost::when_all(boost::move(f1), boost::move(f2));
//(void) all.wait();
boost::csbl::tuple<boost::future<int>, boost::future<std::string> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > v;
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1b));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
}
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
{
try
{
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::tuple<> > all0 = boost::when_any();
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
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::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#endif
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::make_ready_future(1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<std::string> f1 = boost::make_ready_future(std::string("aaaa"));
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<std::string>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<std::string>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f2 = boost::make_ready_future(1);
boost::future<int> f1 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = boost::async(boost::launch::deferred, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#endif
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > v;
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1b));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
}
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
BOOST_THREAD_LOG
<< "MAIN>" << BOOST_THREAD_END_LOG;
return 0;
}
#else
#include <boost/thread/csbl/vector.hpp>
using namespace boost;
void f( boost::csbl::vector<future<int> > &//vec
, BOOST_THREAD_RV_REF(future<int>) //f
) {
}
int main()
{
boost::csbl::vector<future<int> > vec;
f(vec, make_ready_future(0));
return 0;
}
#endif

View File

@@ -0,0 +1,153 @@
// 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/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
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/caller_context.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executors/loop_executor.hpp>
#include <boost/thread/executors/serial_executor.hpp>
#include <boost/thread/executors/inline_executor.hpp>
#include <boost/thread/executors/thread_executor.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/thread/executors/executor_adaptor.hpp>
#include <boost/thread/executor.hpp>
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <string>
#include <iostream>
void p1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
//boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
}
void p2()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
//boost::this_thread::sleep_for(boost::chrono::seconds(10));
}
int f1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
return 1;
}
int f2(int i)
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(2));
return i + 1;
}
void submit_some(boost::generic_executor_ref tp)
{
for (int i = 0; i < 3; ++i) {
tp.submit(&p2);
}
for (int i = 0; i < 3; ++i) {
tp.submit(&p1);
}
}
void at_th_entry(boost::basic_thread_pool& )
{
}
int test_generic_executor_ref()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
{
boost::basic_thread_pool ea(4);
submit_some( ea);
{
boost::future<int> t1 = boost::async(ea, &f1);
boost::future<int> t2 = boost::async(ea, &f1);
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
submit_some(ea);
{
boost::basic_thread_pool ea3(1);
boost::future<int> t1 = boost::async(ea3, &f1);
boost::future<int> t2 = boost::async(ea3, &f1);
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
submit_some(ea);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::loop_executor ea2;
submit_some( ea2);
ea2.run_queued_closures();
}
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea1(4);
boost::serial_executor ea2(ea1);
submit_some(ea2);
}
#endif
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::inline_executor ea1;
submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
//boost::thread_executor ea1;
//submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea(4, at_th_entry);
boost::future<int> t1 = boost::async(ea, &f1);
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
}
}
catch (std::exception& ex)
{
std::cout << "ERROR= " << ex.what() << "" << std::endl;
return 1;
}
catch (...)
{
std::cout << " ERROR= exception thrown" << std::endl;
return 2;
}
}
// std::cout << BOOST_CONTEXTOF << std::endl;
return 0;
}
int main()
{
return test_generic_executor_ref();
}

View File

@@ -8,22 +8,27 @@
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_USES_LOG
//#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/assert.hpp>
#include <string>
#include <iostream>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
&& ! defined BOOST_NO_CXX11_LAMBDAS
&& ! defined BOOST_NO_CXX11_LAMBDAS && ! (defined BOOST_MSVC && _MSC_VER < 1700)
int main()
{
const int number_of_tests = 100;
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
for (int i=0; i< number_of_tests; i++)
try
{
{
@@ -33,18 +38,20 @@ int main()
}
{
boost::future<int> f1 = boost::async(boost::launch::async, []() {return 123;});
boost::future<int> f2 = f1.then([](boost::future<int>& f) {return 2*f.get(); });
boost::future<int> f2 = f1.then([](boost::future<int> f) {return 2*f.get(); });
int result = f2.get();
BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG;
}
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}

View File

@@ -3,59 +3,127 @@
// Distributed under the 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
#include <boost/thread/future.hpp>
#include <iostream>
namespace boost
{
template <typename T>
exception_ptr make_exception_ptr(T v)
{
return copy_exception(v);
}
}
int p1() { return 5; }
int& p1r() { static int i=0; return i; }
void p() { }
#if defined BOOST_THREAD_USES_MOVE
boost::future<void> void_compute()
{
return BOOST_THREAD_MAKE_RV_REF(boost::make_future());
return BOOST_THREAD_MAKE_RV_REF(boost::make_ready_future());
}
#endif
boost::future<int> compute(int x)
{
if (x == 0) return boost::make_future(0);
if (x < 0) return boost::make_future(-1);
if (x == 0) return boost::make_ready_future(0);
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
if (x < 0) return boost::make_exceptional_future<int>(std::logic_error("Error"));
#else
if (x < 0) return boost::make_exceptional(std::logic_error("Error"));
#endif
//boost::future<int> f1 = boost::async([]() { return x+1; });
boost::future<int> f1 = boost::async(boost::launch::async, p1);
boost::future<int> f1 = boost::async(p1);
return boost::move(f1);
}
boost::future<int&> compute_ref(int x)
{
static int i = 0;
//if (x == 0) return boost::make_ready_future<int&>(i); //This must not compile as the type is deduced as boost::future<int>
if (x == 0) return boost::make_ready_no_decay_future<int&>(i);
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
if (x < 0) return boost::make_exceptional_future<int&>(std::logic_error("Error"));
#else
if (x < 0) return boost::make_exceptional(std::logic_error("Error"));
#endif
boost::future<int&> f1 = boost::async(p1r);
return boost::move(f1);
}
boost::shared_future<int> shared_compute(int x)
{
if (x == 0) return boost::make_shared_future(0);
if (x < 0) return boost::make_shared_future(-1);
if (x == 0) return boost::make_ready_future(0).share();
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
if (x < 0) return boost::make_exceptional_future<int>(std::logic_error("Error")).share();
#else
if (x < 0) return boost::make_exceptional(std::logic_error("Error"));
#endif
//boost::future<int> f1 = boost::async([]() { return x+1; });
boost::shared_future<int> f1 = boost::async(p1).share();
return boost::move(f1);
boost::shared_future<int> f1 = boost::async(&p1).share();
return f1;
}
int main()
{
const int number_of_tests = 100;
for (int i=0; i< number_of_tests; i++)
try
{
// {
// std::cout << __FILE__ << " "<<__LINE__ << std::endl;
// boost::future<int> f = boost::async(boost::launch::async, p1);
// std::cout << i << " "<<f.get() << std::endl;
// }
#if defined BOOST_THREAD_USES_MOVE
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::future<void> f = void_compute();
f.get();
}
#endif
{
boost::future<int> f = compute(2);
std::cout << f.get() << std::endl;
}
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::future<int> f = compute(0);
std::cout << f.get() << std::endl;
}
{
boost::shared_future<int> f = shared_compute(2);
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::future<int&> f = compute_ref(0);
std::cout << f.get() << std::endl;
}
// {
// std::cout << __FILE__ << " "<< __LINE__ << std::endl;
// boost::future<int> f = compute(2);
// std::cout << f.get() << std::endl;
// }
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::shared_future<int> f = shared_compute(0);
std::cout << f.get() << std::endl;
}
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
return 1;
}
catch (...)
{
std::cout << "ERRORRRRR "<<"ERRORRRRR exception thrown" << std::endl;
return 2;
}
return 0;
}

View File

@@ -44,8 +44,8 @@ int main()
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
scoped_thread<> t1(thread(use_cerr, boost::ref(mcerr)));
scoped_thread<> t2(thread(use_cout, boost::ref(mcout)));
scoped_thread<> t1(boost::thread(use_cerr, boost::ref(mcerr)));
scoped_thread<> t2(boost::thread(use_cout, boost::ref(mcout)));
this_thread::sleep_for(chrono::seconds(2));
std::string nm;
{

View File

@@ -0,0 +1,61 @@
// (C) Copyright 2012 Howard Hinnant
// (C) Copyright 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)
// adapted from the example given by Howard Hinnant in
#define BOOST_THREAD_VERSION 4
#include <iostream>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/ostream_buffer.hpp>
void use_cerr()
{
using namespace boost;
chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(5);
int i = 0;
while (chrono::steady_clock::now() < tf)
{
ostream_buffer<std::ostream> mcerr(std::cerr);
mcerr.stream() << "logging data to cerr " << i++ << "\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
void use_cout()
{
using namespace boost;
chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(5);
int i = 0;
while (chrono::steady_clock::now() < tf)
{
ostream_buffer<std::ostream> mcout(std::cout);
mcout.stream() << "logging data to cout " << i++ << "\n";
this_thread::sleep_for(chrono::milliseconds(500));
}
}
int main()
{
using namespace boost;
scoped_thread<> t1(&use_cerr);
scoped_thread<> t2(&use_cout);
this_thread::sleep_for(chrono::seconds(2));
std::string nm = "he, he\n";
{
ostream_buffer<std::ostream> mcout(std::cout);
mcout.stream() << "Enter name: \n";
}
t1.join();
t2.join();
{
ostream_buffer<std::ostream> mcout(std::cout);
mcout.stream() << nm;
}
return 0;
}

View File

@@ -0,0 +1,102 @@
// 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/config.hpp>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/future.hpp>
#include <numeric>
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
template<typename Iterator,typename T>
struct accumulate_block
{
//typedef T result_type;
T operator()(Iterator first,Iterator last)
{
return std::accumulate(first,last,T());
}
};
template<typename Iterator,typename T>
T parallel_accumulate(Iterator first,Iterator last,T init)
{
unsigned long const length=std::distance(first,last);
if(!length)
return init;
unsigned long const block_size=25;
unsigned long const num_blocks=(length+block_size-1)/block_size;
boost::csbl::vector<boost::future<T> > futures(num_blocks-1);
boost::basic_thread_pool pool;
Iterator block_start=first;
for(unsigned long i=0;i<(num_blocks-1);++i)
{
Iterator block_end=block_start;
std::advance(block_end,block_size);
futures[i]=boost::async(pool, accumulate_block<Iterator,T>(), block_start, block_end);
block_start=block_end;
}
T last_result=accumulate_block<Iterator,T>()(block_start,last);
T result=init;
for(unsigned long i=0;i<(num_blocks-1);++i)
{
result+=futures[i].get();
}
result += last_result;
return result;
}
int main()
{
try
{
const int s = 1001;
std::vector<int> vec;
vec.reserve(s);
for (int i=0; i<s;++i)
vec.push_back(1);
int r = parallel_accumulate(vec.begin(), vec.end(),0);
std::cout << r << std::endl;
}
catch (std::exception& ex)
{
std::cout << "ERROR= " << ex.what() << "" << std::endl;
return 1;
}
catch (...)
{
std::cout << " ERROR= exception thrown" << std::endl;
return 2;
}
return 0;
}
#else
///#warning "This compiler doesn't supports variadics"
int main()
{
return 0;
}
#endif

View File

@@ -0,0 +1,110 @@
// 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)
#include <boost/config.hpp>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/future.hpp>
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
#include <numeric>
#include <algorithm>
#include <functional>
#include <iostream>
#include <list>
template<typename T>
struct sorter
{
boost::basic_thread_pool pool;
typedef std::list<T> return_type;
std::list<T> do_sort(std::list<T> chunk_data)
{
if(chunk_data.empty())
{
return chunk_data;
}
std::list<T> result;
result.splice(result.begin(),chunk_data, chunk_data.begin());
T const& partition_val=*result.begin();
typename std::list<T>::iterator divide_point=
std::partition(chunk_data.begin(), chunk_data.end(), [&](T const& val){return val<partition_val;});
std::list<T> new_lower_chunk;
new_lower_chunk.splice(new_lower_chunk.end(), chunk_data, chunk_data.begin(), divide_point);
boost::future<std::list<T> > new_lower = boost::async(pool, &sorter::do_sort, this, std::move(new_lower_chunk));
//boost::future<std::list<T> > new_lower = boost::async<return_type>(pool, &sorter::do_sort, this, std::move(new_lower_chunk));
std::list<T> new_higher(do_sort(chunk_data));
result.splice(result.end(),new_higher);
while(!new_lower.is_ready())
{
pool.schedule_one_or_yield();
}
result.splice(result.begin(),new_lower.get());
return result;
}
};
template<typename T>
std::list<T> parallel_quick_sort(std::list<T>& input)
{
if(input.empty())
{
return input;
}
sorter<T> s;
return s.do_sort(input);
}
int main()
{
try
{
const int s = 101;
std::list<int> lst;
for (int i=0; i<s;++i)
lst.push_back(100-i);
std::list<int> r = parallel_quick_sort(lst);
for (std::list<int>::const_iterator it=r.begin(); it != r.end(); ++it)
std::cout << *it << std::endl;
}
catch (std::exception& ex)
{
std::cout << "ERROR= " << ex.what() << "" << std::endl;
return 1;
}
catch (...)
{
std::cout << " ERROR= exception thrown" << std::endl;
return 2;
}
return 0;
}
#else
//#warning "This compiler doesn't supports variadics and move semantics"
int main()
{
return 0;
}
#endif

View File

@@ -143,7 +143,7 @@ namespace
{
typedef SharedData<Types> S;
auto best_producer_time = std::numeric_limits<Stopwatch::rep>::max();
auto best_producer_time = std::numeric_limits<Stopwatch::rep>::max BOOST_PREVENT_MACRO_SUBSTITUTION ();
std::vector<std::thread> consumers
{ consumer_count };
@@ -165,7 +165,7 @@ namespace
for (unsigned i = 0; i < consumer_count; ++i)
consumers[i].join();
best_producer_time = std::min(best_producer_time, shared_data.producer_time);
best_producer_time = std::min BOOST_PREVENT_MACRO_SUBSTITUTION (best_producer_time, shared_data.producer_time);
}

View File

@@ -42,7 +42,7 @@ void unique()
int main()
{
boost::chrono::high_resolution_clock::duration best_time(std::numeric_limits<boost::chrono::high_resolution_clock::duration::rep>::max());
boost::chrono::high_resolution_clock::duration best_time(std::numeric_limits<boost::chrono::high_resolution_clock::duration::rep>::max BOOST_PREVENT_MACRO_SUBSTITUTION ());
for (int i =100; i>0; --i) {
boost::chrono::high_resolution_clock clock;
boost::chrono::high_resolution_clock::time_point s1 = clock.now();
@@ -61,7 +61,7 @@ int main()
// t13.join();
boost::chrono::high_resolution_clock::time_point f1 = clock.now();
//std::cout << " Time spent:" << (f1 - s1) << std::endl;
best_time = std::min(best_time, f1 - s1);
best_time = std::min BOOST_PREVENT_MACRO_SUBSTITUTION (best_time, f1 - s1);
}
std::cout << "Best Time spent:" << best_time << std::endl;

View File

@@ -6,22 +6,33 @@
// adapted from the example given by Howard Hinnant in
#define BOOST_THREAD_VERSION 4
#include <boost/config.hpp>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <iostream>
#include <boost/thread/scoped_thread.hpp>
#ifdef XXXX
#include <boost/thread/externally_locked_stream.hpp>
typedef boost::externally_locked_stream<std::ostream> the_ostream;
#else
typedef std::ostream the_ostream;
typedef std::istream the_istream;
#endif
#include <boost/thread/sync_queue.hpp>
void producer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
//sbq.push(i);
sbq << i;
mos << "push(" << i << ") "<< sbq.size()<<"\n";
sbq.push_back(i);
//sbq << i;
mos << "push_back(" << i << ") "<< sbq.size()<<"\n";
this_thread::sleep_for(chrono::milliseconds(200));
}
}
@@ -35,16 +46,19 @@ void producer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_qu
}
}
void consumer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
void consumer(
the_ostream &mos,
boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
//sbq.pull(r);
sbq >> r;
sbq.pull_front(r);
//sbq >> r;
mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
@@ -57,17 +71,36 @@ void consumer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_qu
mos << "exception !!!\n";
}
}
void consumer2(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
void consumer2(the_ostream &mos, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
bool closed=false;
for(int i=0; ;++i)
{
int r;
sbq.pull(r, closed);
if (closed) break;
mos << i << " pull(" << r << ")\n";
queue_op_status st = sbq.try_pull_front(r);
if (queue_op_status::closed == st) break;
if (queue_op_status::success == st) {
mos << i << " pull(" << r << ")\n";
}
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
mos << "exception !!!\n";
}
}
void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
queue_op_status res = sbq.wait_pull_front(r);
if (res==queue_op_status::closed) break;
mos << i << " wait_pull_front(" << r << ")\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
@@ -76,43 +109,30 @@ void consumer2(boost::externally_locked_stream<std::ostream> &mos, boost::sync_q
mos << "exception !!!\n";
}
}
//void consumer3(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
//{
// using namespace boost;
// bool closed=false;
// try {
// for(int i=0; ;++i)
// {
// int r;
// queue_op_status res = sbq.wait_and_pull(r);
// if (res==queue_op_status::closed) break;
// mos << i << " wait_and_pull(" << r << ")\n";
// this_thread::sleep_for(chrono::milliseconds(250));
// }
// }
// catch(...)
// {
// mos << "exception !!!\n";
// }
//}
int main()
{
using namespace boost;
#ifdef XXXX
recursive_mutex terminal_mutex;
externally_locked_stream<std::ostream> mcerr(std::cerr, terminal_mutex);
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
#else
the_ostream &mcerr = std::cout;
the_ostream &mcout = std::cerr;
//the_istream &mcin = std::cin;
#endif
sync_queue<int> sbq;
{
mcout << "begin of main" << std::endl;
scoped_thread<> t11(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(thread(consumer, boost::ref(mcout), boost::ref(sbq)));
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq)));
this_thread::sleep_for(chrono::seconds(1));

View File

@@ -0,0 +1,150 @@
// (C) Copyright 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)
// adapted from the example given by Howard Hinnant in
#include <boost/config.hpp>
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <iostream>
#include <boost/thread/scoped_thread.hpp>
#ifdef XXXX
#include <boost/thread/externally_locked_stream.hpp>
typedef boost::externally_locked_stream<std::ostream> the_ostream;
#else
typedef std::ostream the_ostream;
typedef std::istream the_istream;
#endif
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
#include <boost/thread/concurrent_queues/queue_views.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
void producer(the_ostream &mos, boost::queue_back<int> sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
sbq.push(i);
//sbq << i;
mos << "push(" << i << ") " << sbq.size() <<"\n";
this_thread::sleep_for(chrono::milliseconds(200));
}
}
catch(sync_queue_is_closed&)
{
mos << "closed !!!\n";
}
catch(...)
{
mos << "exception !!!\n";
}
}
void consumer(
the_ostream &mos,
boost::queue_front<int> sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
sbq.pull(r);
//sbq >> r;
mos << i << " pull(" << r << ") " << sbq.size() <<"\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(sync_queue_is_closed&)
{
mos << "closed !!!\n";
}
catch(...)
{
mos << "exception !!!\n";
}
}
void consumer2(the_ostream &mos, boost::queue_front<int> sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
queue_op_status st = sbq.try_pull(r);
if (queue_op_status::closed == st) break;
if (queue_op_status::success == st) {
mos << i << " try_pull(" << r << ")\n";
}
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
mos << "exception !!!\n";
}
}
void consumer3(the_ostream &mos, boost::queue_front<int> sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
queue_op_status res = sbq.wait_pull(r);
if (res==queue_op_status::closed) break;
mos << i << " wait_pull(" << r << ")\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
mos << "exception !!!\n";
}
}
int main()
{
using namespace boost;
#ifdef XXXX
recursive_mutex terminal_mutex;
externally_locked_stream<std::ostream> mcerr(std::cerr, terminal_mutex);
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
#else
the_ostream &mcerr = std::cout;
the_ostream &mcout = std::cerr;
//the_istream &mcin = std::cin;
#endif
queue_adaptor<sync_queue<int> > sbq;
{
mcout << "begin of main" << std::endl;
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back<int>(sbq)));
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back<int>(sbq)));
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), concurrent::queue_front<int>(sbq)));
this_thread::sleep_for(chrono::seconds(1));
mcout << "closed()" << std::endl;
sbq.close();
mcout << "closed()" << std::endl;
} // all threads joined here.
mcout << "end of main" << std::endl;
return 0;
}

View File

@@ -6,77 +6,92 @@
// adapted from the example given by Howard Hinnant in
#include <boost/config.hpp>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
//#define XXXX
#include <iostream>
#include <boost/thread/scoped_thread.hpp>
#ifdef XXXX
#include <boost/thread/externally_locked_stream.hpp>
typedef boost::externally_locked_stream<std::ostream> the_ostream;
#else
typedef std::ostream the_ostream;
typedef std::istream the_istream;
#endif
#include <boost/thread/sync_bounded_queue.hpp>
void producer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
void producer(the_ostream &/*mos*/, boost::sync_bounded_queue<int> & sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
//sbq.push(i);
sbq << i;
mos << "push(" << i << ") "<< sbq.size()<<"\n";
sbq.push_back(i);
//sbq << i;
//mos << "push_back(" << i << ") "<< sbq.size()<<"\n";
this_thread::sleep_for(chrono::milliseconds(200));
}
}
catch(sync_queue_is_closed&)
{
mos << "closed !!!\n";
//mos << "closed !!!\n";
}
catch(...)
{
mos << "exception !!!\n";
//mos << "exception !!!\n";
}
}
void consumer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
void consumer(the_ostream &/*mos*/, boost::sync_bounded_queue<int> & sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
//sbq.pull(r);
sbq >> r;
mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
sbq.pull_front(r);
//sbq >> r;
//mos << i << " pull_front(" << r << ") "<< sbq.size()<<"\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(sync_queue_is_closed&)
{
mos << "closed !!!\n";
//mos << "closed !!!\n";
}
catch(...)
{
mos << "exception !!!\n";
//mos << "exception !!!\n";
}
}
void consumer2(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
void consumer2(the_ostream &/*mos*/, boost::sync_bounded_queue<int> & sbq)
{
using namespace boost;
try {
bool closed=false;
for(int i=0; ;++i)
{
int r;
sbq.pull(r, closed);
if (closed) break;
mos << i << " pull(" << r << ")\n";
queue_op_status st = sbq.try_pull_front(r);
if (queue_op_status::closed == st) break;
if (queue_op_status::success == st) {
//mos << i << " pull(" << r << ")\n";
}
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
mos << "exception !!!\n";
//mos << "exception !!!\n";
}
}
//void consumer3(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
//void consumer3(the_ostream &mos, boost::sync_bounded_queue<int> & sbq)
//{
// using namespace boost;
// bool closed=false;
@@ -86,33 +101,38 @@ void consumer2(boost::externally_locked_stream<std::ostream> &mos, boost::sync_b
// int r;
// queue_op_status res = sbq.wait_and_pull(r);
// if (res==queue_op_status::closed) break;
// mos << i << " wait_and_pull(" << r << ")\n";
// //mos << i << " wait_and_pull(" << r << ")\n";
// this_thread::sleep_for(chrono::milliseconds(250));
// }
// }
// catch(...)
// {
// mos << "exception !!!\n";
// //mos << "exception !!!\n";
// }
//}
int main()
{
using namespace boost;
#ifdef XXXX
recursive_mutex terminal_mutex;
externally_locked_stream<std::ostream> mcerr(std::cerr, terminal_mutex);
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
#else
the_ostream &mcerr = std::cout;
the_ostream &mcout = std::cerr;
//the_istream &mcin = std::cin;
#endif
sync_bounded_queue<int> sbq(10);
{
mcout << "begin of main" << std::endl;
scoped_thread<> t11(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(thread(consumer, boost::ref(mcout), boost::ref(sbq)));
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq)));
this_thread::sleep_for(chrono::seconds(1));

View File

@@ -13,6 +13,9 @@ void do_something(int& i)
{
++i;
}
void f(int, int)
{
}
struct func
{
@@ -81,7 +84,10 @@ int main()
do_something_in_current_thread();
}
{
boost::scoped_thread<> g( &f, 1, 2 );
do_something_in_current_thread();
}
return 0;
}

View File

@@ -4,6 +4,9 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#undef BOOST_THREAD_VERSION
#define BOOST_THREAD_VERSION 2
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread_only.hpp>

73
example/thread_pool.cpp Normal file
View File

@@ -0,0 +1,73 @@
// 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)
#include <boost/config.hpp>
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/detail/log.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/assert.hpp>
#include <string>
void p1()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " P1" << BOOST_THREAD_END_LOG;
}
void p2()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " P2" << BOOST_THREAD_END_LOG;
}
void submit_some(boost::basic_thread_pool& tp) {
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
}
int main()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
{
try
{
boost::basic_thread_pool tp;
submit_some(tp);
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << "MAIN>" << BOOST_THREAD_END_LOG;
return 0;
}

View File

@@ -0,0 +1,75 @@
// 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/config.hpp>
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/detail/log.hpp>
#include <boost/thread/executors/loop_executor.hpp>
#include <boost/assert.hpp>
#include <boost/thread/thread_only.hpp>
#include <string>
void p1()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " P1" << BOOST_THREAD_END_LOG;
}
void p2()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " P2" << BOOST_THREAD_END_LOG;
}
void submit_some(boost::loop_executor& tp) {
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
}
int main()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
{
try
{
boost::loop_executor tp;
submit_some(tp);
tp.run_queued_closures();
submit_some(tp);
tp.run_queued_closures();
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << "MAIN>" << BOOST_THREAD_END_LOG;
return 0;
}

View File

@@ -0,0 +1,53 @@
// (C) Copyright 2013 Ruslan Baratov
// 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)
// See www.boost.org/libs/thread for documentation.
#define BOOST_THREAD_VERSION 4
#include <iostream> // std::cout
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/with_lock_guard.hpp>
boost::mutex m; // protection for 'x' and 'std::cout'
int x;
#if defined(BOOST_NO_CXX11_LAMBDAS) || (defined BOOST_MSVC && _MSC_VER < 1700)
void print_x() {
++x;
std::cout << "x = " << x << std::endl;
}
void job() {
for (int i = 0; i < 10; ++i) {
boost::with_lock_guard(m, print_x);
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
}
#else
void job() {
for (int i = 0; i < 10; ++i) {
boost::with_lock_guard(
m,
[]() {
++x;
std::cout << "x = " << x << std::endl;
}
);
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
}
#endif
int main() {
#if defined(BOOST_NO_CXX11_LAMBDAS) || (defined BOOST_MSVC && _MSC_VER < 1700)
std::cout << "(no lambdas)" << std::endl;
#endif
boost::scoped_thread<> thread_1((boost::thread(job)));
boost::scoped_thread<> thread_2((boost::thread(job)));
boost::scoped_thread<> thread_3((boost::thread(job)));
return 0;
}

View File

@@ -1,6 +1,7 @@
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
// Copyright (C) 2007-8 Anthony Williams
// (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)
@@ -17,51 +18,236 @@
#include <boost/thread/condition_variable.hpp>
#include <string>
#include <stdexcept>
#include <boost/thread/detail/nullary_function.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace thread_detail
{
typedef detail::nullary_function<void()> void_completion_function;
typedef detail::nullary_function<size_t()> size_completion_function;
class barrier
struct default_barrier_reseter
{
public:
BOOST_THREAD_NO_COPYABLE( barrier )
unsigned int size_;
default_barrier_reseter(unsigned int size) :
size_(size)
{
}
BOOST_THREAD_MOVABLE(default_barrier_reseter)
//BOOST_THREAD_COPYABLE_AND_MOVABLE(default_barrier_reseter)
barrier(unsigned int count)
: m_threshold(count), m_count(count), m_generation(0)
{
if (count == 0)
boost::throw_exception(thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
}
default_barrier_reseter(default_barrier_reseter const& other) BOOST_NOEXCEPT :
size_(other.size_)
{
}
default_barrier_reseter(BOOST_THREAD_RV_REF(default_barrier_reseter) other) BOOST_NOEXCEPT :
size_(BOOST_THREAD_RV(other).size_)
{
}
bool wait()
{
boost::unique_lock<boost::mutex> lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = m_threshold;
m_cond.notify_all();
return true;
}
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
private:
mutex m_mutex;
condition_variable m_cond;
unsigned int m_threshold;
unsigned int m_count;
unsigned int m_generation;
unsigned int operator()()
{
return size_;
}
};
} // namespace boost
struct void_functor_barrier_reseter
{
unsigned int size_;
void_completion_function fct_;
template <typename F>
void_functor_barrier_reseter(unsigned int size, BOOST_THREAD_RV_REF(F) funct)
: size_(size), fct_(boost::move(funct))
{}
template <typename F>
void_functor_barrier_reseter(unsigned int size, F& funct)
: size_(size), fct_(funct)
{}
BOOST_THREAD_MOVABLE(void_functor_barrier_reseter)
//BOOST_THREAD_COPYABLE_AND_MOVABLE(void_functor_barrier_reseter)
void_functor_barrier_reseter(void_functor_barrier_reseter const& other) BOOST_NOEXCEPT :
size_(other.size_), fct_(other.fct_)
{
}
void_functor_barrier_reseter(BOOST_THREAD_RV_REF(void_functor_barrier_reseter) other) BOOST_NOEXCEPT :
size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
//size_(BOOST_THREAD_RV(other).size_), fct_(boost::move(BOOST_THREAD_RV(other).fct_))
{
}
unsigned int operator()()
{
fct_();
return size_;
}
};
struct void_fct_ptr_barrier_reseter
{
unsigned int size_;
void(*fct_)();
void_fct_ptr_barrier_reseter(unsigned int size, void(*funct)()) :
size_(size), fct_(funct)
{
}
BOOST_THREAD_MOVABLE(void_fct_ptr_barrier_reseter)
//BOOST_THREAD_COPYABLE_AND_MOVABLE(void_fct_ptr_barrier_reseter)
void_fct_ptr_barrier_reseter(void_fct_ptr_barrier_reseter const& other) BOOST_NOEXCEPT :
size_(other.size_), fct_(other.fct_)
{
}
void_fct_ptr_barrier_reseter(BOOST_THREAD_RV_REF(void_fct_ptr_barrier_reseter) other) BOOST_NOEXCEPT :
size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
{
}
unsigned int operator()()
{
fct_();
return size_;
}
};
}
//BOOST_THREAD_DCL_MOVABLE(thread_detail::default_barrier_reseter)
//BOOST_THREAD_DCL_MOVABLE(thread_detail::void_functor_barrier_reseter)
//BOOST_THREAD_DCL_MOVABLE(thread_detail::void_fct_ptr_barrier_reseter)
class barrier
{
static inline unsigned int check_counter(unsigned int count)
{
if (count == 0) boost::throw_exception(
thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
return count;
}
struct dummy
{
};
public:
BOOST_THREAD_NO_COPYABLE( barrier)
explicit barrier(unsigned int count) :
m_count(check_counter(count)), m_generation(0), fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count)))
{
}
template <typename F>
barrier(
unsigned int count,
BOOST_THREAD_RV_REF(F) funct,
typename enable_if<
typename is_void<typename result_of<F>::type>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
m_generation(0),
fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count,
boost::move(funct)))
)
{
}
template <typename F>
barrier(
unsigned int count,
F &funct,
typename enable_if<
typename is_void<typename result_of<F>::type>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
m_generation(0),
fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count,
funct))
)
{
}
template <typename F>
barrier(
unsigned int count,
BOOST_THREAD_RV_REF(F) funct,
typename enable_if<
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
m_generation(0),
fct_(boost::move(funct))
{
}
template <typename F>
barrier(
unsigned int count,
F& funct,
typename enable_if<
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
m_generation(0),
fct_(funct)
{
}
barrier(unsigned int count, void(*funct)()) :
m_count(check_counter(count)), m_generation(0),
fct_(funct
? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_fct_ptr_barrier_reseter(count, funct))))
: BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))))
)
{
}
barrier(unsigned int count, unsigned int(*funct)()) :
m_count(check_counter(count)), m_generation(0),
fct_(funct
? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(funct))
: BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))))
)
{
}
bool wait()
{
boost::unique_lock < boost::mutex > lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = static_cast<unsigned int>(fct_());
BOOST_ASSERT(m_count != 0);
m_cond.notify_all();
return true;
}
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
void count_down_and_wait()
{
wait();
}
private:
mutex m_mutex;
condition_variable m_cond;
unsigned int m_count;
unsigned int m_generation;
thread_detail::size_completion_function fct_;
};
} // namespace boost
#include <boost/config/abi_suffix.hpp>

View File

@@ -0,0 +1,56 @@
// (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)
#ifndef BOOST_THREAD_CALL_CONTEXT_HPP
#define BOOST_THREAD_CALL_CONTEXT_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/thread.hpp>
#endif
#include <boost/current_function.hpp>
#include <iomanip>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
struct caller_context_t
{
const char * filename;
unsigned lineno;
const char * func;
caller_context_t(const char * filename, unsigned lineno, const char * func) :
filename(filename), lineno(lineno), func(func)
{
}
};
#define BOOST_CONTEXTOF boost::caller_context_t(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION)
template <typename OStream>
OStream& operator<<(OStream& os, caller_context_t const& ctx)
{
#if defined BOOST_THREAD_USES_LOG_THREAD_ID
{
io::ios_flags_saver ifs( os );
os << std::left << std::setw(14) << boost::this_thread::get_id() << " ";
}
#endif
{
io::ios_flags_saver ifs(os);
os << ctx.filename << "["
<< std::setw(4) << std::right << std::dec<< ctx.lineno << "] ";
os << ctx.func << " " ;
}
return os;
}
}
#include <boost/config/abi_suffix.hpp>
#endif // header

View File

@@ -16,12 +16,8 @@
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <boost/assert.hpp>
#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
#include <boost/function.hpp>
#else
#include <functional>
#endif
//#include <boost/thread/latch.hpp>
//#include <boost/thread/detail/nullary_function.hpp>
#include <boost/thread/csbl/functional.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -37,11 +33,8 @@ namespace boost
{
public:
/// the implementation defined completion function type
#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
typedef function<void()> completion_function;
#else
typedef std::function<void()> completion_function;
#endif
//typedef detail::nullary_function<void()> completion_function;
typedef csbl::function<void()> completion_function;
/// noop completion function factory
static completion_function noop()
{

View File

@@ -0,0 +1,223 @@
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_QUEUE_BASE_HPP
#define BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_QUEUE_BASE_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the 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 http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/throw_exception.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <class ValueType, class Queue>
class sync_queue_base
{
public:
typedef ValueType value_type;
typedef Queue underlying_queue_type;
typedef std::size_t size_type;
typedef queue_op_status op_status;
typedef typename chrono::steady_clock clock;
typedef typename clock::duration duration;
typedef typename clock::time_point time_point;
// Constructors/Assignment/Destructors
BOOST_THREAD_NO_COPYABLE(sync_queue_base)
inline sync_queue_base();
//template <typename Range>
//inline explicit sync_queue(Range range);
inline ~sync_queue_base();
// Observers
inline bool empty() const;
inline bool full() const;
inline size_type size() const;
inline bool closed() const;
// Modifiers
inline void close();
inline underlying_queue_type underlying_queue() {
lock_guard<mutex> lk(mtx_);
return boost::move(data_);
}
protected:
mutable mutex mtx_;
condition_variable not_empty_;
underlying_queue_type data_;
bool closed_;
inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
{
return data_.empty();
}
inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
{
return data_.empty();
}
inline size_type size(lock_guard<mutex>& ) const BOOST_NOEXCEPT
{
return data_.size();
}
inline bool closed(unique_lock<mutex>& lk) const;
inline bool closed(lock_guard<mutex>& lk) const;
inline void throw_if_closed(unique_lock<mutex>&);
inline void throw_if_closed(lock_guard<mutex>&);
inline void wait_until_not_empty(unique_lock<mutex>& lk);
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
inline queue_op_status wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&);
inline void notify_not_empty_if_needed(unique_lock<mutex>& )
{
not_empty_.notify_one();
}
inline void notify_not_empty_if_needed(lock_guard<mutex>& )
{
not_empty_.notify_one();
}
};
template <class ValueType, class Queue>
sync_queue_base<ValueType, Queue>::sync_queue_base() :
data_(), closed_(false)
{
BOOST_ASSERT(data_.empty());
}
template <class ValueType, class Queue>
sync_queue_base<ValueType, Queue>::~sync_queue_base()
{
}
template <class ValueType, class Queue>
void sync_queue_base<ValueType, Queue>::close()
{
{
lock_guard<mutex> lk(mtx_);
closed_ = true;
}
not_empty_.notify_all();
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::closed() const
{
lock_guard<mutex> lk(mtx_);
return closed(lk);
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::closed(unique_lock<mutex>&) const
{
return closed_;
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::closed(lock_guard<mutex>&) const
{
return closed_;
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::empty() const
{
lock_guard<mutex> lk(mtx_);
return empty(lk);
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::full() const
{
return false;
}
template <class ValueType, class Queue>
typename sync_queue_base<ValueType, Queue>::size_type sync_queue_base<ValueType, Queue>::size() const
{
lock_guard<mutex> lk(mtx_);
return size(lk);
}
template <class ValueType, class Queue>
void sync_queue_base<ValueType, Queue>::throw_if_closed(unique_lock<mutex>& lk)
{
if (closed(lk))
{
BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
}
template <class ValueType, class Queue>
void sync_queue_base<ValueType, Queue>::throw_if_closed(lock_guard<mutex>& lk)
{
if (closed(lk))
{
BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
}
template <class ValueType, class Queue>
void sync_queue_base<ValueType, Queue>::wait_until_not_empty(unique_lock<mutex>& lk)
{
for (;;)
{
if (! empty(lk)) break;
throw_if_closed(lk);
not_empty_.wait(lk);
}
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk)
{
for (;;)
{
if (! empty(lk)) break;
if (closed(lk)) return true;
not_empty_.wait(lk);
}
return false;
}
template <class ValueType, class Queue>
queue_op_status sync_queue_base<ValueType, Queue>::wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&tp)
{
for (;;)
{
if (! empty(lk)) return queue_op_status::success;
throw_if_closed(lk);
if (not_empty_.wait_until(lk, tp) == cv_status::timeout ) return queue_op_status::timeout;
}
}
} // detail
} // concurrent
} // boost
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,209 @@
#ifndef BOOST_THREAD_QUEUE_ADAPTOR_HPP
#define BOOST_THREAD_QUEUE_ADAPTOR_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the 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 http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/concurrent_queues/queue_base.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <typename Queue>
class queue_adaptor_copyable_only :
public boost::queue_base<typename Queue::value_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
queue_adaptor_copyable_only() {}
// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }
// Modifiers
void close() { queue.close(); }
void push_back(const value_type& x) { queue.push_back(x); }
void pull_front(value_type& x) { queue.pull_front(x); };
value_type pull_front() { return queue.pull_front(); }
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
};
template <typename Queue>
class queue_adaptor_movable_only :
public boost::queue_base<typename Queue::value_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
queue_adaptor_movable_only() {}
// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }
// Modifiers
void close() { queue.close(); }
void pull_front(value_type& x) { queue.pull_front(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull_front() { return queue.pull_front(); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
};
template <typename Queue>
class queue_adaptor_copyable_and_movable :
public boost::queue_base<typename Queue::value_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
queue_adaptor_copyable_and_movable() {}
// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }
// Modifiers
void close() { queue.close(); }
void push_back(const value_type& x) { queue.push_back(x); }
void pull_front(value_type& x) { queue.pull_front(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull_front() { return queue.pull_front(); }
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
};
template <class Q, class T,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // __GNUC__
#elif defined _MSC_VER
#if _MSC_VER < 1700
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // _MSC_VER
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif
#else
bool Copyable = is_copy_constructible<T>::value,
bool Movable = has_move_emulation_enabled<T>::value
#endif
>
struct queue_adaptor;
template <class Q, class T>
struct queue_adaptor<Q, T, true, true> {
typedef queue_adaptor_copyable_and_movable<Q> type;
};
template <class Q, class T>
struct queue_adaptor<Q, T, true, false> {
typedef queue_adaptor_copyable_only<Q> type;
};
template <class Q, class T>
struct queue_adaptor<Q, T, false, true> {
typedef queue_adaptor_movable_only<Q> type;
};
}
template <typename Queue>
class queue_adaptor :
public detail::queue_adaptor<Queue, typename Queue::value_type>::type
{
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
virtual ~queue_adaptor() {};
};
}
using concurrent::queue_adaptor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,202 @@
#ifndef BOOST_THREAD_QUEUE_BASE_HPP
#define BOOST_THREAD_QUEUE_BASE_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the 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 http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/type_traits/is_copy_constructible.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <typename ValueType>
class queue_base_copyable_only
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_copyable_only() {};
// Observers
virtual bool empty() const = 0;
virtual bool full() const = 0;
virtual size_type size() const = 0;
virtual bool closed() const = 0;
// Modifiers
virtual void close() = 0;
virtual void push_back(const value_type& x) = 0;
virtual void pull_front(value_type&) = 0;
virtual value_type pull_front() = 0;
virtual queue_op_status try_push_back(const value_type& x) = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
};
template <typename ValueType>
class queue_base_movable_only
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_movable_only() {};
// Observers
virtual bool empty() const = 0;
virtual bool full() const = 0;
virtual size_type size() const = 0;
virtual bool closed() const = 0;
// Modifiers
virtual void close() = 0;
virtual void pull_front(value_type&) = 0;
// enable_if is_nothrow_movable<value_type>
virtual value_type pull_front() = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
};
template <typename ValueType>
class queue_base_copyable_and_movable
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_copyable_and_movable() {};
// Observers
virtual bool empty() const = 0;
virtual bool full() const = 0;
virtual size_type size() const = 0;
virtual bool closed() const = 0;
// Modifiers
virtual void close() = 0;
virtual void push_back(const value_type& x) = 0;
virtual void pull_front(value_type&) = 0;
// enable_if is_nothrow_copy_movable<value_type>
virtual value_type pull_front() = 0;
virtual queue_op_status try_push_back(const value_type& x) = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
};
template <class T,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // __GNUC__
#elif defined _MSC_VER
#if _MSC_VER < 1700
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // _MSC_VER
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif
#else
bool Copyable = is_copy_constructible<T>::value,
bool Movable = has_move_emulation_enabled<T>::value
#endif
>
struct queue_base;
template <class T>
struct queue_base<T, true, true> {
typedef queue_base_copyable_and_movable<T> type;
};
template <class T>
struct queue_base<T, true, false> {
typedef queue_base_copyable_only<T> type;
};
template <class T>
struct queue_base<T, false, true> {
typedef queue_base_movable_only<T> type;
};
}
template <typename ValueType>
class queue_base :
public detail::queue_base<ValueType>::type
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base() {};
};
}
using concurrent::queue_base;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,46 @@
#ifndef BOOST_THREAD_QUEUE_OP_STATUS_HPP
#define BOOST_THREAD_QUEUE_OP_STATUS_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the 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 http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
BOOST_SCOPED_ENUM_DECLARE_BEGIN(queue_op_status)
{ success = 0, empty, full, closed, busy, timeout, not_ready }
BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)
struct sync_queue_is_closed : std::exception
{
};
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
struct no_block_tag{};
BOOST_CONSTEXPR_OR_CONST no_block_tag no_block = {};
#endif
using concurrent::queue_op_status;
using concurrent::sync_queue_is_closed;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,165 @@
#ifndef BOOST_THREAD_QUEUE_VIEWS_HPP
#define BOOST_THREAD_QUEUE_VIEWS_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the 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 http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/concurrent_queues/queue_base.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
template <typename Queue>
class queue_back_view
{
Queue* queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_back_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
// Observers
bool empty() const { return queue->empty(); }
bool full() const { return queue->full(); }
size_type size() const { return queue->size(); }
bool closed() const { return queue->closed(); }
// Modifiers
void close() { queue->close(); }
void push(const value_type& x) { queue->push_back(x); }
void pull(value_type& x) { queue->pull_back(x); }
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue->pull_back(); }
queue_op_status try_push(const value_type& x) { return queue->try_push_back(x); }
queue_op_status try_pull(value_type& x) { return queue->try_pull_back(x); }
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_back(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_back(x); }
queue_op_status wait_push(const value_type& x) { return queue->wait_push_back(x); }
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_back(x); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_back(boost::move(x)); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_back(boost::move(x)); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_back(boost::move(x)); }
};
template <typename Queue>
class queue_front_view
{
Queue* queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_front_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
// Observers
bool empty() const { return queue->empty(); }
bool full() const { return queue->full(); }
size_type size() const { return queue->size(); }
bool closed() const { return queue->closed(); }
// Modifiers
void close() { queue->close(); }
void push(const value_type& x) { queue->push_front(x); }
void pull(value_type& x) { queue->pull_front(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue->pull_front(); }
queue_op_status try_push(const value_type& x) { return queue->try_push_front(x); }
queue_op_status try_pull(value_type& x) { return queue->try_pull_front(x); }
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_front(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_front(x); }
queue_op_status wait_push(const value_type& x) { return queue->wait_push_front(x); }
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_front(x); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_front(forward<value_type>(x)); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_front(forward<value_type>(x)); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_front(forward<value_type>(x)); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_front(forward<value_type>(x)); }
};
#if ! defined BOOST_NO_CXX11_TEMPLATE_ALIASES
template <class T>
using queue_back = queue_back_view<queue_base<T> > ;
template <class T>
using queue_front = queue_front_view<queue_base<T> > ;
#else
template <class T>
struct queue_back : queue_back_view<queue_base<T> >
{
typedef queue_back_view<queue_base<T> > base_type;
queue_back(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
};
template <class T>
struct queue_front : queue_front_view<queue_base<T> >
{
typedef queue_front_view<queue_base<T> > base_type;
queue_front(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
};
#endif
// template <class Queue>
// queue_back_view<Queue> back(Queue & q) { return queue_back_view<Queue>(q); }
// template <class Queue>
// queue_front_view<Queue> front(Queue & q) { return queue_front_view<Queue>(q); }
//#if 0
// template <class T>
// queue_back<T> back(queue_base<T> & q) { return queue_back<T>(q); }
// template <class T>
// queue_front<T> front(queue_base<T> & q) { return queue_front<T>(q); }
//#else
// template <class T>
// typename queue_back<T>::type back(queue_base<T> & q) { return typename queue_back<T>::type(q); }
// template <class T>
// typename queue_front<T>::type front(queue_base<T> & q) { return typename queue_front<T>::type(q); }
//#endif
}
using concurrent::queue_back_view;
using concurrent::queue_front_view;
using concurrent::queue_back;
using concurrent::queue_front;
//using concurrent::back;
//using concurrent::front;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,725 @@
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_BOUNDED_QUEUE_HPP
#define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_BOUNDED_QUEUE_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the 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 http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/throw_exception.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
template <typename ValueType>
class sync_bounded_queue
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
BOOST_THREAD_NO_COPYABLE(sync_bounded_queue)
explicit sync_bounded_queue(size_type max_elems);
template <typename Range>
sync_bounded_queue(size_type max_elems, Range range);
~sync_bounded_queue();
// Observers
inline bool empty() const;
inline bool full() const;
inline size_type capacity() const;
inline size_type size() const;
inline bool closed() const;
// Modifiers
inline void close();
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void push(const value_type& x);
inline void push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(const value_type& x);
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(no_block_tag, const value_type& x);
inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
#endif
inline void push_back(const value_type& x);
inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status try_push_back(const value_type& x);
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status nonblocking_push_back(const value_type& x);
inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status wait_push_back(const value_type& x);
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
// Observers/Modifiers
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void pull(value_type&);
// enable_if is_nothrow_copy_movable<value_type>
inline value_type pull();
inline shared_ptr<ValueType> ptr_pull();
inline bool try_pull(value_type&);
inline bool try_pull(no_block_tag,value_type&);
inline shared_ptr<ValueType> try_pull();
#endif
inline void pull_front(value_type&);
// enable_if is_nothrow_copy_movable<value_type>
inline value_type pull_front();
inline queue_op_status try_pull_front(value_type&);
inline queue_op_status nonblocking_pull_front(value_type&);
inline queue_op_status wait_pull_front(ValueType& elem);
private:
mutable mutex mtx_;
condition_variable not_empty_;
condition_variable not_full_;
size_type waiting_full_;
size_type waiting_empty_;
value_type* data_;
size_type in_;
size_type out_;
size_type capacity_;
bool closed_;
inline size_type inc(size_type idx) const BOOST_NOEXCEPT
{
return (idx + 1) % capacity_;
}
inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
{
return in_ == out_;
}
inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
{
return in_ == out_;
}
inline bool full(unique_lock<mutex>& ) const BOOST_NOEXCEPT
{
return (inc(in_) == out_);
}
inline bool full(lock_guard<mutex>& ) const BOOST_NOEXCEPT
{
return (inc(in_) == out_);
}
inline size_type capacity(lock_guard<mutex>& ) const BOOST_NOEXCEPT
{
return capacity_-1;
}
inline size_type size(lock_guard<mutex>& lk) const BOOST_NOEXCEPT
{
if (full(lk)) return capacity(lk);
return ((out_+capacity(lk)-in_) % capacity(lk));
}
inline void throw_if_closed(unique_lock<mutex>&);
inline bool closed(unique_lock<mutex>&) const;
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
#endif
inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline void wait_until_not_empty(unique_lock<mutex>& lk);
inline void wait_until_not_empty(unique_lock<mutex>& lk, bool&);
inline size_type wait_until_not_full(unique_lock<mutex>& lk);
inline size_type wait_until_not_full(unique_lock<mutex>& lk, bool&);
inline void notify_not_empty_if_needed(unique_lock<mutex>& lk)
{
if (waiting_empty_ > 0)
{
--waiting_empty_;
lk.unlock();
not_empty_.notify_one();
}
}
inline void notify_not_full_if_needed(unique_lock<mutex>& lk)
{
if (waiting_full_ > 0)
{
--waiting_full_;
lk.unlock();
not_full_.notify_one();
}
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void pull(value_type& elem, unique_lock<mutex>& lk)
{
elem = boost::move(data_[out_]);
out_ = inc(out_);
notify_not_full_if_needed(lk);
}
inline value_type pull(unique_lock<mutex>& lk)
{
value_type elem = boost::move(data_[out_]);
out_ = inc(out_);
notify_not_full_if_needed(lk);
return boost::move(elem);
}
inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& lk)
{
shared_ptr<value_type> res = make_shared<value_type>(boost::move(data_[out_]));
out_ = inc(out_);
notify_not_full_if_needed(lk);
return res;
}
#endif
inline void pull_front(value_type& elem, unique_lock<mutex>& lk)
{
elem = boost::move(data_[out_]);
out_ = inc(out_);
notify_not_full_if_needed(lk);
}
inline value_type pull_front(unique_lock<mutex>& lk)
{
value_type elem = boost::move(data_[out_]);
out_ = inc(out_);
notify_not_full_if_needed(lk);
return boost::move(elem);
}
inline void set_in(size_type in, unique_lock<mutex>& lk)
{
in_ = in;
notify_not_empty_if_needed(lk);
}
inline void push_at(const value_type& elem, size_type in_p_1, unique_lock<mutex>& lk)
{
data_[in_] = elem;
set_in(in_p_1, lk);
}
inline void push_at(BOOST_THREAD_RV_REF(value_type) elem, size_type in_p_1, unique_lock<mutex>& lk)
{
data_[in_] = boost::move(elem);
set_in(in_p_1, lk);
}
};
template <typename ValueType>
sync_bounded_queue<ValueType>::sync_bounded_queue(typename sync_bounded_queue<ValueType>::size_type max_elems) :
waiting_full_(0), waiting_empty_(0), data_(new value_type[max_elems + 1]), in_(0), out_(0), capacity_(max_elems + 1),
closed_(false)
{
BOOST_ASSERT_MSG(max_elems >= 1, "number of elements must be > 1");
}
// template <typename ValueType>
// template <typename Range>
// sync_bounded_queue<ValueType>::sync_bounded_queue(size_type max_elems, Range range) :
// waiting_full_(0), waiting_empty_(0), data_(new value_type[max_elems + 1]), in_(0), out_(0), capacity_(max_elems + 1),
// closed_(false)
// {
// BOOST_ASSERT_MSG(max_elems >= 1, "number of elements must be > 1");
// BOOST_ASSERT_MSG(max_elems == size(range), "number of elements must match range's size");
// try
// {
// typedef typename Range::iterator iterator_t;
// iterator_t first = boost::begin(range);
// iterator_t end = boost::end(range);
// size_type in = 0;
// for (iterator_t cur = first; cur != end; ++cur, ++in)
// {
// data_[in] = *cur;
// }
// set_in(in);
// }
// catch (...)
// {
// delete[] data_;
// }
// }
template <typename ValueType>
sync_bounded_queue<ValueType>::~sync_bounded_queue()
{
delete[] data_;
}
template <typename ValueType>
void sync_bounded_queue<ValueType>::close()
{
{
lock_guard<mutex> lk(mtx_);
closed_ = true;
}
not_empty_.notify_all();
not_full_.notify_all();
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::closed() const
{
lock_guard<mutex> lk(mtx_);
return closed_;
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::closed(unique_lock<mutex>& ) const
{
return closed_;
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::empty() const
{
lock_guard<mutex> lk(mtx_);
return empty(lk);
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::full() const
{
lock_guard<mutex> lk(mtx_);
return full(lk);
}
template <typename ValueType>
typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::capacity() const
{
lock_guard<mutex> lk(mtx_);
return capacity(lk);
}
template <typename ValueType>
typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::size() const
{
lock_guard<mutex> lk(mtx_);
return size(lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
{
if (empty(lk))
{
throw_if_closed(lk);
return false;
}
pull(elem, lk);
return true;
}
template <typename ValueType>
shared_ptr<ValueType> sync_bounded_queue<ValueType>::try_pull(unique_lock<mutex>& lk)
{
if (empty(lk))
{
throw_if_closed(lk);
return shared_ptr<ValueType>();
}
return ptr_pull(lk);
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_pull(ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return try_pull(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (empty(lk))
{
if (closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull_front(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return try_pull_front(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_pull(no_block_tag,ValueType& elem)
{
unique_lock<mutex> lk(mtx_, try_to_lock);
if (!lk.owns_lock())
{
return false;
}
return try_pull(elem, lk);
}
template <typename ValueType>
boost::shared_ptr<ValueType> sync_bounded_queue<ValueType>::try_pull()
{
unique_lock<mutex> lk(mtx_);
return try_pull(lk);
}
#endif
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::nonblocking_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_pull_front(elem, lk);
}
template <typename ValueType>
void sync_bounded_queue<ValueType>::throw_if_closed(unique_lock<mutex>&)
{
if (closed_)
{
BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
}
template <typename ValueType>
void sync_bounded_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk)
{
for (;;)
{
if (out_ != in_) break;
throw_if_closed(lk);
++waiting_empty_;
not_empty_.wait(lk);
}
}
template <typename ValueType>
void sync_bounded_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk, bool & closed)
{
for (;;)
{
if (out_ != in_) break;
if (closed_) {closed=true; return;}
++waiting_empty_;
not_empty_.wait(lk);
}
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_bounded_queue<ValueType>::pull(ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
pull(elem, lk);
}
// template <typename ValueType>
// void sync_bounded_queue<ValueType>::pull(ValueType& elem, bool & closed)
// {
// unique_lock<mutex> lk(mtx_);
// wait_until_not_empty(lk, closed);
// if (closed) {return;}
// pull(elem, lk);
// }
// enable if ValueType is nothrow movable
template <typename ValueType>
ValueType sync_bounded_queue<ValueType>::pull()
{
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
return pull(lk);
}
template <typename ValueType>
boost::shared_ptr<ValueType> sync_bounded_queue<ValueType>::ptr_pull()
{
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
return ptr_pull(lk);
}
#endif
template <typename ValueType>
void sync_bounded_queue<ValueType>::pull_front(ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
pull_front(elem, lk);
}
// enable if ValueType is nothrow movable
template <typename ValueType>
ValueType sync_bounded_queue<ValueType>::pull_front()
{
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
return pull_front(lk);
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (empty(lk) && closed(lk)) {return queue_op_status::closed;}
wait_until_not_empty(lk);
pull_front(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return wait_pull_front(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
{
throw_if_closed(lk);
size_type in_p_1 = inc(in_);
if (in_p_1 == out_) // full()
{
return false;
}
push_at(elem, in_p_1, lk);
return true;
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return try_push(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
{
if (closed(lk)) return queue_op_status::closed;
size_type in_p_1 = inc(in_);
if (in_p_1 == out_) // full()
{
return queue_op_status::full;
}
push_at(elem, in_p_1, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return try_push_back(elem, lk);
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
{
if (closed(lk)) return queue_op_status::closed;
push_at(elem, wait_until_not_full(lk), lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return wait_push_back(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(no_block_tag, const ValueType& elem)
{
unique_lock<mutex> lk(mtx_, try_to_lock);
if (!lk.owns_lock()) return false;
return try_push(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::nonblocking_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_, try_to_lock);
if (!lk.owns_lock()) return queue_op_status::busy;
return try_push_back(elem, lk);
}
template <typename ValueType>
typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::wait_until_not_full(unique_lock<mutex>& lk)
{
for (;;)
{
throw_if_closed(lk);
size_type in_p_1 = inc(in_);
if (in_p_1 != out_) // ! full()
{
return in_p_1;
}
++waiting_full_;
not_full_.wait(lk);
}
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_bounded_queue<ValueType>::push(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
push_at(elem, wait_until_not_full(lk), lk);
}
#endif
template <typename ValueType>
void sync_bounded_queue<ValueType>::push_back(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
push_at(elem, wait_until_not_full(lk), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
throw_if_closed(lk);
size_type in_p_1 = inc(in_);
if (in_p_1 == out_) // full()
{
return false;
}
push_at(boost::move(elem), in_p_1, lk);
return true;
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_);
return try_push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (closed(lk)) return queue_op_status::closed;
size_type in_p_1 = inc(in_);
if (in_p_1 == out_) // full()
{
return queue_op_status::full;
}
push_at(boost::move(elem), in_p_1, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_);
return try_push_back(boost::move(elem), lk);
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (closed(lk)) return queue_op_status::closed;
push_at(boost::move(elem), wait_until_not_full(lk), lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_);
return try_push_back(boost::move(elem), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_, try_to_lock);
if (!lk.owns_lock())
{
return false;
}
return try_push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_push_back(boost::move(elem), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_bounded_queue<ValueType>::push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_);
push_at(boost::move(elem), wait_until_not_full(lk), lk);
}
#endif
template <typename ValueType>
void sync_bounded_queue<ValueType>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_);
push_at(boost::move(elem), wait_until_not_full(lk), lk);
}
template <typename ValueType>
sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
{
sbq.push_back(boost::move(elem));
return sbq;
}
template <typename ValueType>
sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, ValueType const&elem)
{
sbq.push_back(elem);
return sbq;
}
template <typename ValueType>
sync_bounded_queue<ValueType>& operator>>(sync_bounded_queue<ValueType>& sbq, ValueType &elem)
{
sbq.pull_front(elem);
return sbq;
}
}
using concurrent::sync_bounded_queue;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,362 @@
// 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)
//
#ifndef BOOST_THREAD_SYNC_PRIORITY_QUEUE
#define BOOST_THREAD_SYNC_PRIORITY_QUEUE
#include <boost/thread/detail/config.hpp>
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/csbl/vector.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/atomic.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <exception>
#include <queue>
#include <utility>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail {
template <
class Type,
class Container = csbl::vector<Type>,
class Compare = std::less<Type>
>
class priority_queue
{
private:
std::vector<Type> _elements;
Compare _compare;
public:
explicit priority_queue(const Compare& compare = Compare())
: _elements(), _compare(compare)
{ }
std::size_t size() const
{
return _elements.size();
}
bool empty() const
{
return _elements.empty();
}
void push(Type const& element)
{
_elements.push_back(element);
std::push_heap(_elements.begin(), _elements.end(), _compare);
}
void push(BOOST_RV_REF(Type) element)
{
_elements.push_back(boost::move(element));
std::push_heap(_elements.begin(), _elements.end(), _compare);
}
Type pull()
{
std::pop_heap(_elements.begin(), _elements.end(), _compare);
Type result = boost::move(_elements.back());
_elements.pop_back();
return boost::move(result);
}
Type const& top()
{
return _elements.back();
}
};
}
namespace concurrent
{
template <class ValueType,
class Container = csbl::vector<ValueType>,
class Compare = std::less<typename Container::value_type> >
class sync_priority_queue
: public detail::sync_queue_base<ValueType, boost::detail::priority_queue<ValueType,Container,Compare> >
{
typedef detail::sync_queue_base<ValueType, boost::detail::priority_queue<ValueType,Container,Compare> > super;
public:
typedef ValueType value_type;
//typedef typename super::value_type value_type; // fixme
typedef typename super::underlying_queue_type underlying_queue_type;
typedef typename super::size_type size_type;
typedef typename super::op_status op_status;
typedef chrono::steady_clock clock;
protected:
public:
sync_priority_queue() {}
~sync_priority_queue()
{
if(!super::closed())
{
super::close();
}
}
void push(const ValueType& elem);
void push(BOOST_THREAD_RV_REF(ValueType) elem);
queue_op_status try_push(const ValueType& elem);
queue_op_status try_push(BOOST_THREAD_RV_REF(ValueType) elem);
ValueType pull();
void pull(ValueType&);
queue_op_status pull_until(const clock::time_point&, ValueType&);
queue_op_status pull_for(const clock::duration&, ValueType&);
queue_op_status try_pull(ValueType& elem);
queue_op_status wait_pull(ValueType& elem);
queue_op_status nonblocking_pull(ValueType&);
private:
void push(unique_lock<mutex>&, const ValueType& elem);
void push(lock_guard<mutex>&, const ValueType& elem);
void push(unique_lock<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem);
void push(lock_guard<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem);
queue_op_status try_push(unique_lock<mutex>&, const ValueType& elem);
queue_op_status try_push(unique_lock<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem);
ValueType pull(unique_lock<mutex>&);
ValueType pull(lock_guard<mutex>&);
void pull(unique_lock<mutex>&, ValueType&);
void pull(lock_guard<mutex>&, ValueType&);
queue_op_status try_pull(lock_guard<mutex>& lk, ValueType& elem);
queue_op_status try_pull(unique_lock<mutex>& lk, ValueType& elem);
queue_op_status wait_pull(unique_lock<mutex>& lk, ValueType& elem);
queue_op_status nonblocking_pull(unique_lock<mutex>& lk, ValueType&);
sync_priority_queue(const sync_priority_queue&);
sync_priority_queue& operator= (const sync_priority_queue&);
sync_priority_queue(BOOST_THREAD_RV_REF(sync_priority_queue));
sync_priority_queue& operator= (BOOST_THREAD_RV_REF(sync_priority_queue));
}; //end class
//////////////////////
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(unique_lock<mutex>& lk, const T& elem)
{
super::throw_if_closed(lk);
super::data_.push(elem);
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, const T& elem)
{
super::throw_if_closed(lk);
super::data_.push(elem);
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(const T& elem)
{
lock_guard<mutex> lk(super::mtx_);
push(lk, elem);
}
//////////////////////
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(unique_lock<mutex>& lk, BOOST_THREAD_RV_REF(T) elem)
{
super::throw_if_closed(lk);
super::data_.push(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, BOOST_THREAD_RV_REF(T) elem)
{
super::throw_if_closed(lk);
super::data_.push(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(BOOST_THREAD_RV_REF(T) elem)
{
lock_guard<mutex> lk(super::mtx_);
push(lk, boost::move(elem));
}
//////////////////////
template <class T, class Container,class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::try_push(const T& elem)
{
lock_guard<mutex> lk(super::mtx_);
if (super::closed(lk)) return queue_op_status::closed;
push(lk, elem);
return queue_op_status::success;
}
//////////////////////
template <class T, class Container,class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::try_push(BOOST_THREAD_RV_REF(T) elem)
{
lock_guard<mutex> lk(super::mtx_);
if (super::closed(lk)) return queue_op_status::closed;
push(lk, boost::move(elem));
return queue_op_status::success;
}
//////////////////////
template <class T,class Container, class Cmp>
T sync_priority_queue<T,Container,Cmp>::pull(unique_lock<mutex>&)
{
return super::data_.pull();
}
template <class T,class Container, class Cmp>
T sync_priority_queue<T,Container,Cmp>::pull(lock_guard<mutex>&)
{
return super::data_.pull();
}
template <class T,class Container, class Cmp>
T sync_priority_queue<T,Container,Cmp>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull(lk);
}
//////////////////////
template <class T,class Container, class Cmp>
void sync_priority_queue<T,Container,Cmp>::pull(unique_lock<mutex>&, T& elem)
{
elem = super::data_.pull();
}
template <class T,class Container, class Cmp>
void sync_priority_queue<T,Container,Cmp>::pull(lock_guard<mutex>&, T& elem)
{
elem = super::data_.pull();
}
template <class T,class Container, class Cmp>
void sync_priority_queue<T,Container,Cmp>::pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
pull(lk, elem);
}
//////////////////////
template <class T, class Cont,class Cmp>
queue_op_status
sync_priority_queue<T,Cont,Cmp>::pull_until(const clock::time_point& tp, T& elem)
{
unique_lock<mutex> lk(super::mtx_);
if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp))
return queue_op_status::timeout;
pull(lk, elem);
return queue_op_status::success;
}
//////////////////////
template <class T, class Cont,class Cmp>
queue_op_status
sync_priority_queue<T,Cont,Cmp>::pull_for(const clock::duration& dura, T& elem)
{
return pull_until(clock::now() + dura, elem);
}
//////////////////////
template <class T, class Container,class Cmp>
queue_op_status
sync_priority_queue<T,Container,Cmp>::try_pull(unique_lock<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull(lk, elem);
return queue_op_status::success;
}
template <class T, class Container,class Cmp>
queue_op_status
sync_priority_queue<T,Container,Cmp>::try_pull(lock_guard<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull(lk, elem);
return queue_op_status::success;
}
template <class T, class Container,class Cmp>
queue_op_status
sync_priority_queue<T,Container,Cmp>::try_pull(T& elem)
{
lock_guard<mutex> lk(super::mtx_);
return try_pull(lk, elem);
}
//////////////////////
template <class T,class Container, class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::wait_pull(unique_lock<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
}
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
pull(lk, elem);
return queue_op_status::success;
}
template <class T,class Container, class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::wait_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_pull(lk, elem);
}
//////////////////////
template <class T,class Container, class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::nonblocking_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock()) return queue_op_status::busy;
return try_pull(lk, elem);
}
} //end concurrent namespace
using concurrent::sync_priority_queue;
} //end boost namespace
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,544 @@
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_QUEUE_HPP
#define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_QUEUE_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the 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 http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/csbl/deque.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
template <typename ValueType>
class sync_queue
: public detail::sync_queue_base<ValueType, csbl::deque<ValueType> >
{
typedef detail::sync_queue_base<ValueType, csbl::deque<ValueType> > super;
public:
typedef ValueType value_type;
//typedef typename super::value_type value_type; // fixme
typedef typename super::underlying_queue_type underlying_queue_type;
typedef typename super::size_type size_type;
typedef typename super::op_status op_status;
// Constructors/Assignment/Destructors
BOOST_THREAD_NO_COPYABLE(sync_queue)
inline sync_queue();
//template <typename Range>
//inline explicit sync_queue(Range range);
inline ~sync_queue();
// Modifiers
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void push(const value_type& x);
inline bool try_push(const value_type& x);
inline bool try_push(no_block_tag, const value_type& x);
inline void push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
#endif
inline void push_back(const value_type& x);
inline queue_op_status try_push_back(const value_type& x);
inline queue_op_status nonblocking_push_back(const value_type& x);
inline queue_op_status wait_push_back(const value_type& x);
inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
// Observers/Modifiers
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void pull(value_type&);
inline void pull(ValueType& elem, bool & closed);
// enable_if is_nothrow_copy_movable<value_type>
inline value_type pull();
inline shared_ptr<ValueType> ptr_pull();
#endif
inline void pull_front(value_type&);
// enable_if is_nothrow_copy_movable<value_type>
inline value_type pull_front();
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline bool try_pull(value_type&);
inline bool try_pull(no_block_tag,value_type&);
inline shared_ptr<ValueType> try_pull();
#endif
inline queue_op_status try_pull_front(value_type&);
inline queue_op_status nonblocking_pull_front(value_type&);
inline queue_op_status wait_pull_front(ValueType& elem);
private:
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
#endif
inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void pull(value_type& elem, unique_lock<mutex>& )
{
elem = boost::move(super::data_.front());
super::data_.pop_front();
}
inline value_type pull(unique_lock<mutex>& )
{
value_type e = boost::move(super::data_.front());
super::data_.pop_front();
return boost::move(e);
}
inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& )
{
shared_ptr<value_type> res = make_shared<value_type>(boost::move(super::data_.front()));
super::data_.pop_front();
return res;
}
#endif
inline void pull_front(value_type& elem, unique_lock<mutex>& )
{
elem = boost::move(super::data_.front());
super::data_.pop_front();
}
inline value_type pull_front(unique_lock<mutex>& )
{
value_type e = boost::move(super::data_.front());
super::data_.pop_front();
return boost::move(e);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void push(const value_type& elem, unique_lock<mutex>& lk)
{
super::data_.push_back(elem);
super::notify_not_empty_if_needed(lk);
}
inline void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
{
super::data_.push_back(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
#endif
inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
{
super::data_.push_back(elem);
super::notify_not_empty_if_needed(lk);
}
inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
{
super::data_.push_back(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
};
template <typename ValueType>
sync_queue<ValueType>::sync_queue() :
super()
{
}
// template <typename ValueType>
// template <typename Range>
// explicit sync_queue<ValueType>::sync_queue(Range range) :
// data_(), closed_(false)
// {
// try
// {
// typedef typename Range::iterator iterator_t;
// iterator_t first = boost::begin(range);
// iterator_t end = boost::end(range);
// for (iterator_t cur = first; cur != end; ++cur)
// {
// data_.push(boost::move(*cur));;
// }
// notify_not_empty_if_needed(lk);
// }
// catch (...)
// {
// delete[] data_;
// }
// }
template <typename ValueType>
sync_queue<ValueType>::~sync_queue()
{
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
super::throw_if_closed(lk);
return false;
}
pull(elem, lk);
return true;
}
template <typename ValueType>
shared_ptr<ValueType> sync_queue<ValueType>::try_pull(unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
super::throw_if_closed(lk);
return shared_ptr<ValueType>();
}
return ptr_pull(lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull_front(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
}
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
pull_front(elem, lk);
return queue_op_status::success;
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_pull(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_pull(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_pull_front(elem, lk);
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_pull_front(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_pull(no_block_tag,ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return false;
}
return try_pull(elem, lk);
}
template <typename ValueType>
boost::shared_ptr<ValueType> sync_queue<ValueType>::try_pull()
{
unique_lock<mutex> lk(super::mtx_);
return try_pull(lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::nonblocking_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_pull_front(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_queue<ValueType>::pull(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
pull(elem, lk);
}
template <typename ValueType>
void sync_queue<ValueType>::pull(ValueType& elem, bool & has_been_closed)
{
unique_lock<mutex> lk(super::mtx_);
has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) {return;}
pull(elem, lk);
}
// enable if ValueType is nothrow movable
template <typename ValueType>
ValueType sync_queue<ValueType>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull(lk);
}
template <typename ValueType>
boost::shared_ptr<ValueType> sync_queue<ValueType>::ptr_pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return ptr_pull(lk);
}
#endif
template <typename ValueType>
void sync_queue<ValueType>::pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
pull_front(elem, lk);
}
// enable if ValueType is nothrow movable
template <typename ValueType>
ValueType sync_queue<ValueType>::pull_front()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull_front(lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
{
super::throw_if_closed(lk);
push(elem, lk);
return true;
}
template <typename ValueType>
bool sync_queue<ValueType>::try_push(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push_back(elem, lk);
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_push_back(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(no_block_tag, const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock()) return false;
return try_push(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::nonblocking_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock()) return queue_op_status::busy;
return try_push_back(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_queue<ValueType>::push(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push(elem, lk);
}
#endif
template <typename ValueType>
void sync_queue<ValueType>::push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push_back(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
super::throw_if_closed(lk);
push(boost::move(elem), lk);
return true;
}
template <typename ValueType>
bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(boost::move(elem), lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push_back(boost::move(elem), lk);
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(boost::move(elem), lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_push_back(boost::move(elem), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return false;
}
return try_push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_push_back(boost::move(elem), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_queue<ValueType>::push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
void sync_queue<ValueType>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push_back(boost::move(elem), lk);
}
template <typename ValueType>
sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
{
sbq.push_back(boost::move(elem));
return sbq;
}
template <typename ValueType>
sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, ValueType const&elem)
{
sbq.push_back(elem);
return sbq;
}
template <typename ValueType>
sync_queue<ValueType>& operator>>(sync_queue<ValueType>& sbq, ValueType &elem)
{
sbq.pull_front(elem);
return sbq;
}
}
using concurrent::sync_queue;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,431 @@
// 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)
//
#ifndef BOOST_THREAD_SYNC_TIMED_QUEUE_HPP
#define BOOST_THREAD_SYNC_TIMED_QUEUE_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/concurrent_queues/sync_priority_queue.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/chrono_io.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <class T>
struct scheduled_type
{
typedef typename chrono::steady_clock clock;
typedef chrono::steady_clock::time_point time_point;
T data;
time_point time;
BOOST_THREAD_COPYABLE_AND_MOVABLE(scheduled_type)
scheduled_type(T const& pdata, time_point tp) : data(pdata), time(tp) {}
scheduled_type(BOOST_THREAD_RV_REF(T) pdata, time_point tp) : data(boost::move(pdata)), time(tp) {}
scheduled_type(scheduled_type const& other) : data(other.data), time(other.time) {}
scheduled_type& operator=(BOOST_THREAD_COPY_ASSIGN_REF(scheduled_type) other) {
data = other.data;
time = other.time;
return *this;
}
scheduled_type(BOOST_THREAD_RV_REF(scheduled_type) other) : data(boost::move(other.data)), time(other.time) {}
scheduled_type& operator=(BOOST_THREAD_RV_REF(scheduled_type) other) {
data = boost::move(other.data);
time = other.time;
return *this;
}
bool time_not_reached() const
{
return time > clock::now();
}
bool operator <(const scheduled_type<T> other) const
{
return this->time > other.time;
}
}; //end struct
} //end detail namespace
template <class T>
class sync_timed_queue
: private sync_priority_queue<detail::scheduled_type<T> >
{
typedef detail::scheduled_type<T> stype;
typedef sync_priority_queue<stype> super;
public:
//typedef typename stype::clock clock; // fixme
typedef typename chrono::steady_clock clock;
typedef typename clock::duration duration;
typedef typename clock::time_point time_point;
typedef T value_type;
//typedef typename super::value_type value_type; // fixme
typedef typename super::underlying_queue_type underlying_queue_type;
typedef typename super::size_type size_type;
typedef typename super::op_status op_status;
sync_timed_queue() : super() {};
~sync_timed_queue() {}
using super::size;
using super::empty;
using super::full;
using super::close;
using super::closed;
T pull();
void pull(T& elem);
queue_op_status pull_until(const clock::time_point& tp, T& elem);
queue_op_status pull_for(const clock::duration& dura, T& elem);
queue_op_status try_pull(T& elem);
queue_op_status wait_pull(T& elem);
queue_op_status nonblocking_pull(T& elem);
void push(const T& elem, const time_point& tp);
void push(const T& elem, const duration& dura);
queue_op_status try_push(const T& elem, const time_point& tp);
queue_op_status try_push(const T& elem, const duration& dura);
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, const time_point& tp);
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, const duration& dura);
private:
T pull(unique_lock<mutex>&);
T pull(lock_guard<mutex>&);
void pull(unique_lock<mutex>&, T& elem);
void pull(lock_guard<mutex>&, T& elem);
queue_op_status try_pull(unique_lock<mutex>&, T& elem);
queue_op_status try_pull(lock_guard<mutex>&, T& elem);
queue_op_status wait_pull(unique_lock<mutex>& lk, T& elem);
//queue_op_status nonblocking_pull(unique_lock<mutex>& lk, T& elem);
bool wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>&);
T pull_when_time_reached(unique_lock<mutex>&);
queue_op_status pull_when_time_reached_until(unique_lock<mutex>&, const clock::time_point& tp, T& elem);
bool time_not_reached(unique_lock<mutex>&);
bool time_not_reached(lock_guard<mutex>&);
bool empty_or_time_not_reached(unique_lock<mutex>&);
bool empty_or_time_not_reached(lock_guard<mutex>&);
sync_timed_queue(const sync_timed_queue&);
sync_timed_queue& operator=(const sync_timed_queue&);
sync_timed_queue(BOOST_THREAD_RV_REF(sync_timed_queue));
sync_timed_queue& operator=(BOOST_THREAD_RV_REF(sync_timed_queue));
}; //end class
template <class T>
void sync_timed_queue<T>::push(const T& elem, const time_point& tp)
{
super::push(stype(elem,tp));
}
template <class T>
void sync_timed_queue<T>::push(const T& elem, const duration& dura)
{
push(elem, clock::now() + dura);
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(const T& elem, const time_point& tp)
{
return super::try_push(stype(elem,tp));
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(const T& elem, const duration& dura)
{
return try_push(elem,clock::now() + dura);
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(BOOST_THREAD_RV_REF(T) elem, const time_point& tp)
{
return super::try_push(stype(boost::move(elem), tp));
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(BOOST_THREAD_RV_REF(T) elem, const duration& dura)
{
return try_push(boost::move(elem), clock::now() + dura);
}
///////////////////////////
template <class T>
bool sync_timed_queue<T>::time_not_reached(unique_lock<mutex>&)
{
return super::data_.top().time_not_reached();
}
template <class T>
bool sync_timed_queue<T>::time_not_reached(lock_guard<mutex>&)
{
return super::data_.top().time_not_reached();
}
///////////////////////////
template <class T>
bool sync_timed_queue<T>::wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>& lk)
{
for (;;)
{
if (super::closed(lk)) return true;
while (! super::empty(lk)) {
if (! time_not_reached(lk)) return false;
super::not_empty_.wait_until(lk, super::data_.top().time);
if (super::closed(lk)) return true;
}
if (super::closed(lk)) return true;
super::not_empty_.wait(lk);
}
return false;
}
///////////////////////////
template <class T>
T sync_timed_queue<T>::pull_when_time_reached(unique_lock<mutex>& lk)
{
while (time_not_reached(lk))
{
super::throw_if_closed(lk);
super::not_empty_.wait_until(lk,super::data_.top().time);
super::wait_until_not_empty(lk);
}
return pull(lk);
}
template <class T>
queue_op_status
sync_timed_queue<T>::pull_when_time_reached_until(unique_lock<mutex>& lk, const clock::time_point& tp, T& elem)
{
clock::time_point tpmin = (tp < super::data_.top().time) ? tp : super::data_.top().time;
while (time_not_reached(lk))
{
super::throw_if_closed(lk);
if (queue_op_status::timeout == super::not_empty_.wait_until(lk, tpmin)) {
if (time_not_reached(lk)) return queue_op_status::not_ready;
return queue_op_status::timeout;
}
}
pull(lk, elem);
return queue_op_status::success;
}
///////////////////////////
template <class T>
bool sync_timed_queue<T>::empty_or_time_not_reached(unique_lock<mutex>& lk)
{
if ( super::empty(lk) ) return true;
if ( time_not_reached(lk) ) return true;
return false;
}
template <class T>
bool sync_timed_queue<T>::empty_or_time_not_reached(lock_guard<mutex>& lk)
{
if ( super::empty(lk) ) return true;
if ( time_not_reached(lk) ) return true;
return false;
}
///////////////////////////
template <class T>
T sync_timed_queue<T>::pull(unique_lock<mutex>&)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
return boost::move(super::data_.pull().data);
#else
return super::data_.pull().data;
#endif
}
template <class T>
T sync_timed_queue<T>::pull(lock_guard<mutex>&)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
return boost::move(super::data_.pull().data);
#else
return super::data_.pull().data;
#endif
}
template <class T>
T sync_timed_queue<T>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull_when_time_reached(lk);
}
///////////////////////////
template <class T>
void sync_timed_queue<T>::pull(unique_lock<mutex>&, T& elem)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
elem = boost::move(super::data_.pull().data);
#else
elem = super::data_.pull().data;
#endif
}
template <class T>
void sync_timed_queue<T>::pull(lock_guard<mutex>&, T& elem)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
elem = boost::move(super::data_.pull().data);
#else
elem = super::data_.pull().data;
#endif
}
template <class T>
void sync_timed_queue<T>::pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
elem = pull_when_time_reached(lk);
}
//////////////////////
template <class T>
queue_op_status
sync_timed_queue<T>::pull_until(const clock::time_point& tp, T& elem)
{
unique_lock<mutex> lk(super::mtx_);
if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp))
return queue_op_status::timeout;
return pull_when_time_reached_until(lk, tp, elem);
}
//////////////////////
template <class T>
queue_op_status
sync_timed_queue<T>::pull_for(const clock::duration& dura, T& elem)
{
return pull_until(clock::now() + dura, elem);
}
///////////////////////////
template <class T>
queue_op_status sync_timed_queue<T>::try_pull(unique_lock<mutex>& lk, T& elem)
{
if ( super::empty(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
if ( time_not_reached(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::not_ready;
}
pull(lk, elem);
return queue_op_status::success;
}
template <class T>
queue_op_status sync_timed_queue<T>::try_pull(lock_guard<mutex>& lk, T& elem)
{
if ( super::empty(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
if ( time_not_reached(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::not_ready;
}
pull(lk, elem);
return queue_op_status::success;
}
template <class T>
queue_op_status sync_timed_queue<T>::try_pull(T& elem)
{
lock_guard<mutex> lk(super::mtx_);
return try_pull(lk, elem);
}
///////////////////////////
template <class T>
queue_op_status sync_timed_queue<T>::wait_pull(unique_lock<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
}
bool has_been_closed = wait_until_not_empty_time_reached_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
pull(lk, elem);
return queue_op_status::success;
}
template <class T>
queue_op_status sync_timed_queue<T>::wait_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_pull(lk, elem);
}
// ///////////////////////////
// template <class T>
// queue_op_status sync_timed_queue<T>::wait_pull(unique_lock<mutex> &lk, T& elem)
// {
// if (super::empty(lk))
// {
// if (super::closed(lk)) return queue_op_status::closed;
// }
// bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
// if (has_been_closed) return queue_op_status::closed;
// pull(lk, elem);
// return queue_op_status::success;
// }
// template <class T>
// queue_op_status sync_timed_queue<T>::wait_pull(T& elem)
// {
// unique_lock<mutex> lk(super::mtx_);
// return wait_pull(lk, elem);
// }
///////////////////////////
template <class T>
queue_op_status sync_timed_queue<T>::nonblocking_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (! lk.owns_lock()) return queue_op_status::busy;
return try_pull(lk, elem);
}
} //end concurrent namespace
using concurrent::sync_timed_queue;
} //end boost namespace
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,45 @@
// 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_DEQUE_HPP
#define BOOST_CSBL_DEQUE_HPP
#include <boost/config.hpp>
// MSVC has some trouble instantiating a non_copyable type
//C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(606) : error C2248: 'non_copyable::non_copyable' : cannot access private member declared in class 'non_copyable'
// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(24) : see declaration of 'non_copyable::non_copyable'
// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(23) : see declaration of 'non_copyable'
// C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
// with
// [
// _Ty=non_copyable
// ]
#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_HDR_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
#ifndef BOOST_THREAD_USES_BOOST_DEQUE
#define BOOST_THREAD_USES_BOOST_DEQUE
#endif
#include <boost/container/deque.hpp>
#else
#include <deque>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_DEQUE
using ::boost::container::deque;
#else
using ::std::deque;
#endif
}
}
#endif // header

View File

@@ -0,0 +1,49 @@
// 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_FUNCTIONAL_HPP
#define BOOST_CSBL_FUNCTIONAL_HPP
#include <boost/config.hpp>
#include <functional>
#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL || defined BOOST_NO_CXX11_HDR_FUNCTIONAL || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_THREAD_USES_BOOST_FUNCTIONAL
#define BOOST_THREAD_USES_BOOST_FUNCTIONAL
#endif
#include <boost/function.hpp>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL
using ::boost::function;
#else
// D.8.1, base (deprecated):
// 20.9.3, reference_wrapper:
// 20.9.4, arithmetic operations:
// 20.9.5, comparisons:
// 20.9.6, logical operations:
// 20.9.7, bitwise operations:
// 20.9.8, negators:
// 20.9.9, bind:
// D.9, binders (deprecated):
// D.8.2.1, adaptors (deprecated):
// D.8.2.2, adaptors (deprecated):
// 20.9.10, member function adaptors:
// 20.9.11 polymorphic function wrappers:
using ::std::function;
// 20.9.12, hash function primary template:
#endif
}
}
#endif // header

View File

@@ -0,0 +1,35 @@
// 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_LIST_HPP
#define BOOST_CSBL_LIST_HPP
#include <boost/config.hpp>
#if defined BOOST_THREAD_USES_BOOST_LIST || defined BOOST_NO_CXX11_HDR_LIST || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_THREAD_USES_BOOST_LIST
#define BOOST_THREAD_USES_BOOST_LIST
#endif
#include <boost/container/list.hpp>
#else
#include <list>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_LIST
using ::boost::container::list;
#else
using ::std::list;
#endif
}
}
#endif // header

View File

@@ -0,0 +1,61 @@
// 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_HPP
#define BOOST_CSBL_MEMORY_HPP
// 20.7.2 Header <memory> synopsis
// 20.7.3, pointer traits
#include <boost/thread/csbl/memory/pointer_traits.hpp>
// 20.7.4, pointer safety
// 20.7.5, pointer alignment function
// 20.7.6, allocator argument tag
#include <boost/thread/csbl/memory/allocator_arg.hpp>
// 20.7.8, allocator traits
#include <boost/thread/csbl/memory/allocator_traits.hpp>
// 20.7.7, uses_allocator
#include <boost/thread/csbl/memory/scoped_allocator.hpp>
// 20.7.9, the default allocator:
namespace boost
{
namespace csbl
{
using ::std::allocator;
}
}
// 20.7.10, raw storage iterator:
// 20.7.11, temporary buffers:
// 20.7.12, specialized algorithms:
// 20.8.1 class template unique_ptr:
// default_delete
#include <boost/thread/csbl/memory/default_delete.hpp>
#include <boost/thread/csbl/memory/unique_ptr.hpp>
// 20.8.2.1, class bad_weak_ptr:
// 20.8.2.2, class template shared_ptr:
// 20.8.2.2.6, shared_ptr creation
// 20.8.2.2.7, shared_ptr comparisons:
// 20.8.2.2.8, shared_ptr specialized algorithms:
// 20.8.2.2.9, shared_ptr casts:
// 20.8.2.2.10, shared_ptr get_deleter:
// 20.8.2.2.11, shared_ptr I/O:
// 20.8.2.3, class template weak_ptr:
// 20.8.2.3.6, weak_ptr specialized algorithms:
// 20.8.2.3.7, class template owner_less:
// 20.8.2.4, class template enable_shared_from_this:
// 20.8.2.5, shared_ptr atomic access:
// 20.8.2.6 hash support
#endif // header

View File

@@ -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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP
#define BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP
#include <boost/thread/csbl/memory/config.hpp>
// 20.7.6, allocator argument tag
#if defined BOOST_NO_CXX11_ALLOCATOR
#include <boost/container/scoped_allocator.hpp>
namespace boost
{
namespace csbl
{
using ::boost::container::allocator_arg_t;
using ::boost::container::allocator_arg;
}
}
#else
namespace boost
{
namespace csbl
{
using ::std::allocator_arg_t;
using ::std::allocator_arg;
}
}
#endif // BOOST_NO_CXX11_ALLOCATOR
namespace boost
{
using ::boost::csbl::allocator_arg_t;
using ::boost::csbl::allocator_arg;
}
#endif // header

View File

@@ -0,0 +1,35 @@
// 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_ALLOCATOR_TRAITS_HPP
#define BOOST_CSBL_MEMORY_ALLOCATOR_TRAITS_HPP
#include <boost/thread/csbl/memory/config.hpp>
// 20.7.8, allocator traits
#if defined BOOST_NO_CXX11_ALLOCATOR
#include <boost/container/allocator_traits.hpp>
namespace boost
{
namespace csbl
{
using ::boost::container::allocator_traits;
}
}
#else
namespace boost
{
namespace csbl
{
using ::std::allocator_traits;
}
}
#endif // BOOST_NO_CXX11_POINTER_TRAITS
#endif // header

View File

@@ -0,0 +1,16 @@
// 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_CONFIG_HPP
#define BOOST_CSBL_MEMORY_CONFIG_HPP
#include <boost/config.hpp>
#include <memory>
#endif // header

View File

@@ -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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_DEFAULT_DELETE_HPP
#define BOOST_CSBL_MEMORY_DEFAULT_DELETE_HPP
#include <boost/thread/csbl/memory/config.hpp>
// 20.8.1 class template unique_ptr:
// default_delete
#if defined BOOST_NO_CXX11_SMART_PTR
#include <boost/move/unique_ptr.hpp>
namespace boost
{
namespace csbl
{
using ::boost::movelib::default_delete;
}
}
#else
namespace boost
{
namespace csbl
{
using ::std::default_delete;
}
}
#endif // defined BOOST_NO_CXX11_SMART_PTR
namespace boost
{
using ::boost::csbl::default_delete;
}
#endif // header

View File

@@ -0,0 +1,35 @@
// 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_POINTER_TRAITS_HPP
#define BOOST_CSBL_MEMORY_POINTER_TRAITS_HPP
#include <boost/thread/csbl/memory/config.hpp>
// 20.7.3, pointer traits
#if defined BOOST_NO_CXX11_ALLOCATOR
#include <boost/intrusive/pointer_traits.hpp>
namespace boost
{
namespace csbl
{
using ::boost::intrusive::pointer_traits;
}
}
#else
namespace boost
{
namespace csbl
{
using ::std::pointer_traits;
}
}
#endif // BOOST_NO_CXX11_ALLOCATOR
#endif // header

View File

@@ -0,0 +1,35 @@
// 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_SCOPED_ALLOCATOR_HPP
#define BOOST_CSBL_MEMORY_SCOPED_ALLOCATOR_HPP
#include <boost/thread/csbl/memory/config.hpp>
// 20.7.7, uses_allocator
#if defined BOOST_NO_CXX11_ALLOCATOR
#include <boost/container/scoped_allocator.hpp>
namespace boost
{
namespace csbl
{
using ::boost::container::uses_allocator;
}
}
#else
namespace boost
{
namespace csbl
{
using ::std::uses_allocator;
}
}
#endif // BOOST_NO_CXX11_POINTER_TRAITS
#endif // header

View File

@@ -0,0 +1,42 @@
// 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)
//
// 2014/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_SHARED_PTR_HPP
#define BOOST_CSBL_MEMORY_SHARED_PTR_HPP
#include <boost/thread/csbl/memory/config.hpp>
#if defined BOOST_NO_CXX11_SMART_PTR
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
namespace boost
{
namespace csbl
{
using ::boost::shared_ptr;
using ::boost::make_shared;
}
}
#else
#include <boost/shared_ptr.hpp>
namespace boost
{
namespace csbl
{
using std::shared_ptr;
using std::make_shared;
}
}
#endif
#endif // header

View File

@@ -0,0 +1,28 @@
// Copyright (C) 2013-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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation using interprocess::unique_ptr.
// 2014/09 Vicente J. Botet Escriba
// Adaptation to movelib::unique_ptr
#ifndef BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
#define BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
#include <boost/thread/csbl/memory/config.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/move/make_unique.hpp>
namespace boost
{
namespace csbl
{
using ::boost::movelib::unique_ptr;
using ::boost::movelib::make_unique;
}
}
#endif // header

View File

@@ -0,0 +1,49 @@
// 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_TUPLE_HPP
#define BOOST_CSBL_TUPLE_HPP
#include <boost/config.hpp>
#if defined BOOST_THREAD_USES_BOOST_TUPLE || defined BOOST_NO_CXX11_HDR_TUPLE || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#include <boost/tuple/tuple.hpp>
#ifndef BOOST_THREAD_USES_BOOST_TUPLE
#define BOOST_THREAD_USES_BOOST_TUPLE
#endif
#else
#include <tuple>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_TUPLE
using ::boost::tuple;
using ::boost::get;
using ::boost::make_tuple;
//using ::boost::tuple_size;
#else
// 20.4.2, class template tuple:
using ::std::tuple;
using ::std::get;
using ::std::make_tuple;
using ::std::tuple_size;
// 20.4.2.4, tuple creation functions:
// 20.4.2.5, tuple helper classes:
// 20.4.2.6, element access:
// 20.4.2.7, relational operators:
// 20.4.2.8, allocator-related traits
// 20.4.2.9, specialized algorithms:
#endif
}
}
#endif // header

View File

@@ -0,0 +1,35 @@
// 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_VECTOR_HPP
#define BOOST_CSBL_VECTOR_HPP
#include <boost/config.hpp>
#if defined BOOST_THREAD_USES_BOOST_VECTOR || defined BOOST_NO_CXX11_HDR_VECTOR || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_THREAD_USES_BOOST_VECTOR
#define BOOST_THREAD_USES_BOOST_VECTOR
#endif
#include <boost/container/vector.hpp>
#else
#include <vector>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_VECTOR
using ::boost::container::vector;
#else
using ::std::vector;
#endif
}
}
#endif // header

View File

@@ -9,7 +9,7 @@
#ifndef BOOST_THREAD_CV_STATUS_HPP
#define BOOST_THREAD_CV_STATUS_HPP
#include <boost/detail/scoped_enum_emulation.hpp>
#include <boost/core/scoped_enum.hpp>
namespace boost
{

View File

@@ -1,571 +0,0 @@
// 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)
// 2013/04 Vicente J. Botet Escriba
// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined.
// Make use of Boost.Move
// Make use of Boost.Tuple (movable)
// 2012/11 Vicente J. Botet Escriba
// Adapt to boost libc++ implementation
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
// The async_func code is based on the one from libcxx.
//===----------------------------------------------------------------------===//
#ifndef BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP
#define BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP
#include <boost/config.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/detail/invoke.hpp>
#include <boost/thread/detail/make_tuple_indices.hpp>
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
! defined(BOOST_NO_CXX11_HDR_TUPLE)
#include <tuple>
#else
#include <boost/tuple/tuple.hpp>
#endif
namespace boost
{
namespace detail
{
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
! defined(BOOST_NO_CXX11_HDR_TUPLE)
template <class Fp, class ... Args>
class async_func
{
std::tuple<Fp, Args...> f_;
public:
BOOST_THREAD_MOVABLE_ONLY( async_func)
//typedef typename invoke_of<_Fp, _Args...>::type Rp;
typedef typename result_of<Fp(Args...)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args)... args)
: f_(boost::move(f), boost::move(args)...)
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f) : f_(boost::move(f.f_))
{}
result_type operator()()
{
typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
return execute(Index());
}
private:
template <size_t ...Indices>
result_type
execute(tuple_indices<Indices...>)
{
return invoke(boost::move(std::get<0>(f_)), boost::move(std::get<Indices>(f_))...);
}
};
//BOOST_THREAD_DCL_MOVABLE_BEG(X) async_func<Fp> BOOST_THREAD_DCL_MOVABLE_END
#else
template <class Fp,
class T0 = tuples::null_type, class T1 = tuples::null_type, class T2 = tuples::null_type,
class T3 = tuples::null_type, class T4 = tuples::null_type, class T5 = tuples::null_type,
class T6 = tuples::null_type, class T7 = tuples::null_type, class T8 = tuples::null_type
, class T9 = tuples::null_type
>
class async_func;
template <class Fp,
class T0 , class T1 , class T2 ,
class T3 , class T4 , class T5 ,
class T6 , class T7 , class T8 >
class async_func<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
T7 v7_;
T8 v8_;
//::boost::tuple<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8> f_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7, T8)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
, BOOST_THREAD_RV_REF(T7) a7
, BOOST_THREAD_RV_REF(T8) a8
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
, v7_(boost::move(a7))
, v8_(boost::move(a8))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
, v4_(boost::move(f.a4))
, v5_(boost::move(f.a5))
, v6_(boost::move(f.a6))
, v7_(boost::move(f.a7))
, v8_(boost::move(f.a8))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
, boost::move(v7_)
, boost::move(v8_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
class async_func<Fp, T0, T1, T2, T3, T4, T5, T6, T7>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
T7 v7_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
, BOOST_THREAD_RV_REF(T7) a7
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
, v7_(boost::move(a7))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
, v4_(boost::move(f.a4))
, v5_(boost::move(f.a5))
, v6_(boost::move(f.a6))
, v7_(boost::move(f.a7))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
, boost::move(v7_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6>
class async_func<Fp, T0, T1, T2, T3, T4, T5, T6>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
, v4_(boost::move(f.a4))
, v5_(boost::move(f.a5))
, v6_(boost::move(f.a6))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5>
class async_func<Fp, T0, T1, T2, T3, T4, T5>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
, v4_(boost::move(f.a4))
, v5_(boost::move(f.a5))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4>
class async_func<Fp, T0, T1, T2, T3, T4>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3, T4)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
, v4_(boost::move(f.a4))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3>
class async_func<Fp, T0, T1, T2, T3>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
);
}
};
template <class Fp, class T0, class T1, class T2>
class async_func<Fp, T0, T1, T2>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
);
}
};
template <class Fp, class T0, class T1>
class async_func<Fp, T0, T1>
{
Fp fp_;
T0 v0_;
T1 v1_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
);
}
};
template <class Fp, class T0>
class async_func<Fp, T0>
{
Fp fp_;
T0 v0_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
);
}
};
template <class Fp>
class async_func<Fp>
{
Fp fp_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(async_func)
typedef typename result_of<Fp()>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_FWD_REF(Fp) f)
: fp_(boost::move(f))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_FWD_REF(async_func) f)
: fp_(boost::move(f.fp_))
{}
result_type operator()()
{
return fp_();
}
};
#endif
}
}
#endif // header

View File

@@ -15,8 +15,7 @@
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
// ATTRIBUTE_MAY_ALIAS
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) > 302 \
&& !defined(__INTEL_COMPILER)
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
// regard to violation of the strict aliasing rules.
@@ -240,7 +239,7 @@
! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
! defined(BOOST_NO_CXX11_DECLTYPE) && \
! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
! defined(BOOST_NO_CXX11_AUTO) && \
! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
! defined(BOOST_NO_CXX11_HDR_TUPLE)
@@ -248,6 +247,22 @@
#endif
#endif
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY \
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_WHEN_ALL_WHEN_ANY
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
! defined(BOOST_NO_CXX11_HDR_TUPLE)
#define BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
#endif
#endif
// ! defined(BOOST_NO_SFINAE_EXPR) &&
// ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) &&
// ! defined(BOOST_NO_CXX11_AUTO) &&
// ! defined(BOOST_NO_CXX11_DECLTYPE) &&
// ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) &&
// MAKE_READY_AT_THREAD_EXIT
#if ! defined BOOST_THREAD_PROVIDES_MAKE_READY_AT_THREAD_EXIT \
@@ -264,6 +279,11 @@
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#endif
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP \
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_UNWRAP
#define BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
#endif
// FUTURE_INVALID_AFTER_GET
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET \
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET
@@ -318,6 +338,11 @@
#define BOOST_THREAD_USES_DATETIME
#endif
#if defined(BOOST_THREAD_PLATFORM_WIN32) && defined BOOST_THREAD_DONT_USE_CHRONO
#undef BOOST_THREAD_DONT_USE_CHRONO
#define BOOST_THREAD_USES_CHRONO
#endif
// BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.55
// BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.55
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
@@ -328,6 +353,12 @@
#endif
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_THREAD_USES_MOVE
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_FUTURE_USES_OPTIONAL
#endif
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
# pragma warn -8008 // Condition always true/false
# pragma warn -8080 // Identifier declared but never used
@@ -353,7 +384,9 @@
// compatibility with the rest of Boost's auto-linking code:
#if defined(BOOST_THREAD_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
# undef BOOST_THREAD_USE_LIB
# define BOOST_THREAD_USE_DLL
# if !defined(BOOST_THREAD_USE_DLL)
# define BOOST_THREAD_USE_DLL
# endif
#endif
#if defined(BOOST_THREAD_BUILD_DLL) //Build dll

View File

@@ -75,15 +75,28 @@ namespace boost
};
struct counter_is_not_zero
{
counter_is_not_zero(const counter& count) : count_(count) {}
counter_is_not_zero(counter const& count) : count_(count) {}
bool operator()() const { return count_ != 0; }
const counter& count_;
counter const& count_;
};
struct counter_is_zero
{
counter_is_zero(const counter& count) : count_(count) {}
counter_is_zero(counter const& count) : count_(count) {}
bool operator()() const { return count_ == 0; }
const counter& count_;
counter const& count_;
};
struct is_zero
{
is_zero(std::size_t& count) : count_(count) {}
bool operator()() const { return count_ == 0; }
std::size_t& count_;
};
struct not_equal
{
not_equal(std::size_t& x, std::size_t& y) : x_(x), y_(y) {}
bool operator()() const { return x_ != y_; }
std::size_t& x_;
std::size_t& y_;
};
}
} // namespace boost

View File

@@ -15,7 +15,8 @@
* BOOST_THREAD_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or
* makes it private.
*/
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
#if ! defined BOOST_NO_CXX11_DELETED_FUNCTIONS && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
CLASS(CLASS const&) = delete; \
@@ -23,6 +24,17 @@
CLASS& operator=(CLASS const&) = delete;
#else // BOOST_NO_CXX11_DELETED_FUNCTIONS
#if defined(BOOST_MSVC) && _MSC_VER >= 1600
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
private: \
CLASS(CLASS const&); \
public:
#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \
private: \
CLASS& operator=(CLASS const&); \
public:
#else
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
private: \
CLASS(CLASS&); \
@@ -32,6 +44,7 @@
private: \
CLASS& operator=(CLASS&); \
public:
#endif
#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
/**

View File

@@ -0,0 +1,93 @@
// 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)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
// Make use of Boost.Move
#ifndef BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP
#define BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP
#include <boost/config.hpp>
#include <boost/thread/detail/memory.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/csbl/memory/unique_ptr.hpp>
#include <memory>
#include <functional>
namespace boost
{
namespace detail
{
class function_wrapper
{
struct impl_base
{
virtual void call()=0;
virtual ~impl_base()
{
}
};
typedef boost::csbl::unique_ptr<impl_base> impl_base_type;
impl_base_type impl;
template <typename F>
struct impl_type: impl_base
{
F f;
impl_type(F const &f_)
: f(f_)
{}
impl_type(BOOST_THREAD_RV_REF(F) f_)
: f(boost::move(f_))
{}
void call()
{
if (impl) f();
}
};
public:
BOOST_THREAD_MOVABLE_ONLY(function_wrapper)
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename F>
function_wrapper(F const& f):
impl(new impl_type<F>(f))
{}
//#endif
template<typename F>
function_wrapper(BOOST_THREAD_RV_REF(F) f):
impl(new impl_type<F>(boost::forward<F>(f)))
{}
function_wrapper(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT :
impl(other.impl)
{
other.impl = 0;
}
function_wrapper()
: impl(0)
{
}
~function_wrapper()
{
}
function_wrapper& operator=(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT
{
impl=other.impl;
other.impl=0;
return *this;
}
void operator()()
{ impl->call();}
};
}
}
#endif // header

View File

@@ -28,7 +28,11 @@
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_member_function_pointer.hpp>
#include <boost/type_traits/remove_reference.hpp>
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
#include <functional>
@@ -40,11 +44,10 @@ namespace boost
{
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
! defined(BOOST_NO_SFINAE_EXPR) && \
#if ! defined(BOOST_NO_SFINAE_EXPR) && \
! defined(BOOST_NO_CXX11_DECLTYPE) && \
! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
! defined(BOOST_NO_CXX11_AUTO)
! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
#define BOOST_THREAD_PROVIDES_INVOKE
@@ -58,6 +61,13 @@ namespace boost
{
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
}
template <class R, class Fp, class A0, class ...Args>
inline auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...))
{
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
}
template <class Fp, class A0, class ...Args>
inline auto
@@ -66,6 +76,13 @@ namespace boost
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
}
template <class R, class Fp, class A0, class ...Args>
inline auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...))
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
}
// bullets 3 and 4
@@ -85,14 +102,38 @@ namespace boost
return (*boost::forward<A0>(a0)).*f;
}
template <class R, class Fp, class A0>
inline auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype(boost::forward<A0>(a0).*f)
{
return boost::forward<A0>(a0).*f;
}
template <class R, class Fp, class A0>
inline auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype((*boost::forward<A0>(a0)).*f)
{
return (*boost::forward<A0>(a0)).*f;
}
// bullet 5
template <class R, class Fp, class ...Args>
inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
-> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...))
{
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
}
template <class Fp, class ...Args>
inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
-> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...))
{
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
}
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
// bullets 1 and 2
@@ -105,21 +146,45 @@ namespace boost
{
return (boost::forward<A0>(a0).*f)();
}
template <class R, class Fp, class A0>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype((boost::forward<A0>(a0).*f)())
{
return (boost::forward<A0>(a0).*f)();
}
template <class Fp, class A0, class A1>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(a1)))
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)))
{
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(a1));
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
}
template <class R, class Fp, class A0, class A1>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)))
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
}
template <class Fp, class A0, class A1, class A2>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2)))
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
{
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2));
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class R, class Fp, class A0, class A1, class A2>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Fp, class A0>
@@ -130,21 +195,45 @@ namespace boost
{
return ((*boost::forward<A0>(a0)).*f)();
}
template <class R, class Fp, class A0>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype(((*boost::forward<A0>(a0)).*f)())
{
return ((*boost::forward<A0>(a0)).*f)();
}
template <class Fp, class A0, class A1>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1)))
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)))
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1));
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
}
template <class Fp, class A0, class A1>
template <class R, class Fp, class A0, class A1>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)))
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
}
template <class Fp, class A0, class A1, class A2>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2)))
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2));
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class R, class Fp, class A0, class A1, class A2>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
// bullets 3 and 4
@@ -157,6 +246,14 @@ namespace boost
{
return boost::forward<A0>(a0).*f;
}
template <class R, class Fp, class A0>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype(boost::forward<A0>(a0).*f)
{
return boost::forward<A0>(a0).*f;
}
template <class Fp, class A0>
inline
@@ -166,6 +263,14 @@ namespace boost
{
return (*boost::forward<A0>(a0)).*f;
}
template <class R, class Fp, class A0>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype((*boost::forward<A0>(a0)).*f)
{
return (*boost::forward<A0>(a0)).*f;
}
// bullet 5
@@ -178,7 +283,7 @@ namespace boost
}
template <class Fp, class A1>
inline
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) a1)
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1)))
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1));
@@ -197,6 +302,36 @@ namespace boost
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class R, class Fp>
inline
auto invoke(BOOST_THREAD_RV_REF(Fp) f)
-> decltype(boost::forward<Fp>(f)())
{
return boost::forward<Fp>(f)();
}
template <class R, class Fp, class A1>
inline
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1)))
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1));
}
template <class R, class Fp, class A1, class A2>
inline
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class R, class Fp, class A1, class A2, class A3>
inline
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)))
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
#elif ! defined(BOOST_NO_SFINAE_EXPR) && \
@@ -395,22 +530,28 @@ namespace boost
// bullet 5
// f(t1, t2, ..., tN) in all other cases.
template <class Ret, class Fp, class ...Args>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
{
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
}
template <class Ret, class Fp, class ...Args>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
{
return f(boost::forward<Args>(args)...);
}
template <class Ret, class Fp, class ...Args>
inline
typename enable_if_c
typename disable_if_c
<
! is_member_function_pointer<Fp>::value,
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
{
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
}
template <class Ret, class ...Args>
inline Ret
invoke(Ret(*f)(Args... ), BOOST_THREAD_RV_REF(Args) ...args)
{
return f(boost::forward<Args>(args)...);
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<Args>(args)...);
}
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
// bullet 1
@@ -424,9 +565,34 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(), BOOST_THREAD_RV_REF(A0) a0)
invoke(Ret (A::*f)(), A0& a0)
{
return (boost::forward<A0>(a0).*f)();
return (a0.*f)();
}
template <class Ret, class A, class A0>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(), A0* a0)
{
return ((*a0).*f)();
}
template <class Ret, class A, class A0, class A1>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1),
A0& a0, BOOST_THREAD_RV_REF(A1) a1
)
{
return (a0.*f)(boost::forward<A1>(a1));
}
template <class Ret, class A, class A0, class A1>
inline
@@ -435,21 +601,33 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
}
template <class Ret, class A, class A0, class A1>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1), A0 a0, A1 a1)
invoke(Ret (A::*f)(A1), A0& a0, A1 a1)
{
return (a0.*f)(a1);
}
template <class Ret, class A, class A0, class A1>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1), A0* a0, BOOST_THREAD_RV_REF(A1) a1
)
{
return (*(a0).*f)(boost::forward<A1>(a1));
}
template <class Ret, class A, class A0, class A1>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1), A0* a0, A1 a1)
{
return (*a0.*f)(a1);
}
template <class Ret, class A, class A0, class A1, class A2>
inline
typename enable_if_c
@@ -458,10 +636,10 @@ namespace boost
Ret
>::type
invoke(Ret (A::*f)(A1, A2),
BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
)
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class A, class A0, class A1, class A2>
inline
@@ -470,9 +648,9 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1, A2), A0 a0, A1 a1, A2 a2)
invoke(Ret (A::*f)(A1, A2), A0* a0, A1 a1, A2 a2)
{
return (a0.*f)(a1, a2);
return ((*a0).*f)(a1, a2);
}
template <class Ret, class A, class A0, class A1, class A2, class A3>
inline
@@ -482,9 +660,9 @@ namespace boost
Ret
>::type
invoke(Ret (A::*f)(A1, A2, A3),
BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class Ret, class A, class A0, class A1, class A2, class A3>
inline
@@ -493,9 +671,9 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1, A2, A3), A0 a0, A1 a1, A2 a2, A3 a3)
invoke(Ret (A::*f)(A1, A2, A3), A0* a0, A1 a1, A2 a2, A3 a3)
{
return (a0.*f)(a1, a2, a3);
return ((*a0).*f)(a1, a2, a3);
}
///
@@ -506,9 +684,20 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)() const, BOOST_THREAD_RV_REF(A0) a0)
invoke(Ret (A::*f)() const, A0 const& a0)
{
return (boost::forward<A0>(a0).*f)();
return (a0.*f)();
}
template <class Ret, class A, class A0>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)() const, A0 const* a0)
{
return ((*a0).*f)();
}
template <class Ret, class A, class A0, class A1>
inline
@@ -517,9 +706,9 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1) const, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
invoke(Ret (A::*f)(A1) const, A0 const& a0, BOOST_THREAD_RV_REF(A1) a1)
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
return (a0.*f)(boost::forward<A1>(a1));
}
template <class Ret, class A, class A0, class A1>
inline
@@ -528,7 +717,19 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1) const, A0 a0, A1 a1)
invoke(Ret (A::*f)(A1) const, A0 const* a0, BOOST_THREAD_RV_REF(A1) a1)
{
return ((*a0).*f)(boost::forward<A1>(a1));
}
template <class Ret, class A, class A0, class A1>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1) const, A0 const& a0, A1 a1)
{
return (a0.*f)(a1);
}
@@ -540,7 +741,7 @@ namespace boost
Ret
>::type
invoke(Ret (A::*f)(A1, A2) const,
BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
A0 const& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
)
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)
@@ -553,7 +754,7 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1, A2) const, A0 a0, A1 a1, A2 a2)
invoke(Ret (A::*f)(A1, A2) const, A0 const& a0, A1 a1, A2 a2)
{
return (a0.*f)(a1, a2);
}
@@ -1159,189 +1360,241 @@ namespace boost
// f(t1, t2, ..., tN) in all other cases.
template <class Ret, class Fp>
inline
typename enable_if_c
<
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f)
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f)
{
return boost::forward<Fp>(f)();
}
template <class Ret, class Fp, class A1>
template <class Ret, class Fp>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f)
{
return f();
}
template <class Ret, class Fp>
inline
typename enable_if_c
typename disable_if_c
<
! is_member_function_pointer<Fp>::value,
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
invoke(BOOST_THREAD_FWD_REF(Fp) f)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f));
}
template <class Ret, class Fp, class A1>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1));
}
template <class Ret, class Fp, class A1>
inline
typename enable_if_c
<
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f, A1 a1)
{
return boost::forward<Fp>(f)(a1);
}
template <class Ret, class Fp, class A1, class A2>
inline
typename enable_if_c
<
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class Fp, class A1, class A2>
inline
typename enable_if_c
<
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f, A1 a1, A2 a2)
{
return boost::forward<Fp>(f)(a1, a2);
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline
typename enable_if_c
<
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline
typename enable_if_c
<
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f, A1 a1, A2 a2, A3 a3)
{
return boost::forward<Fp>(f)(a1, a2, a3);
}
///
template <class Ret, class Fp>
inline
typename enable_if_c
<
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp const &f)
{
return f();
}
template <class Ret, class Fp, class A1>
inline
typename enable_if_c
<
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp const &f, BOOST_THREAD_RV_REF(A1) a1)
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
{
return f(boost::forward<A1>(a1));
}
template <class Ret, class Fp, class A1>
inline
typename enable_if_c
typename disable_if_c
<
! is_member_function_pointer<Fp>::value,
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp const &f, A1 a1)
invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1));
}
template <class Ret, class Fp, class A1, class A2>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class Fp, class A1, class A2>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class Fp, class A1, class A2>
inline
typename disable_if_c
<
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline
typename disable_if_c
<
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class Ret, class Fp, class A1>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
{
return boost::forward<Fp>(f)(a1);
}
template <class Ret, class Fp, class A1>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
{
return f(a1);
}
template <class Ret, class Fp, class A1>
inline
typename disable_if_c
<
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1);
}
template <class Ret, class Fp, class A1, class A2>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
{
return boost::forward<Fp>(f)(a1, a2);
}
template <class Ret, class Fp, class A1, class A2>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
{
return f(a1, a2);
}
template <class Ret, class Fp, class A1, class A2>
inline
typename disable_if_c
<
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2);
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
{
return boost::forward<Fp>(f)(a1, a2, a3);
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
{
return f(a1, a2, a3);
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline
typename disable_if_c
<
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2, a3);
}
///
template <class Ret, class Fp>
inline
typename disable_if_c
<
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp &f)
{
return f();
}
template <class Ret, class Fp, class A1>
inline
typename disable_if_c
<
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1)
{
return f(boost::forward<A1>(a1));
}
template <class Ret, class Fp, class A1>
inline
typename disable_if_c
<
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp &f, A1 a1)
{
return f(a1);
}
template <class Ret, class Fp, class A1, class A2>
inline
typename enable_if_c
typename disable_if_c
<
! is_member_function_pointer<Fp>::value,
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp const &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class Fp, class A1, class A2>
inline
typename enable_if_c
typename disable_if_c
<
! is_member_function_pointer<Fp>::value,
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp const &f, A1 a1, A2 a2)
invoke(Fp &f, A1 a1, A2 a2)
{
return f(a1, a2);
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline
typename enable_if_c
typename disable_if_c
<
! is_member_function_pointer<Fp>::value,
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp const &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline
typename enable_if_c
typename disable_if_c
<
! is_member_function_pointer<Fp>::value,
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp const &f, A1 a1, A2 a2, A3 a3)
invoke(Fp &f, A1 a1, A2 a2, A3 a3)
{
return f(a1, a2, a3);
}
///
template <class Ret>
inline Ret
invoke(Ret(*f)())
{
return f();
}
template <class Ret, class A1>
inline Ret
invoke(Ret(*f)(A1), BOOST_THREAD_RV_REF(A1) a1)
{
return f(boost::forward<A1>(a1));
}
template <class Ret, class A1, class A2>
inline Ret
invoke(Ret(*f)(A1, A2),
BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class A1, class A2, class A3>
inline Ret
invoke(Ret(*f)(A1, A2, A3),
BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif // all

View File

@@ -0,0 +1,754 @@
// 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)
// 2013/04 Vicente J. Botet Escriba
// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined.
// Make use of Boost.Move
// Make use of Boost.Tuple (movable)
// 2012/11 Vicente J. Botet Escriba
// Adapt to boost libc++ implementation
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
// The invoker code is based on the one from libcxx.
//===----------------------------------------------------------------------===//
#ifndef BOOST_THREAD_DETAIL_INVOKER_HPP
#define BOOST_THREAD_DETAIL_INVOKER_HPP
#include <boost/config.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/detail/invoke.hpp>
#include <boost/thread/detail/make_tuple_indices.hpp>
#include <boost/thread/csbl/tuple.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/thread/detail/variadic_header.hpp>
namespace boost
{
namespace detail
{
#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
template <class Fp, class ... Args>
class invoker
{
//typedef typename decay<Fp>::type Fpd;
//typedef tuple<typename decay<Args>::type...> Argsd;
//csbl::tuple<Fpd, Argsd...> f_;
csbl::tuple<Fp, Args...> f_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker)
//typedef typename invoke_of<_Fp, _Args...>::type Rp;
typedef typename result_of<Fp(Args...)>::type result_type;
template <class F, class ... As>
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args)
: f_(boost::forward<F>(f), boost::forward<As>(args)...)
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f) : f_(boost::move(BOOST_THREAD_RV(f).f_))
{}
BOOST_SYMBOL_VISIBLE
invoker( const invoker& f) : f_(f.f_)
{}
BOOST_SYMBOL_VISIBLE
invoker& operator=(BOOST_THREAD_RV_REF(invoker) f)
{
f_ = boost::move(BOOST_THREAD_RV(f).f_);
}
BOOST_SYMBOL_VISIBLE
invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f)
{
f_ = f.f_;
}
result_type operator()()
{
typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
return execute(Index());
}
private:
template <size_t ...Indices>
result_type
execute(tuple_indices<Indices...>)
{
return invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
}
};
template <class R, class Fp, class ... Args>
class invoker_ret
{
//typedef typename decay<Fp>::type Fpd;
//typedef tuple<typename decay<Args>::type...> Argsd;
//csbl::tuple<Fpd, Argsd...> f_;
csbl::tuple<Fp, Args...> f_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker_ret)
typedef R result_type;
template <class F, class ... As>
BOOST_SYMBOL_VISIBLE
explicit invoker_ret(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args)
: f_(boost::forward<F>(f), boost::forward<As>(args)...)
{}
BOOST_SYMBOL_VISIBLE
invoker_ret(BOOST_THREAD_RV_REF(invoker_ret) f) : f_(boost::move(BOOST_THREAD_RV(f).f_))
{}
result_type operator()()
{
typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
return execute(Index());
}
private:
template <size_t ...Indices>
result_type
execute(tuple_indices<Indices...>)
{
return invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
}
};
//BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END
#else
#if ! defined BOOST_MSVC
#define BOOST_THREAD_RV_REF_ARG_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(Arg##n)
#define BOOST_THREAD_RV_REF_A_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(A##n)
#define BOOST_THREAD_RV_REF_ARG(z, n, unused) , BOOST_THREAD_RV_REF(Arg##n) arg##n
#define BOOST_THREAD_FWD_REF_A(z, n, unused) , BOOST_THREAD_FWD_REF(A##n) arg##n
#define BOOST_THREAD_FWD_REF_ARG(z, n, unused) , BOOST_THREAD_FWD_REF(Arg##n) arg##n
#define BOOST_THREAD_FWD_PARAM(z, n, unused) , boost::forward<Arg##n>(arg##n)
#define BOOST_THREAD_FWD_PARAM_A(z, n, unused) , boost::forward<A##n>(arg##n)
#define BOOST_THREAD_DCL(z, n, unused) Arg##n v##n;
#define BOOST_THREAD_MOVE_PARAM(z, n, unused) , v##n(boost::move(arg##n))
#define BOOST_THREAD_FORWARD_PARAM_A(z, n, unused) , v##n(boost::forward<A##n>(arg##n))
#define BOOST_THREAD_MOVE_RHS_PARAM(z, n, unused) , v##n(boost::move(x.v##n))
#define BOOST_THREAD_MOVE_DCL(z, n, unused) , boost::move(v##n)
#define BOOST_THREAD_MOVE_DCL_T(z, n, unused) BOOST_PP_COMMA_IF(n) boost::move(v##n)
#define BOOST_THREAD_ARG_DEF(z, n, unused) , class Arg##n = tuples::null_type
template <class Fp, class Arg = tuples::null_type
BOOST_PP_REPEAT(BOOST_THREAD_MAX_ARGS, BOOST_THREAD_ARG_DEF, ~)
>
class invoker;
#define BOOST_THREAD_ASYNC_FUNCT(z, n, unused) \
template <class Fp BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class Arg) > \
class invoker<Fp BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Arg)> \
{ \
Fp fp_; \
BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
public: \
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
\
template <class F BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
BOOST_SYMBOL_VISIBLE \
explicit invoker(BOOST_THREAD_FWD_REF(F) f \
BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \
) \
: fp_(boost::forward<F>(f)) \
BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \
{} \
\
BOOST_SYMBOL_VISIBLE \
invoker(BOOST_THREAD_RV_REF(invoker) x) \
: fp_(boost::move(x.fp_)) \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
{} \
\
result_type operator()() { \
return invoke(boost::move(fp_) \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \
); \
} \
}; \
\
template <class R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class Arg) > \
class invoker<R(*)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_ARG_T, ~)) BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Arg)> \
{ \
typedef R(*Fp)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_ARG_T, ~)); \
Fp fp_; \
BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
public: \
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
\
template <class R2 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
BOOST_SYMBOL_VISIBLE \
explicit invoker(R2(*f)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_A_T, ~)) \
BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \
) \
: fp_(f) \
BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \
{} \
\
BOOST_SYMBOL_VISIBLE \
invoker(BOOST_THREAD_RV_REF(invoker) x) \
: fp_(x.fp_) \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
{} \
\
result_type operator()() { \
return fp_( \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL_T, ~) \
); \
} \
};
BOOST_PP_REPEAT(BOOST_THREAD_MAX_ARGS, BOOST_THREAD_ASYNC_FUNCT, ~)
#undef BOOST_THREAD_RV_REF_ARG_T
#undef BOOST_THREAD_RV_REF_ARG
#undef BOOST_THREAD_FWD_REF_ARG
#undef BOOST_THREAD_FWD_REF_A
#undef BOOST_THREAD_FWD_PARAM
#undef BOOST_THREAD_FWD_PARAM_A
#undef BOOST_THREAD_DCL
#undef BOOST_THREAD_MOVE_PARAM
#undef BOOST_THREAD_MOVE_RHS_PARAM
#undef BOOST_THREAD_MOVE_DCL
#undef BOOST_THREAD_ARG_DEF
#undef BOOST_THREAD_ASYNC_FUNCT
#else
template <class Fp,
class T0 = tuples::null_type, class T1 = tuples::null_type, class T2 = tuples::null_type,
class T3 = tuples::null_type, class T4 = tuples::null_type, class T5 = tuples::null_type,
class T6 = tuples::null_type, class T7 = tuples::null_type, class T8 = tuples::null_type
, class T9 = tuples::null_type
>
class invoker;
template <class Fp,
class T0 , class T1 , class T2 ,
class T3 , class T4 , class T5 ,
class T6 , class T7 , class T8 >
class invoker<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
T7 v7_;
T8 v8_;
//::boost::tuple<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8> f_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7, T8)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
, BOOST_THREAD_RV_REF(T7) a7
, BOOST_THREAD_RV_REF(T8) a8
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
, v7_(boost::move(a7))
, v8_(boost::move(a8))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
, v6_(boost::move(BOOST_THREAD_RV(f).v6_))
, v7_(boost::move(BOOST_THREAD_RV(f).v7_))
, v8_(boost::move(BOOST_THREAD_RV(f).v8_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
, boost::move(v7_)
, boost::move(v8_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
class invoker<Fp, T0, T1, T2, T3, T4, T5, T6, T7>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
T7 v7_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
, BOOST_THREAD_RV_REF(T7) a7
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
, v7_(boost::move(a7))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
, v6_(boost::move(BOOST_THREAD_RV(f).v6_))
, v7_(boost::move(BOOST_THREAD_RV(f).v7_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
, boost::move(v7_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6>
class invoker<Fp, T0, T1, T2, T3, T4, T5, T6>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
, v6_(boost::move(BOOST_THREAD_RV(f).v6_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5>
class invoker<Fp, T0, T1, T2, T3, T4, T5>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4>
class invoker<Fp, T0, T1, T2, T3, T4>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3>
class invoker<Fp, T0, T1, T2, T3>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
);
}
};
template <class Fp, class T0, class T1, class T2>
class invoker<Fp, T0, T1, T2>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
);
}
};
template <class Fp, class T0, class T1>
class invoker<Fp, T0, T1>
{
Fp fp_;
T0 v0_;
T1 v1_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
);
}
};
template <class Fp, class T0>
class invoker<Fp, T0>
{
Fp fp_;
T0 v0_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
);
}
};
template <class Fp>
class invoker<Fp>
{
Fp fp_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp()>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f)
: fp_(boost::move(f))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(f.fp_))
{}
result_type operator()()
{
return fp_();
}
};
template <class R>
class invoker<R(*)()>
{
typedef R(*Fp)();
Fp fp_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp()>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(Fp f)
: fp_(f)
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(f.fp_)
{}
result_type operator()()
{
return fp_();
}
};
#endif
#endif
}
}
#include <boost/thread/detail/variadic_footer.hpp>
#endif // header

View File

@@ -1,8 +1,9 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (C) 2011-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)
//
// See http://www.boost.org/libs/thread for documentation.
//

View File

@@ -1,8 +1,9 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (C) 2011-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)
//
// See http://www.boost.org/libs/thread for documentation.
//
@@ -12,14 +13,11 @@
#define BOOST_THREAD_DETAIL_MEMORY_HPP
#include <boost/config.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
#include <boost/thread/csbl/memory/pointer_traits.hpp>
#include <boost/thread/csbl/memory/allocator_arg.hpp>
#include <boost/thread/csbl/memory/allocator_traits.hpp>
#include <boost/thread/csbl/memory/scoped_allocator.hpp>
namespace boost
{
@@ -28,7 +26,7 @@ namespace boost
template <class _Alloc>
class allocator_destructor
{
typedef container::allocator_traits<_Alloc> alloc_traits;
typedef csbl::allocator_traits<_Alloc> alloc_traits;
public:
typedef typename alloc_traits::pointer pointer;
typedef typename alloc_traits::size_type size_type;
@@ -46,111 +44,5 @@ namespace boost
}
};
} //namespace thread_detail
typedef container::allocator_arg_t allocator_arg_t;
BOOST_CONSTEXPR_OR_CONST allocator_arg_t allocator_arg = {};
template <class T, class Alloc>
struct uses_allocator: public container::uses_allocator<T, Alloc>
{
};
template <class Ptr>
struct pointer_traits
{
typedef Ptr pointer;
// typedef <details> element_type;
// typedef <details> difference_type;
// template <class U> using rebind = <details>;
//
// static pointer pointer_to(<details>);
};
template <class T>
struct pointer_traits<T*>
{
typedef T* pointer;
typedef T element_type;
typedef ptrdiff_t difference_type;
// template <class U> using rebind = U*;
//
// static pointer pointer_to(<details>) noexcept;
};
namespace thread_detail {
template <class _Ptr1, class _Ptr2,
bool = is_same<typename remove_cv<typename pointer_traits<_Ptr1>::element_type>::type,
typename remove_cv<typename pointer_traits<_Ptr2>::element_type>::type
>::value
>
struct same_or_less_cv_qualified_imp
: is_convertible<_Ptr1, _Ptr2> {};
template <class _Ptr1, class _Ptr2>
struct same_or_less_cv_qualified_imp<_Ptr1, _Ptr2, false>
: false_type {};
template <class _Ptr1, class _Ptr2, bool = is_scalar<_Ptr1>::value &&
!is_pointer<_Ptr1>::value>
struct same_or_less_cv_qualified
: same_or_less_cv_qualified_imp<_Ptr1, _Ptr2> {};
template <class _Ptr1, class _Ptr2>
struct same_or_less_cv_qualified<_Ptr1, _Ptr2, true>
: false_type {};
}
template <class T>
struct BOOST_SYMBOL_VISIBLE default_delete
{
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() = default;
#else
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {}
#endif
template <class U>
BOOST_SYMBOL_VISIBLE
default_delete(const default_delete<U>&,
typename enable_if<is_convertible<U*, T*> >::type* = 0) BOOST_NOEXCEPT {}
BOOST_SYMBOL_VISIBLE
void operator() (T* ptr) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
delete ptr;
}
};
template <class T>
struct BOOST_SYMBOL_VISIBLE default_delete<T[]>
{
public:
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() = default;
#else
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {}
#endif
template <class U>
BOOST_SYMBOL_VISIBLE
default_delete(const default_delete<U[]>&,
typename enable_if<thread_detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) BOOST_NOEXCEPT {}
template <class U>
BOOST_SYMBOL_VISIBLE
void operator() (U* ptr,
typename enable_if<thread_detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
delete [] ptr;
}
};
} // namespace boost
}
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP

View File

@@ -9,18 +9,27 @@
#include <boost/thread/detail/config.hpp>
#ifndef BOOST_NO_SFINAE
#include <boost/utility/enable_if.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/decay.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/traits.hpp>
#include <boost/config/abi_prefix.hpp>
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#include <type_traits>
#endif
namespace boost
{
@@ -71,6 +80,7 @@ namespace boost
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
@@ -91,6 +101,7 @@ namespace boost
#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_MSVC
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
@@ -112,6 +123,7 @@ namespace boost
#else
#if defined BOOST_THREAD_USES_MOVE
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
@@ -131,6 +143,7 @@ namespace boost
#else
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) const TYPE&
#define BOOST_THREAD_RV_REF(TYPE) boost::detail::thread_move_t< TYPE >
#define BOOST_THREAD_RV_REF_BEG boost::detail::thread_move_t<
#define BOOST_THREAD_RV_REF_END >
@@ -189,6 +202,8 @@ namespace detail
#define BOOST_THREAD_MOVABLE(TYPE)
#define BOOST_THREAD_COPYABLE(TYPE)
#else
#if defined BOOST_THREAD_USES_MOVE
@@ -211,6 +226,11 @@ namespace detail
return *static_cast<const ::boost::rv<TYPE>* >(this); \
}\
#define BOOST_THREAD_COPYABLE(TYPE) \
TYPE& operator=(TYPE &t)\
{ this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}
#else
#define BOOST_THREAD_MOVABLE(TYPE) \
@@ -224,21 +244,94 @@ namespace detail
return x; \
} \
#define BOOST_THREAD_COPYABLE(TYPE)
#endif
#endif
#define BOOST_THREAD_MOVABLE_ONLY(TYPE) \
BOOST_THREAD_NO_COPYABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
typedef int boost_move_no_copy_constructor_or_assign; \
#define BOOST_THREAD_COPYABLE_AND_MOVABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
BOOST_THREAD_COPYABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
namespace boost
{ namespace thread_detail
{
namespace thread_detail
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#elif defined BOOST_THREAD_USES_MOVE
template <class T>
struct is_rv
: ::boost::move_detail::is_rv<T>
{};
#else
template <class T>
struct is_rv
: ::boost::integral_constant<bool, false>
{};
template <class T>
struct is_rv< ::boost::detail::thread_move_t<T> >
: ::boost::integral_constant<bool, true>
{};
template <class T>
struct is_rv< const ::boost::detail::thread_move_t<T> >
: ::boost::integral_constant<bool, true>
{};
#endif
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class Tp>
struct remove_reference : boost::remove_reference<Tp> {};
template <class Tp>
struct decay : boost::decay<Tp> {};
#else
template <class Tp>
struct remove_reference
{
typedef Tp type;
};
template <class Tp>
struct remove_reference<Tp&>
{
typedef Tp type;
};
template <class Tp>
struct remove_reference< rv<Tp> > {
typedef Tp type;
};
template <class Tp>
struct decay
{
private:
typedef typename boost::move_detail::remove_rvalue_reference<Tp>::type Up0;
typedef typename boost::remove_reference<Up0>::type Up;
public:
typedef typename conditional
<
is_array<Up>::value,
typename remove_extent<Up>::type*,
typename conditional
<
is_function<Up>::value,
typename add_pointer<Up>::type,
typename remove_cv<Up>::type
>::type
>::type type;
};
#endif
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class T>
typename decay<T>::type

View File

@@ -0,0 +1,234 @@
// 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)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
// Make use of Boost.Move
#ifndef BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP
#define BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP
#include <boost/config.hpp>
#include <boost/thread/detail/memory.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/csbl/memory/shared_ptr.hpp>
#include <boost/type_traits/decay.hpp>
namespace boost
{
namespace detail
{
template <typename F>
class nullary_function;
template <>
class nullary_function<void()>
{
struct impl_base
{
virtual void call()=0;
virtual ~impl_base()
{
}
};
csbl::shared_ptr<impl_base> impl;
template <typename F>
struct impl_type: impl_base
{
F f;
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
impl_type(F &f_)
: f(f_)
{}
#endif
impl_type(BOOST_THREAD_RV_REF(F) f_)
: f(boost::move(f_))
{}
void call()
{
f();
}
};
struct impl_type_ptr: impl_base
{
void (*f)();
impl_type_ptr(void (*f_)())
: f(f_)
{}
void call()
{
f();
}
};
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
explicit nullary_function(void (*f)()):
impl(new impl_type_ptr(f))
{}
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename F>
explicit nullary_function(F& f):
impl(new impl_type<F>(f))
{}
#endif
template<typename F>
nullary_function(BOOST_THREAD_RV_REF(F) f):
impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
{}
nullary_function()
: impl()
{
}
nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
impl(other.impl)
{
}
nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
#if defined BOOST_NO_CXX11_SMART_PTR
impl(BOOST_THREAD_RV(other).impl)
{
BOOST_THREAD_RV(other).impl.reset();
}
#else
impl(boost::move(other.impl))
{
}
#endif
~nullary_function()
{
}
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
{
impl=other.impl;
return *this;
}
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
{
#if defined BOOST_NO_CXX11_SMART_PTR
impl=BOOST_THREAD_RV(other).impl;
BOOST_THREAD_RV(other).impl.reset();
#else
impl = boost::move(other.impl);
#endif
return *this;
}
void operator()()
{ if (impl) impl->call();}
};
template <typename R>
class nullary_function<R()>
{
struct impl_base
{
virtual R call()=0;
virtual ~impl_base()
{
}
};
csbl::shared_ptr<impl_base> impl;
template <typename F>
struct impl_type: impl_base
{
F f;
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
impl_type(F &f_)
: f(f_)
{}
#endif
impl_type(BOOST_THREAD_RV_REF(F) f_)
: f(boost::move(f_))
{}
R call()
{
return f();
}
};
struct impl_type_ptr: impl_base
{
R (*f)();
impl_type_ptr(R (*f_)())
: f(f_)
{}
R call()
{
return f();
}
};
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
nullary_function(R (*f)()):
impl(new impl_type_ptr(f))
{}
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename F>
nullary_function(F& f):
impl(new impl_type<F>(f))
{}
#endif
template<typename F>
nullary_function(BOOST_THREAD_RV_REF(F) f):
impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
{}
nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
impl(other.impl)
{
}
nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
#if defined BOOST_NO_CXX11_SMART_PTR
impl(BOOST_THREAD_RV(other).impl)
{
BOOST_THREAD_RV(other).impl.reset();
}
#else
impl(boost::move(other.impl))
{
}
#endif
nullary_function()
: impl()
{
}
~nullary_function()
{
}
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
{
impl=other.impl;
return *this;
}
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
{
#if defined BOOST_NO_CXX11_SMART_PTR
impl=BOOST_THREAD_RV(other).impl;
BOOST_THREAD_RV(other).impl.reset();
#else
impl = boost::move(other.impl);
#endif
return *this;
}
R operator()()
{ if (impl) return impl->call(); else return R();}
};
}
//BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
}
#endif // header

View File

@@ -4,9 +4,10 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-2010 Anthony Williams
// (C) Copyright 20011-2012 Vicente J. Botet Escriba
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/predef/platform.h>
#include <boost/thread/exceptions.hpp>
#ifndef BOOST_NO_IOSTREAM
@@ -24,12 +25,12 @@
#include <boost/assert.hpp>
#include <list>
#include <algorithm>
#include <boost/ref.hpp>
#include <boost/core/ref.hpp>
#include <boost/cstdint.hpp>
#include <boost/bind.hpp>
#include <stdlib.h>
#include <memory>
#include <boost/utility/enable_if.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/io/ios_state.hpp>
#include <boost/type_traits/is_same.hpp>
@@ -64,11 +65,9 @@ namespace boost
{
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
thread_data(BOOST_THREAD_RV_REF(F) f_, BOOST_THREAD_RV_REF(ArgTypes)... args_):
fp(boost::forward<F>(f_), boost::forward<ArgTypes>(args_)...)
{}
#endif
template <std::size_t ...Indices>
void run2(tuple_indices<Indices...>)
{
@@ -174,7 +173,7 @@ namespace boost
private:
bool start_thread_noexcept();
bool start_thread_noexcept(const attributes& attr);
public:
//public:
void start_thread()
{
if (!start_thread_noexcept())
@@ -293,7 +292,8 @@ namespace boost
template <class F>
explicit thread(F f
, typename disable_if_c<
boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
boost::thread_detail::is_rv<F>::value // todo ass a thread_detail::is_rv
//boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
//|| is_same<typename decay<F>::type, thread>::value
, dummy* >::type=0
):
@@ -303,7 +303,8 @@ namespace boost
}
template <class F>
thread(attributes const& attrs, F f
, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
, typename disable_if<boost::thread_detail::is_rv<F>, dummy* >::type=0
//, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
):
thread_info(make_thread_info(f))
{
@@ -334,7 +335,7 @@ namespace boost
start_thread(attrs);
}
#endif
thread(BOOST_THREAD_RV_REF(thread) x)
thread(BOOST_THREAD_RV_REF(thread) x) BOOST_NOEXCEPT
{
thread_info=BOOST_THREAD_RV(x).thread_info;
BOOST_THREAD_RV(x).thread_info.reset();
@@ -466,11 +467,20 @@ namespace boost
inline void join();
#ifdef BOOST_THREAD_USES_CHRONO
#if defined(BOOST_THREAD_PLATFORM_WIN32)
template <class Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
{
chrono::milliseconds rel_time2= chrono::ceil<chrono::milliseconds>(rel_time);
return do_try_join_until(rel_time2.count());
}
#else
template <class Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_join_until(chrono::steady_clock::now() + rel_time);
}
#endif
template <class Clock, class Duration>
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
{
@@ -546,6 +556,7 @@ namespace boost
void detach();
static unsigned hardware_concurrency() BOOST_NOEXCEPT;
static unsigned physical_concurrency() BOOST_NOEXCEPT;
#define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
typedef detail::thread_data_base::native_handle_type native_handle_type;
@@ -749,10 +760,10 @@ namespace boost
#endif
void thread::join() {
if (this_thread::get_id() == get_id())
boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(),
thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")
thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")
);
}
@@ -763,7 +774,7 @@ namespace boost
#endif
{
if (this_thread::get_id() == get_id())
boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
bool res;
if (do_try_join_until_noexcept(timeout, res))
{
@@ -772,7 +783,7 @@ namespace boost
else
{
BOOST_THREAD_THROW_ELSE_RETURN(
(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")),
(thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")),
false
);
}
@@ -826,6 +837,19 @@ namespace boost
};
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
struct shared_state_base;
#if defined(BOOST_THREAD_PLATFORM_WIN32)
inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
{
detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
if(current_thread_data)
{
current_thread_data->make_ready_at_thread_exit(as);
}
}
#else
void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as);
#endif
}
namespace this_thread

View File

@@ -85,7 +85,7 @@ namespace boost
if(thrd)
{
BOOST_THREAD_ASSERT_PRECONDITION( ! is_thread_in(thrd) ,
thread_resource_error(system::errc::resource_deadlock_would_occur, "boost::thread_group: trying to add a duplicated thread")
thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying to add a duplicated thread")
);
boost::lock_guard<shared_mutex> guard(m);
@@ -106,7 +106,7 @@ namespace boost
void join_all()
{
BOOST_THREAD_ASSERT_PRECONDITION( ! is_this_thread_in() ,
thread_resource_error(system::errc::resource_deadlock_would_occur, "boost::thread_group: trying joining itself")
thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying joining itself")
);
boost::shared_lock<shared_mutex> guard(m);

View File

@@ -0,0 +1,10 @@
// 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)
#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif

View File

@@ -0,0 +1,19 @@
// 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)
#include <boost/config.hpp>
//#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#ifndef BOOST_THREAD_MAX_ARGS
#define BOOST_THREAD_MAX_ARGS 9
#endif
//#endif

View File

@@ -0,0 +1,23 @@
// (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)
#ifndef BOOST_THREAD_DETAIL_WORK_HPP
#define BOOST_THREAD_DETAIL_WORK_HPP
#include <boost/thread/detail/nullary_function.hpp>
namespace boost
{
namespace thread_detail
{
typedef detail::nullary_function<void()> work;
}
} // namespace boost
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP

View File

@@ -0,0 +1,44 @@
// Distributed under the 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 2014 Vicente J. Botet Escriba
#ifndef BOOST_THREAD_EXCEPTIONAL_PTR_HPP
#define BOOST_THREAD_EXCEPTIONAL_PTR_HPP
#include <boost/thread/detail/move.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
struct exceptional_ptr {
exception_ptr ptr_;
exceptional_ptr() : ptr_() {}
explicit exceptional_ptr(exception_ptr ex) : ptr_(ex) {}
template <class E>
explicit exceptional_ptr(BOOST_FWD_REF(E) ex) : ptr_(boost::copy_exception(boost::forward<E>(ex))) {}
};
template <class E>
inline exceptional_ptr make_exceptional(BOOST_FWD_REF(E) ex) {
return exceptional_ptr(boost::forward<E>(ex));
}
inline exceptional_ptr make_exceptional(exception_ptr ex)
{
return exceptional_ptr(ex);
}
inline exceptional_ptr make_exceptional()
{
return exceptional_ptr();
}
} // namespace boost
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -124,7 +124,7 @@ namespace boost
typedef thread_exception base_type;
public:
thread_resource_error()
: base_type(system::errc::resource_unavailable_try_again, "boost::thread_resource_error")
: base_type(static_cast<int>(system::errc::resource_unavailable_try_again), "boost::thread_resource_error")
{}
thread_resource_error( int ev )
@@ -152,7 +152,7 @@ namespace boost
typedef thread_exception base_type;
public:
unsupported_thread_option()
: base_type(system::errc::invalid_argument, "boost::unsupported_thread_option")
: base_type(static_cast<int>(system::errc::invalid_argument), "boost::unsupported_thread_option")
{}
unsupported_thread_option( int ev )
@@ -176,7 +176,7 @@ namespace boost
typedef thread_exception base_type;
public:
invalid_thread_argument()
: base_type(system::errc::invalid_argument, "boost::invalid_thread_argument")
: base_type(static_cast<int>(system::errc::invalid_argument), "boost::invalid_thread_argument")
{}
invalid_thread_argument( int ev )
@@ -200,7 +200,7 @@ namespace boost
typedef thread_exception base_type;
public:
thread_permission_error()
: base_type(system::errc::permission_denied, "boost::thread_permission_error")
: base_type(static_cast<int>(system::errc::permission_denied), "boost::thread_permission_error")
{}
thread_permission_error( int ev )

View File

@@ -0,0 +1,15 @@
// 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)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
#ifndef BOOST_THREAD_EXECUTOR_HPP
#define BOOST_THREAD_EXECUTOR_HPP
#include <boost/thread/executors/executor.hpp>
#include <boost/thread/executors/executor_adaptor.hpp>
#endif

View File

@@ -0,0 +1,311 @@
// Copyright (C) 2013-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)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
// first implementation of a simple pool thread using a vector of threads and a sync_queue.
#ifndef BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP
#define BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/csbl/vector.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
class basic_thread_pool
{
public:
/// type-erasure to store the works to do
typedef executors::work work;
private:
/// the kind of stored threads are scoped threads to ensure that the threads are joined.
/// A move aware vector type
typedef scoped_thread<> thread_t;
typedef csbl::vector<thread_t> thread_vector;
/// the thread safe work queue
concurrent::sync_queue<work > work_queue;
/// A move aware vector
thread_vector threads;
public:
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one()
{
try
{
work task;
if (work_queue.try_pull_front(task) == queue_op_status::success)
{
task();
return true;
}
return false;
}
catch (...)
{
std::terminate();
return false;
}
}
/**
* Effects: schedule one task or yields
* Throws: whatever the current task constructor throws or the task() throws.
*/
void schedule_one_or_yield()
{
if ( ! try_executing_one())
{
this_thread::yield();
}
}
private:
/**
* The main loop of the worker threads
*/
void worker_thread()
{
try
{
for(;;)
{
work task;
queue_op_status st = work_queue.wait_pull_front(task);
if (st == queue_op_status::closed) return;
task();
}
}
catch (...)
{
std::terminate();
return;
}
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class AtThreadEntry>
void worker_thread1(AtThreadEntry& at_thread_entry)
{
at_thread_entry(*this);
worker_thread();
}
#endif
void worker_thread2(void(*at_thread_entry)(basic_thread_pool&))
{
at_thread_entry(*this);
worker_thread();
}
template <class AtThreadEntry>
void worker_thread3(BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry)
{
at_thread_entry(*this);
worker_thread();
}
static void do_nothing_at_thread_entry(basic_thread_pool&) {}
public:
/// basic_thread_pool is not copyable.
BOOST_THREAD_NO_COPYABLE(basic_thread_pool)
/**
* \b Effects: creates a thread pool that runs closures on \c thread_count threads.
*
* \b Throws: Whatever exception is thrown while initializing the needed resources.
*/
basic_thread_pool(unsigned const thread_count = thread::hardware_concurrency()+1)
{
try
{
threads.reserve(thread_count);
for (unsigned i = 0; i < thread_count; ++i)
{
#if 1
thread th (&basic_thread_pool::worker_thread, this);
threads.push_back(thread_t(boost::move(th)));
#else
threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
#endif
}
}
catch (...)
{
close();
throw;
}
}
/**
* \b Effects: creates a thread pool that runs closures on \c thread_count threads
* and executes the at_thread_entry function at the entry of each created thread. .
*
* \b Throws: Whatever exception is thrown while initializing the needed resources.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class AtThreadEntry>
basic_thread_pool( unsigned const thread_count, AtThreadEntry& at_thread_entry)
{
try
{
threads.reserve(thread_count);
for (unsigned i = 0; i < thread_count; ++i)
{
thread th (&basic_thread_pool::worker_thread1<AtThreadEntry>, this, at_thread_entry);
threads.push_back(thread_t(boost::move(th)));
//threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
}
}
catch (...)
{
close();
throw;
}
}
#endif
basic_thread_pool( unsigned const thread_count, void(*at_thread_entry)(basic_thread_pool&))
{
try
{
threads.reserve(thread_count);
for (unsigned i = 0; i < thread_count; ++i)
{
thread th (&basic_thread_pool::worker_thread2, this, at_thread_entry);
threads.push_back(thread_t(boost::move(th)));
//threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
}
}
catch (...)
{
close();
throw;
}
}
template <class AtThreadEntry>
basic_thread_pool( unsigned const thread_count, BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry)
{
try
{
threads.reserve(thread_count);
for (unsigned i = 0; i < thread_count; ++i)
{
thread th (&basic_thread_pool::worker_thread3<AtThreadEntry>, this, boost::forward<AtThreadEntry>(at_thread_entry));
threads.push_back(thread_t(boost::move(th)));
//threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
}
}
catch (...)
{
close();
throw;
}
}
/**
* \b Effects: Destroys the thread pool.
*
* \b Synchronization: The completion of all the closures happen before the completion of the \c basic_thread_pool destructor.
*/
~basic_thread_pool()
{
// signal to all the worker threads that there will be no more submissions.
close();
// joins all the threads as the threads were scoped_threads
}
/**
* \b Effects: join all the threads.
*/
void join()
{
for (unsigned i = 0; i < threads.size(); ++i)
{
threads[i].join();
}
}
/**
* \b Effects: close the \c basic_thread_pool for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close()
{
work_queue.close();
}
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed()
{
return work_queue.closed();
}
/**
* \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
*
* \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the \c basic_thread_pool will call \c std::terminate, as is the case with threads.
*
* \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work_queue.push_back(work(closure));
}
#endif
void submit(void (*closure)())
{
work_queue.push_back(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work_queue.push_back(work(boost::forward<Closure>(closure)));
}
/**
* \b Requires: This must be called from an scheduled task.
*
* \b Effects: reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
{
do {
if ( ! try_executing_one())
{
return false;
}
} while (! pred());
return true;
}
};
}
using executors::basic_thread_pool;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,93 @@
// 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)
//
#ifndef SCHEDULED_EXECUTOR_HPP
#define SCHEDULED_EXECUTOR_HPP
#include <boost/atomic.hpp>
#include <boost/function.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/concurrent_queues/sync_timed_queue.hpp>
#include <boost/thread/executors/work.hpp>
namespace boost
{
namespace executors
{
namespace detail
{
class scheduled_executor_base
{
public:
typedef boost::function<void()> work;
//typedef executors::work work;
typedef chrono::steady_clock clock;
typedef clock::duration duration;
typedef clock::time_point time_point;
protected:
concurrent::sync_timed_queue<work> _workq;
scheduled_executor_base() {}
public:
~scheduled_executor_base()
{
if(!closed())
{
this->close();
}
}
void close()
{
_workq.close();
}
bool closed()
{
return _workq.closed();
}
void submit(work w)
{
_workq.push(w, clock::now());
}
void submit_at(work w, const time_point& tp)
{
_workq.push(w, tp);
}
void submit_after(work w, const duration& dura)
{
_workq.push(w, dura);
}
void loop()
{
try
{
for(;;)
{
work task;
queue_op_status st = _workq.wait_pull(task);
if (st == queue_op_status::closed) return;
task();
}
}
catch (...)
{
std::terminate();
return;
}
}
}; //end class
} //end detail namespace
} //end executors namespace
} //end boost namespace
#endif

View File

@@ -0,0 +1,147 @@
// Copyright (C) 2013,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)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
#define BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
class executor
{
public:
/// type-erasure to store the works to do
typedef executors::work work;
/// executor is not copyable.
BOOST_THREAD_NO_COPYABLE(executor)
executor() {}
/**
* \par Effects
* Destroys the executor.
*
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
virtual ~executor() {};
/**
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
virtual void close() = 0;
/**
* \par Returns
* Whether the pool is closed for submissions.
*/
virtual bool closed() = 0;
/**
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
virtual void submit(BOOST_THREAD_RV_REF(work) closure) = 0;
// virtual void submit(work& closure) = 0;
/**
* \par Requires
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
*
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work w ((closure));
submit(boost::move(w));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
submit(boost::move(w));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work w = boost::move(closure);
submit(boost::move(w));
}
/**
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
virtual bool try_executing_one() = 0;
/**
* \par Requires
* This must be called from an scheduled task.
*
* \par Effects
* Reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
{
do {
//schedule_one_or_yield();
if ( ! try_executing_one())
{
return false;
}
} while (! pred());
return true;
}
};
}
using executors::executor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,137 @@
// Copyright (C) 2013,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)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
#define BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
/**
* Polymorphic adaptor of a model of Executor to an executor.
*/
template <typename Executor>
class executor_adaptor : public executor
{
Executor ex;
public:
/// type-erasure to store the works to do
typedef executor::work work;
/// executor is not copyable.
BOOST_THREAD_NO_COPYABLE(executor_adaptor)
/**
* executor_adaptor constructor
*/
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename ...Args>
executor_adaptor(BOOST_THREAD_RV_REF(Args) ... args) : ex(boost::forward<Args>(args)...) {}
#else
/**
* executor_adaptor constructor
*/
executor_adaptor() : ex() {}
template <typename A1>
executor_adaptor(
BOOST_THREAD_FWD_REF(A1) a1
) :
ex(
boost::forward<A1>(a1)
) {}
template <typename A1, typename A2>
executor_adaptor(
BOOST_THREAD_FWD_REF(A1) a1,
BOOST_THREAD_FWD_REF(A2) a2
) :
ex(
boost::forward<A1>(a1),
boost::forward<A2>(a2)
) {}
template <typename A1, typename A2, typename A3>
executor_adaptor(
BOOST_THREAD_FWD_REF(A1) a1,
BOOST_THREAD_FWD_REF(A2) a2,
BOOST_THREAD_FWD_REF(A3) a3
) :
ex(
boost::forward<A1>(a1),
boost::forward<A2>(a2),
boost::forward<A3>(a3)
) {}
#endif
Executor& underlying_executor() { return ex; }
/**
* \b Effects: close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close() { ex.close(); }
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed() { return ex.closed(); }
/**
* \b Effects: The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure) {
return ex.submit(boost::move(closure));
}
// void submit(work & closure) {
// return ex.submit(closure);
// }
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
submit(work(closure));
}
#endif
void submit(void (*closure)())
{
submit(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
submit(work(boost::forward<Closure>(closure)));
}
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one() { return ex.try_executing_one(); }
};
}
using executors::executor_adaptor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,211 @@
// 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)
//
#ifndef BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
#define BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
template <class Executor>
class executor_ref : public executor
{
Executor& ex;
public:
/// type-erasure to store the works to do
typedef executors::work work;
/// executor is not copyable.
BOOST_THREAD_NO_COPYABLE(executor_ref)
executor_ref(Executor& ex) : ex(ex) {}
/**
* \par Effects
* Destroys the executor.
*
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
~executor_ref() {};
/**
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close() { ex.close(); }
/**
* \par Returns
* Whether the pool is closed for submissions.
*/
bool closed() { return ex.closed(); }
/**
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure) {
ex.submit(boost::move(closure));
}
// void submit(work& closure) {
// ex.submit(closure);
// }
/**
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one() { return ex.try_executing_one(); }
};
class generic_executor_ref
{
shared_ptr<executor> ex;
public:
/// type-erasure to store the works to do
typedef executors::work work;
template<typename Executor>
generic_executor_ref(Executor& ex)
//: ex(make_shared<executor_ref<Executor> >(ex)) // todo check why this doesn't works with C++03
: ex( new executor_ref<Executor>(ex) )
{
}
//generic_executor_ref(generic_executor_ref const& other) noexcept {}
//generic_executor_ref& operator=(generic_executor_ref const& other) noexcept {}
/**
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close() { ex->close(); }
/**
* \par Returns
* Whether the pool is closed for submissions.
*/
bool closed() { return ex->closed(); }
void submit(BOOST_THREAD_RV_REF(work) closure)
{
ex->submit(boost::forward<work>(closure));
}
/**
* \par Requires
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
*
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work w ((closure));
submit(boost::move(w));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
submit(boost::move(w));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work w = boost::move(closure);
submit(boost::move(w));
}
// size_t num_pending_closures() const
// {
// return ex->num_pending_closures();
// }
/**
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one() { return ex->try_executing_one(); }
/**
* \par Requires
* This must be called from an scheduled task.
*
* \par Effects
* reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
{
do {
//schedule_one_or_yield();
if ( ! try_executing_one())
{
return false;
}
} while (! pred());
return true;
}
};
}
using executors::executor_ref;
using executors::generic_executor_ref;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,171 @@
// 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)
//
// 2013/11 Vicente J. Botet Escriba
// first implementation of a simple serial scheduler.
#ifndef BOOST_THREAD_INLINE_EXECUTOR_HPP
#define BOOST_THREAD_INLINE_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
class inline_executor
{
public:
/// type-erasure to store the works to do
typedef executors::work work;
bool closed_;
mutable mutex mtx_;
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one()
{
return false;
}
public:
/// inline_executor is not copyable.
BOOST_THREAD_NO_COPYABLE(inline_executor)
/**
* \b Effects: creates a inline executor that runs closures immediately.
*
* \b Throws: Nothing.
*/
inline_executor()
: closed_(false)
{
}
/**
* \b Effects: Destroys the inline executor.
*
* \b Synchronization: The completion of all the closures happen before the completion of the \c inline_executor destructor.
*/
~inline_executor()
{
// signal to all the worker thread that there will be no more submissions.
close();
}
/**
* \b Effects: close the \c inline_executor for submissions.
* The loop will work until there is no more closures to run.
*/
void close()
{
lock_guard<mutex> lk(mtx_);
closed_ = true;
}
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed(lock_guard<mutex>& )
{
return closed_;
}
bool closed()
{
lock_guard<mutex> lk(mtx_);
return closed(lk);
}
/**
* \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
*
* \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the \c inline_executor will call \c std::terminate, as is the case with threads.
*
* \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
try
{
closure();
}
catch (...)
{
std::terminate();
return;
}
}
#endif
void submit(void (*closure)())
{
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
try
{
closure();
}
catch (...)
{
std::terminate();
return;
}
}
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
try
{
closure();
}
catch (...)
{
std::terminate();
return;
}
}
/**
* \b Requires: This must be called from an scheduled task.
*
* \b Effects: reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& )
{
return false;
}
};
}
using executors::inline_executor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,199 @@
// Copyright (C) 2013,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)
//
// 2013/11 Vicente J. Botet Escriba
// first implementation of a simple user scheduler.
// 2013/11 Vicente J. Botet Escriba
// rename loop_executor.
#ifndef BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
#define BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
class loop_executor
{
public:
/// type-erasure to store the works to do
typedef executors::work work;
private:
/// the thread safe work queue
concurrent::sync_queue<work > work_queue;
public:
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one()
{
work task;
try
{
if (work_queue.try_pull_front(task) == queue_op_status::success)
{
task();
return true;
}
return false;
}
catch (...)
{
std::terminate();
return false;
}
}
private:
/**
* Effects: schedule one task or yields
* Throws: whatever the current task constructor throws or the task() throws.
*/
void schedule_one_or_yield()
{
if ( ! try_executing_one())
{
this_thread::yield();
}
}
public:
/// loop_executor is not copyable.
BOOST_THREAD_NO_COPYABLE(loop_executor)
/**
* \b Effects: creates a thread pool that runs closures using one of its closure-executing methods.
*
* \b Throws: Whatever exception is thrown while initializing the needed resources.
*/
loop_executor()
{
}
/**
* \b Effects: Destroys the thread pool.
*
* \b Synchronization: The completion of all the closures happen before the completion of the \c loop_executor destructor.
*/
~loop_executor()
{
// signal to all the worker thread that there will be no more submissions.
close();
}
/**
* The main loop of the worker thread
*/
void loop()
{
while (!closed())
{
schedule_one_or_yield();
}
while (try_executing_one())
{
}
}
/**
* \b Effects: close the \c loop_executor for submissions.
* The loop will work until there is no more closures to run.
*/
void close()
{
work_queue.close();
}
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed()
{
return work_queue.closed();
}
/**
* \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
*
* \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the \c loop_executor will call \c std::terminate, as is the case with threads.
*
* \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work_queue.push_back(work(closure));
}
#endif
void submit(void (*closure)())
{
work_queue.push_back(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work_queue.push_back(work(boost::forward<Closure>(closure)));
}
/**
* \b Requires: This must be called from an scheduled task.
*
* \b Effects: reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
{
do {
if ( ! try_executing_one())
{
return false;
}
} while (! pred());
return true;
}
/**
* run queued closures
*/
void run_queued_closures()
{
sync_queue<work>::underlying_queue_type q = work_queue.underlying_queue();
while (! q.empty())
{
work& task = q.front();
task();
q.pop_front();
}
}
};
}
using executors::loop_executor;
}
#include <boost/config/abi_suffix.hpp>
#endif

Some files were not shown because too many files have changed in this diff Show More