2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-03 21:52:07 +00:00

Compare commits

..

170 Commits

Author SHA1 Message Date
Vicente J. Botet Escriba
6e427659a4 Remove the set_executor promise/packged_task member function. Added a promise constructor taking an Executor as parameter. The packaged_task will come later. 2015-10-29 23:15:48 +01:00
Vicente J. Botet Escriba
c108444e78 s/ex/excp when ex means exception. Mark the executor type erased code. 2015-10-29 18:18:29 +01:00
Vicente J. Botet Escriba
c0317c5206 Add return *this in invoker assignment. 2015-10-29 11:06:48 +01:00
Vicente J. Botet Escriba
06d2571ec6 Merge branch 'master' into develop 2015-10-22 23:05:13 +02:00
Vicente J. Botet Escriba
fdaba4efe7 try to fix Windows issue with system::time_point arithmetic. 2015-10-22 23:04:23 +02:00
Vicente J. Botet Escriba
8a7cd83123 Merge branch 'develop' 2015-10-22 11:22:27 +02:00
Vicente J. Botet Escriba
98a5e343f8 fix compiler error on time_point_cast. 2015-10-22 11:15:20 +02:00
Vicente J. Botet Escriba
89d8e18c82 Merge branch 'develop' 2015-10-22 00:43:17 +02:00
Vicente J. Botet Escriba
d9492530bd fix timi_point conversion. 2015-10-21 20:19:56 +02:00
Vicente J. Botet Escriba
f6c732b124 Merge branch 'develop' 2015-10-21 18:59:44 +02:00
Vicente J. Botet Escriba
dcc3227668 don't use steady clock if not supported. 2015-10-20 10:03:51 +02:00
Vicente J. Botet Escriba
b3d237731a avoid Boost.Test. 2015-10-20 10:03:15 +02:00
Vicente J. Botet Escriba
4321b59c1e Merge branch 'develop' 2015-10-20 00:23:51 +02:00
Vicente J. Botet Escriba
67759325eb update version 2015-10-20 00:23:06 +02:00
Vicente J. Botet Escriba
8153e2a652 try to fix MSVC issue with template class. 2015-10-19 20:01:42 +02:00
Vicente J. Botet Escriba
7876163c68 make sync optional. 2015-10-19 00:50:29 +02:00
Vicente J. Botet Escriba
805fa41a4e try to fix issues with gcc-3.x.y with not supported -Wno-variadic-macros. 2015-10-18 18:50:34 +02:00
Vicente J. Botet Escriba
0e6376d93a make async return a blocking future. 2015-10-18 18:47:24 +02:00
Vicente J. Botet Escriba
bf1fc5158e Added launch::inherit and specialize the behavior for the(launch::inherit, Cont). 2015-10-18 04:17:27 +02:00
Vicente J. Botet Escriba
1e4e9ab84c #11734. future::then(Cont) should be able to execute the contination on undetermined thread. 2015-10-18 00:36:25 +02:00
Vicente J. Botet Escriba
88ab663ac5 Merge branch 'feature/non_blocking_futures' into develop 2015-10-17 14:57:39 +02:00
Vicente J. Botet Escriba
0ab63b9248 Remove counting when async future blocking. 2015-10-17 11:38:06 +02:00
Vicente J. Botet Escriba
73053e4abe merge from develop. 2015-10-17 10:51:50 +02:00
Vicente J. Botet Escriba
9a4fbbec5d Merge branch 'develop' 2015-10-17 08:22:38 +02:00
Vicente J. Botet Escriba
b4744a2aa8 then can be now sync. The destructor of a shared state that joins check for thread_ifbefore join. Adde continuation_shared_state to share common behavior. 2015-10-17 00:44:45 +02:00
Vicente J. Botet Escriba
4169bcee44 Addoverloadsfor shared. 2015-10-17 00:40:53 +02:00
Vicente J. Botet Escriba
baf516e82f comment serial conttest. 2015-10-17 00:40:23 +02:00
Vicente J. Botet Escriba
cc309eef8d refactor ::then(f) in function of ::then(launch_policy, f). 2015-10-15 23:31:38 +02:00
Vicente J. Botet Escriba
45cc1704ef fix some missing decay. Cleanup adding init. 2015-10-15 19:19:07 +02:00
Vicente J. Botet Escriba
278a06fd47 Merge pull request #71 from jhunold/executors_fix
Fix executor forward
2015-10-12 23:49:48 +02:00
Jürgen Hunold
6ed577f4eb Fix executor forward
correct namespace and type
2015-10-12 08:01:19 +02:00
Vicente J. Botet Escriba
bf8459cf23 Merge from develop. 2015-10-11 23:34:45 +02:00
Vicente J. Botet Escriba
ad3cf1189e More fixes for some move semantic issues C++03. 2015-10-11 21:30:54 +02:00
Vicente J. Botet Escriba
b8db8fef8b Use parent executor (#11716). Add promise::set_executor and packaged_task::set_executor (#11717). Fix some move semantic issues C++03. 2015-10-11 19:56:38 +02:00
Vicente J. Botet Escriba
384c71dbe6 minor updates. 2015-10-11 18:45:58 +02:00
Vicente J. Botet Escriba
111574cf0c minor updat on configuration. 2015-10-10 15:47:28 +02:00
Vicente J. Botet Escriba
759601d08a Merge pull request #70 from mauve/fix-provides-executors-doc
doc: add PROVIDES_EXECUTORS to the config table
2015-10-10 10:26:01 +02:00
Vicente J. Botet Escriba
c60d152102 Merge pull request #69 from mauve/fix-then-docs
doc: then() on future take an executor
2015-10-10 10:24:18 +02:00
Mikael Olenfalk
6ff4fe1a89 doc: add PROVIDES_EXECUTORS to the config table 2015-10-10 09:04:38 +02:00
Mikael Olenfalk
2c0c4ead7f doc: then() on future take an executor 2015-10-10 08:54:37 +02:00
Vicente J. Botet Escriba
dacd6deb0a Add static_shared_from_this and make use of it. 2015-10-09 08:53:47 +02:00
Vicente J. Botet Escriba
c7df715709 Merge branch 'develop' 2015-10-06 23:27:17 +02:00
Vicente J. Botet Escriba
ddd26b5bb8 remove comments after \ continuator macro. 2015-10-04 18:06:59 +02:00
Vicente J. Botet Escriba
f0228ff559 fix shared_state_nullary_task_lifetime_issue_bad_use_of_direct_pointer on C++98 compilers. 2015-10-04 02:10:33 +02:00
Vicente J. Botet Escriba
4acaddd166 rollback fix shared_state_nullary_task_lifetime_issue_bad_use_of_direct_pointer on C++98 compilersas there is a compile error to fix. 2015-10-03 20:26:47 +02:00
Vicente J. Botet Escriba
3a65295d7d replace >> by > >. 2015-09-30 23:58:03 +02:00
Vicente J. Botet Escriba
773f8bfcb4 replace >> by > >. 2015-09-30 23:57:00 +02:00
Vicente J. Botet Escriba
8afcbe22af uncomment fixed test after merge from develop. 2015-09-30 00:08:16 +02:00
Vicente J. Botet Escriba
450f34daed merge from develop. 2015-09-30 00:01:33 +02:00
Vicente J. Botet Escriba
ea9eb62802 fix shared_state_nullary_task_lifetime_issue_bad_use_of_direct_pointer. 2015-09-29 21:57:52 +02:00
Vicente J. Botet Escriba
971c028c9a thread::try_join_until: Avoid busy wait if system clock changes. #11688. 2015-09-28 21:46:16 +02:00
Vicente J. Botet Escriba
3f8618b42b update release notes. 2015-09-27 16:27:06 +02:00
Vicente J. Botet Escriba
9a8759a3dd rollback physical_concurrency changes and take care of patch #10788. #11683. 2015-09-27 15:14:58 +02:00
Vicente J. Botet Escriba
9ac736a4c4 Apply patch fromPR - Do not wake up computer from sleep. #11368. 2015-09-27 14:30:16 +02:00
Vicente J. Botet Escriba
730cb550e6 Merge branch 'develop' 2015-09-27 08:24:26 +02:00
Vicente J. Botet Escriba
8f5de1d7c3 make condition_variable_any steady when BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC. 2015-09-25 07:35:25 +02:00
Vicente J. Botet Escriba
0fdd4fc620 remove comments. 2015-09-24 01:36:41 +02:00
Vicente J. Botet Escriba
a86e2ebcc4 Dont use nanosleep on sleep_for if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC. 2015-09-24 01:25:22 +02:00
Vicente J. Botet Escriba
18cbf4b055 rollback reverse the use of dattime and chrono when chrono is acceptable. 2015-09-24 01:24:08 +02:00
Vicente J. Botet Escriba
6029447774 Merge branch 'develop' of github.com:boostorg/thread into develop 2015-09-24 00:08:22 +02:00
Vicente J. Botet Escriba
205a1d7e2b apply patch ref #7720. 2015-09-24 00:07:11 +02:00
Vicente J. Botet Escriba
2af9c7b98e Merge pull request #66 from BenWiederhake/fix-auto-ptr/develop
Avoid deprecated auto_ptr
2015-09-19 19:59:25 +02:00
Ben Wiederhake
baca517058 Avoid deprecated auto_ptr 2015-09-19 18:14:41 +02:00
Vicente J. Botet Escriba
26486b0288 Merge pull request #65 from mclow/develop
Remove use of deprecated macros in documentation
2015-09-12 08:50:27 +02:00
Marshall Clow
f8ff41e34b Remove use of deprecated macros in documentation 2015-09-11 15:30:34 -07:00
Vicente J. Botet Escriba
16ece266a4 Merge pull request #64 from MarcelRaad/patch-1
Fix for future with RTTI off
2015-09-11 18:32:59 +02:00
Marcel Raad
4224a9f4df Fix for future with RTTI off
895b4a0ac5 introduced dynamic_casts. This breaks boost::future with RTTI turned off, which worked before. static_casts should be enough here.
2015-09-11 11:06:32 +02:00
Vicente J. Botet Escriba
2e17e028b1 use serial_executor instead of serial_executor_cont. 2015-09-08 21:55:48 +02:00
Vicente J. Botet Escriba
febe4a814d comment trace to see the error. 2015-09-08 21:39:33 +02:00
Vicente J. Botet Escriba
242cf35c51 Try patch for oldticket #3926 - thread_specific_ptr + dlopen library causes a SIGSEGV 2015-09-08 19:24:15 +02:00
Vicente J. Botet Escriba
c1ee2bfbd8 fix issue with latch:wait when count is already 0. 2015-09-08 18:25:20 +02:00
Vicente J. Botet Escriba
b30cde32d4 reverse the use of dattime and chrono when chrono is acceptable. 2015-09-08 18:22:44 +02:00
Vicente J. Botet Escriba
ac3f7eb037 comment sleep_for overload on nanoseconds on windows. 2015-09-05 16:17:36 +02:00
Vicente J. Botet Escriba
9f883f6ad7 Add a possible implementation of a steady condition_variable. 2015-09-03 23:44:03 +02:00
Vicente J. Botet Escriba
b332f17825 Added failing test for #11611. 2015-09-02 22:39:26 +02:00
Vicente J. Botet Escriba
a3497e1ffc Merge branch 'develop' 2015-08-22 07:20:49 +02:00
Vicente J. Botet Escriba
89b119f65f Merge branch 'develop' of github.com:boostorg/thread into develop 2015-08-21 18:38:14 +02:00
Vicente J. Botet Escriba
1ae07f3f3a Add shared_timed_mutex typedef. 2015-08-21 18:37:42 +02:00
Vicente J. Botet Escriba
0143748de8 Add test_11499. 2015-08-21 18:37:08 +02:00
Vicente J. Botet Escriba
ac603f6bd1 fix devector allocator_traits_type specific usage. 2015-08-21 18:35:36 +02:00
Vicente J. Botet Escriba
6aeac1e33e Merge pull request #61 from jzmaddock/patch-2
Move Oracle workaround to correct location
2015-08-21 00:00:38 +02:00
jzmaddock
ff375e2780 Move Oracle workaround to correct location 2015-08-20 10:51:23 +01:00
Vicente J. Botet Escriba
5b1c755e42 Merge pull request #60 from jzmaddock/patch-1
Fix to get Thread lib building with Oracle C++
2015-08-19 06:33:59 +02:00
jzmaddock
b8dbe960b7 Fix to get Thread lib building with Oracle C++
See https://svn.boost.org/trac/boost/ticket/11550
2015-08-18 18:20:25 +01:00
Vicente J. Botet Escriba
4f9a08c418 fix for(;;){} . 2015-07-01 13:21:39 +02:00
Vicente J. Botet Escriba
44272d3b7c fix for(;;); . 2015-06-29 08:43:01 +02:00
Vicente J. Botet Escriba
ccd1cd5808 fix Link to archived copy of article. 2015-06-28 11:27:02 +02:00
Vicente J. Botet Escriba
8c974800f9 try to remove yet more warnings. 2015-06-23 19:05:32 +02:00
Vicente J. Botet Escriba
6e002ae3ec try to remove more warnings. 2015-06-21 23:09:15 +02:00
Vicente J. Botet Escriba
2a375808c4 Merge branch 'develop' of github.com:boostorg/thread into develop 2015-06-21 17:38:13 +02:00
Vicente J. Botet Escriba
55c21919fc try to remove some warnings. 2015-06-21 17:37:30 +02:00
Vicente J. Botet Escriba
91e2cded63 Merge pull request #57 from MarcelRaad/patch-1
Fix typo
2015-06-05 18:12:58 +02:00
Marcel Raad
b980b88474 Fix typo
There was a typo in the code with both BOOST_USE_WINDOWS_H and BOOST_NO_ANSI_APIS defined.
2015-06-05 17:48:53 +02:00
Vicente J. Botet Escriba
7cb5211e25 fix typo on poly lockables. 2015-05-29 20:02:08 +02:00
Vicente J. Botet Escriba
958b773d05 Merge from develop. 2015-05-18 22:35:17 +02:00
Vicente J. Botet Escriba
4d45da6c06 Apply patch #11302. 2015-05-18 21:26:46 +02:00
Vicente J. Botet Escriba
e39703ff18 Merge branch 'develop' of github.com:boostorg/thread into develop 2015-05-15 15:07:08 +02:00
Vicente J. Botet Escriba
aafd5ca726 applie patch for #11266. 2015-05-15 15:05:09 +02:00
Vicente J. Botet Escriba
9b69912801 Merge pull request #54 from tempoz/patch-5
Remove unused parameter
2015-05-14 18:18:31 +02:00
Vicente J. Botet Escriba
259c08473d Merge branch 'develop' of github.com:boostorg/thread into develop 2015-05-14 18:08:52 +02:00
Vicente J. Botet Escriba
6ca3a99cbc Merge pull request #56 from danieljames/link-fix
Link to archived copy of article.
2015-05-12 22:39:59 +02:00
Daniel James
3dcd875944 Link to archived copy of article.
The original is no longer available.

Fixes: https://svn.boost.org/trac/boost/ticket/11185
2015-05-12 18:52:23 +01:00
Vicente J. Botet Escriba
58e8addad6 Try to get rid of bad link issue while defining global new. 2015-05-06 13:51:21 +02:00
Vicente J. Botet Escriba
87615d54dd cleanup unused function set_exceptional_if_invalid. 2015-05-06 09:48:54 +02:00
Vicente J. Botet Escriba
d322aba077 Merge pull request #55 from jessicah/tests-fix-error-message
Tests: correct #error message in recursive_mutex/native_handle_pass
2015-05-05 20:50:32 +02:00
Jessica Hamilton
c0afe2d873 Tests: correct #error message in recursive_mutex/native_handle_pass 2015-05-06 02:14:13 +12:00
Vicente J. Botet Escriba
5488482a44 simplify launch_continuation interface. 2015-05-04 23:06:39 +02:00
Vicente J. Botet Escriba
1480d6fc99 simplify launch_continuation interface. 2015-05-04 18:24:09 +02:00
Vicente J. Botet Escriba
131c92a7d8 propagate unwrap fixes. 2015-05-04 00:19:12 +02:00
Vicente J. Botet Escriba
71d9a0a120 fix issue with unwrap shared state. Take care of exceptions on the unwrapped future. 2015-05-03 22:52:52 +02:00
Vicente J. Botet Escriba
b7b2a463cf fix issue with unwrap shared state. 2015-05-03 22:32:17 +02:00
Vicente J. Botet Escriba
c50d0ac4ba try to fix issue with continuation on unwrap shared state. 2015-05-03 16:51:41 +02:00
Vicente J. Botet Escriba
1b2736012c Merge branch 'fix/basic_thread_pool_bad_use_of_scoped_thread' into develop 2015-05-03 14:36:57 +02:00
Vicente J. Botet Escriba
5205fa71bf Fixed some missing lock.unlock(). 2015-05-03 14:30:52 +02:00
Vicente J. Botet Escriba
ba2988a8f7 Fixed issue with basic_thread_pool scoped threads. 2015-05-03 10:42:42 +02:00
Vicente J. Botet Escriba
650956bd3b First draft of non-blocking. Fixed issue with basic_thread_pool scoped threads. Now when the result of async(ex,f) is not stored, there is a lifetime issue with shared_state_nullary_task use of direct pointer to the shared state, however there is some weak_ptr issues :(. 2015-05-03 10:13:08 +02:00
Vicente J. Botet Escriba
e598796eaf Add assertion on future continuation parameter is ready. As noted in #11256, there some serious issues with the parameter passed and with lock on locked mutextes :(. 2015-05-02 16:29:06 +02:00
Vicente J. Botet Escriba
bce7eabba2 fix make_exceptional issue. 2015-04-30 01:11:39 +02:00
Vicente J. Botet Escriba
0218136ed7 Try to see if share_from_this helps on the thread sanitize data race. 2015-04-25 15:41:49 +02:00
Vicente J. Botet Escriba
461bf803fc Avoid data race in std::cout. 2015-04-25 11:17:20 +02:00
Vicente J. Botet Escriba
1bd78bbeea cleanup commented code. 2015-04-25 11:16:03 +02:00
Vicente J. Botet Escriba
348da6b7e4 fix memory leack in test. 2015-04-25 10:11:01 +02:00
Vicente J. Botet Escriba
e850218c49 ref #11174 - boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite. 2015-04-25 00:20:53 +02:00
Vicente J. Botet Escriba
385eefd3b3 ref #11174 - boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite. 2015-04-25 00:20:05 +02:00
Zoey Greer
2ddf7aad0b Remove unused parameter
lk is unused in get_state, naming it causes build warnings
2015-04-22 19:37:36 -04:00
Vicente J. Botet Escriba
c9433c2a5b rollback ref #11174 - boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite. 2015-04-22 22:49:26 +02:00
Vicente J. Botet Escriba
8853a4cbdf ref #11174 - boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite. 2015-04-22 07:23:38 +02:00
Vicente J. Botet Escriba
6f53279b50 ref #11174 - boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite. 2015-04-18 19:26:07 +02:00
Vicente J. Botet Escriba
f25bc8bbab Merge branch 'develop' 2015-04-18 11:56:34 +02:00
Vicente J. Botet Escriba
5c442e068c update compliance. 2015-04-18 07:10:43 +02:00
Vicente J. Botet Escriba
0bed674233 ref #11192- boost::future<>::then() with an executor doesn't compile when the callback returns a future 2015-04-18 07:04:50 +02:00
Vicente J. Botet Escriba
66193b0d38 Test with generic lambdas. 2015-04-17 18:31:34 +02:00
Vicente J. Botet Escriba
45c9a1d7fd ref #11192- boost::future<>::then() with an executor doesn't compile when the callback returns a future 2015-04-17 18:30:49 +02:00
Niall Douglas
0d8ddfe378 Merge pull request #51 from MarcelRaad/patch-1
Respect BOOST_USE_WINDOWS_H again
2015-04-03 17:11:17 +01:00
Vicente J. Botet Escriba
74f479d5c9 Fix non_copyable class in queue/dequeue view tests. 2015-03-29 19:34:28 +02:00
Vicente J. Botet Escriba
dbf793e7eb Don't execute test for launch::deferred if BOOST_THREAD_PROVIDES_VARIADIC_THREAD is not defined. 2015-03-29 19:28:05 +02:00
Marcel Raad
b5c6f760c5 Respect BOOST_USE_WINDOWS_H again
With the GetTickCount64 and WinRT fixes, the Windows API functions were always re-declared regardless of BOOST_USE_WINDOWS_H. This breaks clang-cl, which complains about conflicting definitions.
2015-03-26 13:43:44 +01:00
Vicente J. Botet Escriba
0f6a3ebbe5 Merge branch 'develop' 2015-03-21 15:44:02 +01:00
Vicente J. Botet Escriba
a5c34e7be2 update version and copyright. 2015-03-21 15:43:04 +01:00
Vicente J. Botet Escriba
287100119a Merge branch 'develop' 2015-03-17 03:16:35 +01:00
Vicente J. Botet Escriba
ba2f814342 Don't lock while storing the exception_ptr list as only the task_region thread can do it. 2015-03-16 08:41:04 +01:00
Vicente J. Botet Escriba
5169a5414b mutex::unlock must not throw. 2015-03-14 16:26:35 +01:00
Vicente J. Botet Escriba
82b9a4e28c Use coherently size_type. 2015-03-12 04:09:34 +01:00
Vicente J. Botet Escriba
e989d2f626 Add comments. 2015-03-12 04:08:42 +01:00
Vicente J. Botet Escriba
331f0b9325 Added test for future<T&>::get_or. 2015-03-10 07:54:09 +01:00
Vicente J. Botet Escriba
ec6a1fcf80 try to get rid of data race. 2015-03-10 00:48:12 +01:00
Vicente J. Botet Escriba
dcebe26a11 try to get rid of possible deadlock. 2015-03-10 00:47:38 +01:00
Vicente J. Botet Escriba
d7721940f3 update history. 2015-03-09 23:17:35 +01:00
Vicente J. Botet Escriba
b678edb0d8 update history. 2015-03-08 23:31:37 +01:00
Vicente J. Botet Escriba
1371728e02 Merge pull request #50 from wmamrak/develop
Fixed some documentation bugs.
2015-03-06 00:11:52 +01:00
Wojciech Mamrak
17d802db81 Fixed documentation bugs. 2015-03-05 13:22:04 +01:00
Wojciech Mamrak
9fc06a8741 Fixed documentation bugs. 2015-03-05 12:37:10 +01:00
Wojciech Mamrak
946fac633e Fixed documentation bugs. 2015-03-04 12:22:33 +01:00
Wojciech Mamrak
af1c7d0c26 Fixed documentation bugs. 2015-03-03 19:03:18 +01:00
Vicente J. Botet Escriba
d9594e7fc8 Merge branch 'develop' 2015-03-01 18:54:42 +01:00
Vicente J. Botet Escriba
0653efff3d Added this_executor and default_executor examples. 2015-03-01 18:53:11 +01:00
Vicente J. Botet Escriba
566199e49b Added this_executor and default_executor examples. 2015-03-01 18:37:16 +01:00
Vicente J. Botet Escriba
c7bb6fa318 Allow timed and recursive mutex on ANDROID. Related to #11035. 2015-03-01 01:37:45 +01:00
Vicente J. Botet Escriba
c678b3794b Crash issue while calling run_thread_exit_callbacks. Related to #11053. 2015-03-01 01:37:35 +01:00
Vicente J. Botet Escriba
e0ce8af1d9 cleanup work.hpp 2015-02-28 12:39:03 +01:00
Vicente J. Botet Escriba
c54dbe30a2 move the work parameter. 2015-02-28 12:37:27 +01:00
Vicente J. Botet Escriba
b8763b05ad Add missing push(movable&&) and Run some failing tests that work when BOOST_NO_CXX11_RVALUE_REFERENCES is not defined. 2015-02-28 12:35:42 +01:00
Vicente J. Botet Escriba
3755af2063 Run some failing tests that work when BOOST_NO_CXX11_RVALUE_REFERENCES is not defined. 2015-02-28 12:35:23 +01:00
Vicente J. Botet Escriba
41172e4814 fix missing include in caller_context.hpp and let the possibility to dump function at compile time. 2015-02-28 12:33:46 +01:00
Vicente J. Botet Escriba
25310eaf7c make use of nullary_function<void()> as work for timed schedulers (priority_queue) on C++11. 2015-02-22 23:44:34 +01:00
Vicente J. Botet Escriba
55f9563f60 Merge branch 'fix/blocking_future' into develop 2015-02-20 16:36:18 +01:00
Vicente J. Botet Escriba
83ced837fa rollback nullary_function specialization as is the cause of compile failures. 2015-02-20 15:33:26 +01:00
Vicente J. Botet Escriba
ce2b2801d6 Merge branch 'fix/blocking_future' into develop 2015-02-20 14:37:10 +01:00
Vicente J. Botet Escriba
855e56076b Merge branch 'develop' 2015-02-19 08:59:18 +01:00
Vicente J. Botet Escriba
3c6a183aa3 Merge branch 'develop' 2015-02-08 18:19:07 +01:00
112 changed files with 2649 additions and 1259 deletions

View File

@@ -60,7 +60,8 @@ project boost/thread
<toolset>gcc:<cxxflags>-Wno-long-long
#<toolset>gcc:<cxxflags>-ansi
#<toolset>gcc:<cxxflags>-fpermissive
<toolset>gcc:<cxxflags>-Wno-variadic-macros
<toolset>gcc-4:<cxxflags>-Wno-variadic-macros
<toolset>gcc-5:<cxxflags>-Wno-variadic-macros
#<toolset>gcc:<cxxflags>-Wunused-local-typedefs
<toolset>gcc:<cxxflags>-Wunused-function
<toolset>gcc:<cxxflags>-Wno-unused-parameter
@@ -70,7 +71,9 @@ project boost/thread
#<toolset>darwin:<cxxflags>-ansi
<toolset>darwin:<cxxflags>-fpermissive
<toolset>darwin:<cxxflags>-Wno-long-long
<toolset>darwin:<cxxflags>-Wno-variadic-macros
#<toolset>darwin:<cxxflags>-Wno-variadic-macros
<toolset>darwin-4:<cxxflags>-Wno-variadic-macros
<toolset>darwin-5:<cxxflags>-Wno-variadic-macros
#<toolset>darwin:<cxxflags>-Wunused-local-typedefs
<toolset>darwin:<cxxflags>-Wunused-function
<toolset>darwin:<cxxflags>-Wno-unused-parameter

View File

@@ -1,5 +1,6 @@
[/
(C) Copyright 2007-8 Anthony Williams.
(C) Copyright 2012-2015 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).

View File

@@ -1,5 +1,5 @@
[/
/ Copyright (c) 2014 Vicente J. Botet Escriba
/ Copyright (c) 2014-2015 Vicente J. Botet Escriba
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -319,33 +319,23 @@ The reason is that the user can always use a thread_local variable and reset it
}
);
[
[heading Default executor]
The library authors share some of the concerns of the C++ standard committee (introduction of a new single shared resource, a singleton, could make it difficult to make it portable to all the environments) and that this library doesn't need to provide a default executor for the time been.
The user can always define his default executor himself and use the `at_thread_entry ` member function to set the default constructor.
The user can always define his default executor himself.
thread_local default_executor_state_type default_executor_state;
executor* default_executor() { return default_executor_state.default_executor(); }
// in main
MyDefaultExecutor myDefaultExecutor(
// at_thread_entry
[](MyDefaultExecutor& ex) {
default_executor_state.set_default_executor(ex);
}
);
basic_thread_pool pool(
// at_thread_entry
[&myDefaultExecutor](basic_thread_pool& pool) {
default_executor_state.set_default_executor(myDefaultExecutor);
}
);
boost::generic_executor_ref default_executor()
{
static boost::basic_thread_pool tp(4);
return generic_executor_ref(tp);
}
[endsect]
[/////////////////////]
[section:ref Reference]
@@ -421,7 +411,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
[variablelist
[[Effects:] [close the scheduler/executor `e` for submissions.]]
[[Effects:] [close the executor `e` for submissions.]]
[[Remark:] [The worker threads will work until there is no more closures to run.]]
@@ -441,7 +431,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
[[Return type:] [`bool`.]]
[[Return:] [whether the scheduler/executor is closed for submissions.]]
[[Return:] [whether the executor is closed for submissions.]]
[[Throws:] [Whatever exception that can be throw while ensuring the thread safety.]]
@@ -824,7 +814,7 @@ Scheduler providing time related functions. Note that `scheduler` is not an Exec
}
[/////////////////////////////////////]
[section:constructor Constructor `at_executor(Scheduler&)`]
[section:constructor Constructor `at_executor(Scheduler&, clock::time_point const&)`]
at_executor(Scheduler& sch, clock::time_point const& tp);

View File

@@ -1,6 +1,6 @@
[/
(C) Copyright 2007-8 Anthony Williams.
(C) Copyright 2013 Vicente J. Botet Escriba.
(C) Copyright 2013-2015 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).

View File

@@ -1,6 +1,6 @@
[/
(C) Copyright 2007-11 Anthony Williams.
(C) Copyright 2011-14 Vicente J. Botet Escriba.
(C) Copyright 2011-15 Vicente J. Botet Escriba.
Distributed under the 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,46 +8,101 @@
[section:changes History]
[heading Version 4.6.0 - boost 1.60]
[*Know Bugs:]
* [@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/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/10942 #10942] Boost.Thread fails to build on Cygwin.
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 regression test snapshot.
[*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/11231 #11231] Allow to set continuation future's destructor behavior to non-blocking
* [@http://svn.boost.org/trac/boost/ticket/11424 #11424] Provide shared_timed_mutex as an alternative name for shared_mutex and deprecate the use of shared_mutex as a timed mutex
* [@http://svn.boost.org/trac/boost/ticket/11734 #11734] future::then(Cont) should be able to execute the contination on undetermined thread
* [@http://svn.boost.org/trac/boost/ticket/11736 #11736] Allow to use launch::executor on future::then(launch::executor, cont)
* [@http://svn.boost.org/trac/boost/ticket/11737 #11737] Add a launch::inherit policy that can be used on ::then() to use the policy of the parent future
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
* [@http://svn.boost.org/trac/boost/ticket/6377 #6377] Condition variable blocks when changing time
* [@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/7720 #7720] exception lock_error while intensive locking/unlocking of mutex
* [@http://svn.boost.org/trac/boost/ticket/9309 #9309] test_latch fails often on clang-darwin-tot11
* [@http://svn.boost.org/trac/boost/ticket/10788 #10788] GetLogicalProcessor isn't available for Windows platform less or equals to 0x0502
* [@http://svn.boost.org/trac/boost/ticket/11090 #11090] ex_future_unwrap- ThreadSanitizer: lock-order-inversion (potential deadlock)
* [@http://svn.boost.org/trac/boost/ticket/11158 #11158] Pthread thread deadlock when faketime used
* [@http://svn.boost.org/trac/boost/ticket/11174 #11174] boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite
* [@http://svn.boost.org/trac/boost/ticket/11185 #11185] Incorrect URL redirection
* [@http://svn.boost.org/trac/boost/ticket/11192 #11192] boost::future<>::then() with an executor doesn't compile when the callback returns a future
* [@http://svn.boost.org/trac/boost/ticket/11250 #11250] future made from make_exceptional fails on assertion in destructor
* [@http://svn.boost.org/trac/boost/ticket/11256 #11256] future<>::is_ready() == false in continuation function
* [@http://svn.boost.org/trac/boost/ticket/11261 #11261] bad use of scoped threads in basic_thread_pool
* [@http://svn.boost.org/trac/boost/ticket/11262 #11262] bad use of direct pointer in shared_state_nullary_task
* [@http://svn.boost.org/trac/boost/ticket/11263 #11263] lock already locked lock
* [@http://svn.boost.org/trac/boost/ticket/11266 #11266] boost::packaged_task has invalid variadic signature
* [@http://svn.boost.org/trac/boost/ticket/11302 #11302] boost thread doesn't build with BOOST_THREAD_PATCH.
* [@http://svn.boost.org/trac/boost/ticket/11322 #11322] sleep_for() nanoseconds overload will always return too early on windows
* [@http://svn.boost.org/trac/boost/ticket/11329 #11329] using declarative for GetProcessHeap, .... fails
* [@http://svn.boost.org/trac/boost/ticket/11368 #11368] boost thread's usage of CreateWaitableTimer wakes PC from sleep (doh)
* [@http://svn.boost.org/trac/boost/ticket/11377 #11377] Boost condition variable always waits for system clock deadline
* [@http://svn.boost.org/trac/boost/ticket/11435 #11435] gcc compiler warning in future.hpp
* [@http://svn.boost.org/trac/boost/ticket/11555 #11555] devector.hpp assumes allocator_traits_type is always present
* [@http://svn.boost.org/trac/boost/ticket/11562 #11562] Timer (using steady_clock) expires after computer time is set forward on Ubuntu 64-bit
* [@http://svn.boost.org/trac/boost/ticket/11672 #11672] Thread: Should use unique_ptr, not auto_ptr
* [@http://svn.boost.org/trac/boost/ticket/11688 #11688] thread::try_join_until: Avoid busy wait if system clock changes
* [@http://svn.boost.org/trac/boost/ticket/11672 #11716] ::then(f) should inherit the parent Executor
[heading Version 4.5.0 - boost 1.58]
[*Know Bugs:]
* [@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/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
* [@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/9311 #9311] ex_lambda_future fails on msvc-11.0
* [@http://svn.boost.org/trac/boost/ticket/9856 #9856] [windows] condition_variable::wait_for returns wrong cv_status on timeout.
* [@http://svn.boost.org/trac/boost/ticket/10942 #10942] Boost.Thread fails to build on Cygwin.
[/
* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler.
* [@http://svn.boost.org/trac/boost/ticket/10685 #10685] mfc_thread_init.hpp does not compile.
* [@http://svn.boost.org/trac/boost/ticket/10942 #10942] Boost.Thread fails to build on Cygwin.
* [@http://svn.boost.org/trac/boost/ticket/10967 #10967] Timed wait points inconsistently convert relative to absolute waits.
* [@http://svn.boost.org/trac/boost/ticket/10968 #10968] The futures returned by async() and future::then() are not blocking.
]
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.
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last regression test 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 ( [@http://svn.boost.org/trac/boost/ticket/3926 #3926], ),
* timed operation on windows are inconsistent ( [@http://svn.boost.org/trac/boost/ticket/9856 #9856], [@http://svn.boost.org/trac/boost/ticket/10967 #10967]).
* The futures returned by async() and future::then() are not blocking ([@http://svn.boost.org/trac/boost/ticket/10968 #10968]).
[*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/9600 #9600] Async: Add task_region
* [@http://svn.boost.org/trac/boost/ticket/10611 #10611] Add emplace promise::set_value and emplace make_ready_future
* [@http://svn.boost.org/trac/boost/ticket/10826 #10826] Add scheduled executor operations
* [@http://svn.boost.org/trac/boost/ticket/11048 #11048] Add a serial_executor based on continuations
[*Fixed Bugs:]
* [@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/10734 #10734] Submit method work differently on different executors, some throw exception and some silently ignore error (thread_executor and inline_executor)
* [@http://svn.boost.org/trac/boost/ticket/10736 #10736] Task exceptions silently ignored. I think std::terminate solution from N3785 and std::thread is better choice and more consistent.
* [@http://svn.boost.org/trac/boost/ticket/10737 #10737] In serial_executor we have infinite wait if task throw exception.
@@ -55,9 +110,13 @@ There are some severe bugs that prevent the use of the library on concrete conte
* [@http://svn.boost.org/trac/boost/ticket/10824 #10824] Boost.Thread 1.57 breaks Windows XP compatibility for SP2 and below.
* [@http://svn.boost.org/trac/boost/ticket/10963 #10963] future<future<T>>::then Has No Implementation
* [@http://svn.boost.org/trac/boost/ticket/10964 #10964] future<future<T>>::unwrap().then() Deadlocks
* [@http://svn.boost.org/trac/boost/ticket/10968 #10968] The futures returned by async() and future::then() are not blocking.
* [@http://svn.boost.org/trac/boost/ticket/10971 #10971] shared_future::get()/get_or() must be const
* [@http://svn.boost.org/trac/boost/ticket/10972 #10972] shared_future::then() can be called multiple times.
* [@http://svn.boost.org/trac/boost/ticket/10979 #10979] Support T& type deduction when the make_ready_future parameter is reference_wrapper<T>
* [@http://svn.boost.org/trac/boost/ticket/10996 #10996] Thread physical_concurrency() is failing on Windows
* [@http://svn.boost.org/trac/boost/ticket/11035 #11035] BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE not defined for Android
* [@http://svn.boost.org/trac/boost/ticket/11053 #11053] The attached code results in a R6025 - pure virtual function call in run_thread_exit_callbacks
[heading Version 4.4.0 - boost 1.57]
@@ -76,6 +135,7 @@ There are some severe bugs that prevent the use of the library on concrete conte
* [@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.

View File

@@ -1,13 +1,15 @@
[/
(C) Copyright 2011-2013 Vicente J. Botet Escriba.
(C) Copyright 2011-2015 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
]
[section:compliance Conformance and Extension]
[////////////////////////////////////////////]
[section:cpp11 C++11 standard Thread library]
[///////////////////////////////////////////]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 - Standard for Programming Language C++]]]
@@ -88,6 +90,7 @@
]
[endsect]
[section:cxx14 C++14 standard Thread library - accepted changes]
[//////////////////////////////////////////////////////////////]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.html Working Draft, Standard for Programming Language C++]]
@@ -103,6 +106,7 @@
[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]]
@@ -126,8 +130,10 @@
[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 N3600 C++ Latches and Barriers]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3817.html N3817 C++ Latches and Barriers]]
@@ -140,6 +146,7 @@
[endsect]
[section:queue C++ Concurrent Queues]
[///////////////////////////////////]
[note [@ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3533.html N3533 C++ Concurrent Queues]]
@@ -183,24 +190,25 @@
[[X.3.4] [Managed Indirection] [No] [ - ]]
]
[endsect]
[section:executors Asynchronous Executors]
[section:executors Executors and Schedulers]
[//////////////////////////////////////////]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3785.pdf N3785 Executors and Schedulers]]
[table Asynchronous Executors
[table Executors and Schedulers
[[Section] [Description] [Status] [Comments]]
[[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.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.1.2] [`add_at`] [No] [ renamed with a function template `scheduler::submit_at` ]]
[[V.1.2] [`add_after`] [No] [ renamed with a function template `scheduler::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> ]]
[[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>` ]]
]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3784.pdf N3784-Improvements to `std::future<T> and Related APIs]]
@@ -212,8 +220,31 @@
[[30.6.8] [`async`] [Yes] [ - ]]
]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4143.pdf N4143-Executors and schedulers, revision 4]]
[table Executors and Schedulers - revision 4
[[Section] [Description] [Status] [Comments]]
[[VI.A] [Executor Concept] [Yes] [ `wrapper_type` renamed by `work` and `spawn by `submit` ]]
[[VI.A.1] [`thread_per_task_executor] [Yes] [ renamed `thread_executor`]]
[[VI.A.2] [`thread_pool_executor`] [Yes] [ renamed `basic_thread_pool`]]
[[VI.A.3] [`system_executor`] [No] [ - ]]
[[VI.A.4] [`loop_executor`] [Yes] [ - ]]
[[VI.A.5] [`serial_executor`] [yes] [ - ]]
[[VI.B] [`executor_ref`] [yes] [ - ]]
[[VI.C] [`executor`] [yes] [ renamed `gen_executor_ref` ]]
[[VI.D] [Free Functions and Helper Objects] [partial] [ - ]]
[[VI.D] [`make_package`] [No] [ - ]]
[[VI.D] [`spawn_future`] [No] [ `async(Ex&, ...)` is similar but returns a blocking future. ]]
[[VI.D] [`spawn`] [No] [ - ]]
[[VI.D] [`task_wrapper`] [No] [ renamed `resubmitter` ]]
[[VI.D] [`set_executor`] [No] [ renamed `resubmit` ]]
[[VI.D] [`function_wrapper`] [Partial] [ renamed `work` ]]
]
[endsect]
[//////////////////////////////////////////////////////////////
[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.
@@ -241,7 +272,7 @@ While Boost.Thread implementation of stream mutexes differ in the approach, it i
[endsect]
///////////////////////////////]
[endsect]
[endsect]

View File

@@ -1,5 +1,5 @@
[/
(C) Copyright 20012 Vicente J. Botet Escriba.
(C) Copyright 2012-2015 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
@@ -23,6 +23,7 @@
[[PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN] [DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN] [NO] [YES] [YES] ]
[[PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION] [DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSION] [NO] [YES] [YES] ]
[[PROVIDES_EXECUTORS] [-] [NO] [NO] [NO] ]
[[PROVIDES_EXPLICIT_LOCK_CONVERSION] [DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION] [NO] [YES] [YES] ]
[[PROVIDES_FUTURE] [DONT_PROVIDE_FUTURE] [NO] [YES] [YES] ]
[[PROVIDES_FUTURE_CTOR_ALLOCATORS] [DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS] [NO] [YES] [YES] ]

View File

@@ -260,7 +260,7 @@ Locks provide an explicit bool conversion operator when the compiler provides th
The library provides un implicit conversion to an undefined type that can be used as a conditional expression.
#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
operator ``['unspecified-bool-type]``() const;
bool operator!() const;
#else
@@ -346,14 +346,14 @@ use
And instead of
#ifdef BOOST_NO_SCOPED_ENUMS
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
template <>
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type { };
#endif
use
#ifdef BOOST_NO_SCOPED_ENUMS
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
template <>
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { };
#endif

View File

@@ -98,7 +98,7 @@ or inheriting from a class which add these lockable functions.
The `basic_lockable_adapter` class helps to define the `BankAccount` class as
class BankAccount
: public basic_lockable_adapter<thread_mutex>
: public basic_lockable_adapter<boost::mutex>
{
int balance_;
public:
@@ -138,7 +138,7 @@ Notice that now acct is being locked by Withdraw after it has already been locke
As `boost::mutex` is not recursive, we need to use its recursive version `boost::recursive_mutex`.
class BankAccount
: public basic_lockable_adapter<recursive_mutex>
: public basic_lockable_adapter<boost::recursive_mutex>
{
// ...
@@ -147,7 +147,7 @@ As `boost::mutex` is not recursive, we need to use its recursive version `boost:
The caller-ensured locking approach is more flexible and the most efficient, but very dangerous. In an implementation using caller-ensured locking, BankAccount still holds a mutex, but its member functions don't manipulate it at all. Deposit and Withdraw are not thread-safe anymore. Instead, the client code is responsible for locking BankAccount properly.
class BankAccount
: public basic_lockable_adapter<boost:mutex> {
: public basic_lockable_adapter<boost::mutex> {
int balance_;
public:
void Deposit(int amount) {
@@ -271,7 +271,7 @@ Now that we have such a strict `strict_lock`, how do we harness its power in def
A little code is worth 1,000 words, a (hacked into) saying goes, so here's the new BankAccount class:
class BankAccount
: public basic_lockable_adapter<boost:recursive_mutex>
: public basic_lockable_adapter<boost::mutex>
{
int balance_;
public:
@@ -280,7 +280,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n
balance_ += amount;
}
void Deposit(int amount) {
strict_lock<boost:mutex> guard(*this); // Internally locked
strict_lock<BankAccount> guard(*this); // Internally locked
Deposit(amount, guard);
}
void Withdraw(int amount, strict_lock<BankAccount>&) {
@@ -288,7 +288,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n
balance_ -= amount;
}
void Withdraw(int amount) {
strict_lock<boost:mutex> guard(*this); // Internally locked
strict_lock<BankAccount> guard(*this); // Internally locked
Withdraw(amount, guard);
}
};
@@ -327,7 +327,7 @@ The scheme is useful because the likelihood of a programmer forgetting about any
Using `strict_lock` permits compile-time checking of the most common source of errors, and runtime checking of the less frequent problem.
Let's see how to enforce that the appropriate BankAccount object is locked. First, we need to add a member function to the `strict_lock` class template.
The `bool strict_lock<T>::owns_lock(Loclable*)` function returns a reference to the locked object.
The `bool strict_lock<T>::owns_lock(Lockable*)` function returns a reference to the locked object.
template <class Lockable> class strict_lock {
... as before ...
@@ -338,7 +338,7 @@ The `bool strict_lock<T>::owns_lock(Loclable*)` function returns a reference to
Second, BankAccount needs to use this function compare the locked object against this:
class BankAccount {
: public basic_lockable_adapter<boost::recursive_mutex>
: public basic_lockable_adapter<boost::mutex>
int balance_;
public:
void Deposit(int amount, strict_lock<BankAccount>& guard) {
@@ -403,7 +403,7 @@ The solution is to use a little bridge template `externally_locked` that control
T& get(strict_lock<Lockable>& lock) {
#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
if (!lock.owns_lock(&lockable_)) throw lock_error(); //run time check throw if not locks the same
#endif
return obj_;
}
@@ -421,10 +421,10 @@ The solution is to use a little bridge template `externally_locked` that control
Instead of making `checkingAcct_` and `savingsAcct_` of type `BankAccount`, `AccountManager` holds objects of type `externally_locked<BankAccount, AccountManager>`:
class AccountManager
: public basic_lockable_adapter<thread_mutex>
: public basic_lockable_adapter<boost::mutex>
{
public:
typedef basic_lockable_adapter<thread_mutex> lockable_base_type;
typedef basic_lockable_adapter<boost::mutex> lockable_base_type;
AccountManager()
: checkingAcct_(*this)
, savingsAcct_(*this)
@@ -498,7 +498,7 @@ Now we need to state that both classes are `strict_lock`s.
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 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.
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 an exception is thrown.
template <typename Locker >
class nested_strict_lock
@@ -510,7 +510,7 @@ First `nested_strict_lock` class will store on a temporary lock the `Locker`, an
nested_strict_lock(Locker& lock)
: lock_(lock) // Store reference to locker
, tmp_lock_(lock.move()) // Move ownership to temporaty locker
, tmp_lock_(lock.move()) // Move ownership to temporary locker
{
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
if (tmp_lock_.mutex()==0) {

View File

@@ -1,5 +1,6 @@
[/
(C) Copyright 2008-11 Anthony Williams.
(C) Copyright 2012-2015 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
@@ -28,9 +29,11 @@
enum class launch
{
none = unspecified,
async = unspecified,
deferred = unspecified,
executor = unspecified,
inherit = unspecified,
any = async | deferred
};
@@ -164,14 +167,27 @@
enum class launch
{
none = unspecified,
async = unspecified,
deferred = unspecified,
executor = unspecified,
inherit = unspecified,
any = async | deferred
};
The enum type launch is a bitmask type with launch::async and launch::deferred denoting individual bits.
A future created with `promise<>` or with a `packaged_task<>` or with `make_ready_future`/`make_exceptional_future` (has no associated launch policy), has an implicit a launch policy of `launch::none`.
A future created by `async(launch::async, ...)` or `::then(launch::async, ...)` has associated a launch policy `launch::async`.
A future created by `async(launch::deferred, ...)` or `::then(launch::deferred, ...)` has associated a launch policy `launch::deferred`.
A future created by `async(Executor, ...)` or `::then(Executor, ...)` or `::then(launch::executor, ...)` has associated a launch policy `launch::executor`.
A future created by `async(...)` or `::then(...)` has associated a launch policy `launch::none`.
A future created by `::then(launch::inherit, ...)` has associated a launch policy parent future.
The `executor` and the `inherit` launch policies have a sense only can be user only on `then()`.
[endsect]
[///////////////////////////////////////////////////////////////////////////]
[section:is_error_code_enum Specialization `is_error_code_enum<future_errc>`]
@@ -344,7 +360,7 @@ The object's `name` virtual function returns a pointer to the string "future".]]
then(F&& func); // EXTENSION
template<typename S, typename F>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(S& scheduler, F&& func); // EXTENSION
then(Ex& executor, F&& func); // EXTENSION
template<typename F>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(launch policy, F&& func); // EXTENSION
@@ -884,7 +900,7 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
then(F&& func); // EXTENSION
template<typename S, typename F>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(S& scheduler, F&& func); // EXTENSION
then(Ex& executor, F&& func); // EXTENSION
template<typename F>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(launch policy, F&& func); // EXTENSION
@@ -897,29 +913,41 @@ There are not too much tests yet, so it is possible that you can find out some t
[variablelist
[[Notes:] [The three functions differ only by input parameters. The first only takes a callable object which accepts a
future object as a parameter. The second function takes a scheduler as the first parameter and a callable object as
future object as a parameter. The second function takes a executor as the first parameter and a callable object as
the second parameter. The third function takes a launch policy as the first parameter and a callable object as the
second parameter.]]
[[Requires:] [`INVOKE(DECAY_COPY (std::forward<F>(func)), std::move(*this))` shall be a valid expression.]]
[[Effects:] [
All the functions create a shared state that is associated with the returned future object. The further behavior of the functions is as follows.
All the functions create a shared state that is associated with the returned future object. Additionally,
- The continuation is called when the object's shared state is ready (has a value or exception stored).
- When the object's shared state is ready, the continuation
`INVOKE(DECAY_COPY(std::forward<F>(func)), std::move(*this))` is called depending on the overload (see below) with the call to DECAY_COPY() being evaluated in the thread that called then.
- The continuation launches according to the specified policy or scheduler.
- Any value returned from the continuation is stored as the result in the shared state of the resulting `future`.
Any exception propagated from the execution of the continuation is stored as the exceptional result in the shared state of the resulting `future`.
- When the scheduler or launch policy is not provided the continuation inherits the
parent's launch policy or scheduler.
- Any value returned from the continuation is stored as the result in the shared state of the resulting `future`. Any exception propagated from the execution of the continuation is stored as the exceptional result in the shared state of the resulting `future`.
The continuation launches according to the specified policy or executor or noting.
- If the parent was created with `promise<>` or with a `packaged_task<>` (has no associated launch policy), the
continuation behaves the same as the third overload with a policy argument of `launch::async | launch::deferred` and
the same argument for `func`.
- When the launch policy is `launch::none` the continuation is called on an unspecified thread of execution.
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy or
scheduler, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
- When the launch policy is `launch::async` the continuation is called on a new thread of execution.
- When the launch policy is `launch::deferred` the continuation is called on demand.
- When the launch policy is `launch::executor` the continuation is called on one of the thread of execution of the executor.
- When the launch policy is `launch::inherit` the continuation inherits the parent's launch policy or executor.
- When the executor or launch policy is not provided (first overload) is if as if launch::none was specified.
- When the executor is provided (second overload) the continuation is called on one of the thread of execution of the executor.
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy
executor, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
`launch::deferred`.
]]
@@ -1361,7 +1389,7 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
then(F&& func) const; // EXTENSION
template<typename S, typename F>
__unique_future__<typename boost::result_of<F(shared_future)>::type>
then(S& scheduler, F&& func) const; // EXTENSION
then(Ex& executor, F&& func) const; // EXTENSION
template<typename F>
__unique_future__<typename boost::result_of<F(shared_future)>::type>
then(launch policy, F&& func) const; // EXTENSION
@@ -1375,26 +1403,42 @@ There are not too much tests yet, so it is possible that you can find out some t
[variablelist
[[Notes:] [The three functions differ only by input parameters. The first only takes a callable object which accepts a
shared_future object as a parameter. The second function takes a scheduler as the first parameter and a callable object as
shared_future object as a parameter. The second function takes an executor as the first parameter and a callable object as
the second parameter. The third function takes a launch policy as the first parameter and a callable object as the
second parameter.]]
[[Requires:] [`INVOKE(DECAY_COPY (std::forward<F>(func)), *this)` shall be a valid expression.]]
[[Effects:] [
- The continuation is called when the object's shared state is ready (has a value or exception stored).
All the functions create a shared state that is associated with the returned future object. Additionally,
- The continuation launches according to the specified policy or scheduler.
- When the object's shared state is ready, the continuation
`INVOKE(DECAY_COPY(std::forward<F>(func)), *this)` is called depending on the overload (see below) with the call to DECAY_COPY() being evaluated in the thread that called then.
- When the scheduler or launch policy is not provided the continuation inherits the
parent's launch policy or scheduler.
- Any value returned from the continuation is stored as the result in the shared state of the resulting `future`.
Any exception propagated from the execution of the continuation is stored as the exceptional result in the shared state of the resulting `future`.
- If the parent was created with `promise` or with a `packaged_task` (has no associated launch policy), the
continuation behaves the same as the third overload with a policy argument of `launch::async | launch::deferred` and
the same argument for func.
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy or
scheduler, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
`launch::deferred`
The continuation launches according to the specified policy or executor or noting.
- When the launch policy is `launch::none` the continuation is called on an unspecified thread of execution.
- When the launch policy is `launch::async` the continuation is called on a new thread of execution.
- When the launch policy is `launch::deferred` the continuation is called on demand.
- When the launch policy is `launch::executor` the continuation is called on one of the thread of execution of the executor.
- When the launch policy is `launch::inherit` the continuation inherits the parent's launch policy or executor.
- When the executor or launch policy is not provided (first overload) is if as if launch::none was specified.
- When the executor is provided (second overload) the continuation is called on one of the thread of execution of the executor.
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy
executor, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
`launch::deferred`.
]]

View File

@@ -1,5 +1,6 @@
[/
(C) Copyright 2008-11 Anthony Williams.
(C) Copyright 2012-2015 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
@@ -443,10 +444,10 @@ Input Parameters:
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
* Executor: Providing an overload to `.then`, to take a executor 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.
asynchronous operations. The lifetime of the executor must outlive the continuation.
* Launch policy: if the additional flexibility that the executor 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

View File

@@ -2664,7 +2664,7 @@ Only the specificities respect to __Lockable are described here.
[endsect]
[///////////////////////////////]
[section:get2 `get(strict_lock<nested_strict_lock<Lock>>&)`]
[section:get2 `get(nested_strict_lock<Lock>&)`]
template <class Lock>
T& get(nested_strict_lock<Lock>& lk);
@@ -2684,7 +2684,7 @@ Only the specificities respect to __Lockable are described here.
[endsect]
[///////////////////////////////]
[section:get3 `get(strict_lock<nested_strict_lock<Lock>>&)`]
[section:get3 `get(Lock&)`]
template <class Lock>
T& get(Lock& lk);
@@ -2826,7 +2826,7 @@ Only the specificities respect to __Lockable are described here.
[endsect]
[///////////////////////////////]
[section:get2 `get(strict_lock<nested_strict_lock<Lock>>&)`]
[section:get2 `get(nested_strict_lock<Lock>&)`]
template <class Lock>
T& get(nested_strict_lock<Lock>& lk);
@@ -2846,7 +2846,7 @@ Only the specificities respect to __Lockable are described here.
[endsect]
[///////////////////////////////]
[section:get3 `get(strict_lock<nested_strict_lock<Lock>>&)`]
[section:get3 `get(Lock&)`]
template <class Lock>
T& get(Lock& lk);

View File

@@ -181,7 +181,7 @@ where
[variablelist
[[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety.]]
[[Requires:] [Q::value_type is no throw move constructible. This is needed to ensure the exception safety.]]
[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element.]]
@@ -206,7 +206,7 @@ where
[variablelist
[/[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety. ]]
[/[Requires:] [Q::value_type is no throw move assignable. This is needed to ensure the exception safety. ]]
[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element into a shared_ptr.]]
@@ -314,7 +314,7 @@ where
[variablelist
[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
[[Effects:] [If the queue is not empty pulls the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
@@ -393,7 +393,7 @@ where
[endsect]
[/////////////////////////////////////]
[section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve());`]
[section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve);`]
[variablelist
@@ -427,7 +427,7 @@ where
[variablelist
[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
[[Effects:] [If the queue is not empty pulls the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
@@ -636,12 +636,12 @@ Closed queues add the following valid expressions
namespace boost
{
template <typename ValueType>
template <typename ValueType, class SizeType=std::size_t>
class queue_base
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base() {};
@@ -671,7 +671,7 @@ Closed queues add the following valid expressions
virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
virtual queue_op_status wait_pull_front(value_type& elem) = 0;
};
}
@@ -685,11 +685,11 @@ Closed queues add the following valid expressions
namespace boost
{
template <typename Queue>
class queue_adaptor : public queue_base<typename Queue::value_type>
class queue_adaptor : public queue_base<typename Queue::value_type, typename Queue::size_type>
{
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
@@ -1002,13 +1002,13 @@ Closed queues add the following valid expressions
namespace boost
{
template <typename ValueType>
template <typename ValueType, class Container = csbl::devector<ValueType>>
class sync_queue
{
public:
typedef ValueType value_type;
typedef csbl::deque<ValueType> underlying_queue_type;
typedef std::size_t size_type;
typedef Container underlying_queue_type;
typedef typename Container::size_type size_type;
sync_queue(sync_queue const&) = delete;
sync_queue& operator=(sync_queue const&) = delete;

View File

@@ -7,7 +7,9 @@
[section:tutorial Tutorial]
[@http://home.roadrunner.com/~hinnant/mutexes/locking.html Handling mutexes in C++] is an excellent tutorial. You need just replace std and ting by boost.
[@http://web.archive.org/web/20140531071228/http://home.roadrunner.com/~hinnant/mutexes/locking.html Handling mutexes in C++] is an excellent tutorial. You need just replace std and ting by boost.
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html Mutex, Lock, Condition Variable Rationale] adds rationale for the design decisions made for mutexes, locks and condition variables.

View File

@@ -88,9 +88,9 @@
typedef T value_type;
typedef Lockable mutex_type;
synchronized_value() noexept(is_nothrow_default_constructible<T>::value);
synchronized_value(T const& other) noexept(is_nothrow_copy_constructible<T>::value);
synchronized_value(T&& other) noexept(is_nothrow_move_constructible<T>::value);
synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
synchronized_value(synchronized_value const& rhs);
synchronized_value(synchronized_value&& other);
@@ -129,7 +129,7 @@
[section:constructor `synchronized_value()`]
synchronized_value() noexept(is_nothrow_default_constructible<T>::value);
synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
[variablelist
@@ -145,7 +145,7 @@
[section:constructor_vt `synchronized_value(T const&)`]
synchronized_value(T const& other) noexept(is_nothrow_copy_constructible<T>::value);
synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
[variablelist
@@ -175,11 +175,11 @@
[section:move_vt `synchronized_value(T&&)`]
synchronized_value(T&& other) noexept(is_nothrow_move_constructible<T>::value);
synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
[variablelist
[[Requires:] [`T` is `CopyMovable `.]]
[[Requires:] [`T` is `MoveConstructible `.]]
[[Effects:] [Move constructs the cloaked value_type]]
[[Throws:] [Any exception thrown by `value_type(value_type&&)`.]]
@@ -194,7 +194,7 @@
[variablelist
[[Requires:] [`T` is `CopyMovable `.]]
[[Requires:] [`T` is `MoveConstructible `.]]
[[Effects:] [Move constructs the cloaked value_type]]
[[Throws:] [Any exception thrown by `value_type(value_type&&)` or `mtx_.lock()`.]]
@@ -209,7 +209,7 @@
[variablelist
[[Requires:] [`T` is `Assignale`.]]
[[Requires:] [`T` is `Assignable`.]]
[[Effects:] [Copies the underlying value on a scope protected by the two mutexes. The mutex is not copied. The locks are acquired avoiding deadlock. For example, there is no problem if one thread assigns `a = b` and the other assigns `b = a`.]]
[[Return:] [`*this`]]
@@ -224,7 +224,7 @@
[variablelist
[[Requires:] [`T` is `Assignale`.]]
[[Requires:] [`T` is `Assignable`.]]
[[Effects:] [Copies the value on a scope protected by the mutex.]]
[[Return:] [`*this`]]
@@ -273,7 +273,7 @@
[variablelist
[[Requires:] [`T` is `Assignale`.]]
[[Requires:] [`T` is `Assignable`.]]
[[Effects:] [Swaps the data on a scope protected by both mutex. Both mutex are acquired to avoid dead-lock. The mutexes are not swapped.]]
[[Throws:] [Any exception thrown by `swap(value_, rhs.value)` or `mtx_.lock()` or `rhs_.mtx_.lock()`.]]

View File

@@ -8,10 +8,10 @@
[library Thread
[quickbook 1.5]
[version 4.4.0]
[version 4.6.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
[copyright 2011-14 Vicente J. Botet Escriba]
[copyright 2011-15 Vicente J. Botet Escriba]
[purpose C++ Library for launching threads and synchronizing data between them]
[category text]
[license

View File

@@ -0,0 +1,61 @@
// Copyright (C) 2014 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#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/generic_executor_ref.hpp>
#include <string>
#include <iostream>
#include <boost/thread/caller_context.hpp>
boost::generic_executor_ref default_executor()
{
static boost::basic_thread_pool tp(4);
return boost::generic_executor_ref(tp);
}
void p2()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
std::cout << BOOST_CONTEXTOF << std::endl;
}
void p1()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
default_executor().submit(&p2);
boost::this_thread::sleep_for(boost::chrono::milliseconds(400));
std::cout << BOOST_CONTEXTOF << std::endl;
}
int main()
{
std::cout << BOOST_CONTEXTOF << std::endl;
default_executor().submit(&p1);
boost::this_thread::sleep_for(boost::chrono::seconds(5));
std::cout << BOOST_CONTEXTOF << std::endl;
return 1;
}

View File

@@ -7,6 +7,7 @@
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <iostream>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
@@ -27,6 +28,12 @@
#include <boost/assert.hpp>
#include <string>
#include <iostream>
#include <cassert>
boost::future<void> p(boost::future<void> f) {
assert(f.is_ready());
return boost::make_ready_future();
}
void p1()
{
@@ -42,8 +49,9 @@ void p2()
int f1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
std::cout << BOOST_CONTEXTOF << std::endl;
return 1;
}
int f2(int i)
@@ -72,61 +80,95 @@ void at_th_entry(boost::basic_thread_pool& )
int test_executor_adaptor()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
{
boost::executor_adaptor < boost::basic_thread_pool > ea(4);
std::cout << BOOST_CONTEXTOF << std::endl;
submit_some( ea);
std::cout << BOOST_CONTEXTOF << std::endl;
#if 1
// fixme
// ERROR= tr1::bad_weak_ptr
{
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;
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
std::cout << BOOST_CONTEXTOF << std::endl;
submit_some(ea);
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea3(1);
std::cout << BOOST_CONTEXTOF << std::endl;
boost::future<int> t1 = boost::async(ea3, &f1);
std::cout << BOOST_CONTEXTOF << std::endl;
boost::future<int> t2 = boost::async(ea3, &f1);
std::cout << BOOST_CONTEXTOF << std::endl;
//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;
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
#endif
std::cout << BOOST_CONTEXTOF << std::endl;
submit_some(ea);
std::cout << BOOST_CONTEXTOF << std::endl;
}
// std::cout << BOOST_CONTEXTOF << std::endl;
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;
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;
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::inline_executor > ea1;
submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::thread_executor > ea1;
submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
#if 1
// fixme
// ERROR= tr1::bad_weak_ptr
{
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;
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
}
#endif
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::async(&f1);
}
#if 1
// fixme
// ERROR= tr1::bad_weak_ptr
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea(1);
boost::async(ea,&f1);
}
#endif
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
std::cout << BOOST_CONTEXTOF << std::endl;
}
catch (std::exception& ex)
{
@@ -147,4 +189,19 @@ int test_executor_adaptor()
int main()
{
return test_executor_adaptor();
#if 0 && defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
&& defined BOOST_THREAD_PROVIDES_EXECUTORS \
&& ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
boost::basic_thread_pool executor;
// compiles
boost::make_ready_future().then(&p);
// ??
boost::make_ready_future().then(executor, &p);
// doesn't compile
boost::make_ready_future().then(executor, &p);
#endif
}

View File

@@ -58,6 +58,8 @@ int p2(boost::future<int> f)
}
BOOST_THREAD_LOG
<< "P2>" << BOOST_THREAD_END_LOG;
return 0;
}
int p2s(boost::shared_future<int> f)
{
@@ -81,6 +83,7 @@ int p2s(boost::shared_future<int> f)
}
BOOST_THREAD_LOG
<< "P2>" << BOOST_THREAD_END_LOG;
return 0;
}
int main()

View File

@@ -73,7 +73,7 @@ void at_th_entry(boost::basic_thread_pool& )
int test_generic_executor_ref()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
@@ -83,8 +83,8 @@ int test_generic_executor_ref()
{
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;
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
submit_some(ea);
{
@@ -93,41 +93,51 @@ int test_generic_executor_ref()
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;
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;
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;
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;
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::inline_executor ea1;
submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
{
//boost::thread_executor ea1;
//submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
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;
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
}
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea(4, at_th_entry);
boost::async(ea, &f1);
std::cout << BOOST_CONTEXTOF << std::endl;
}
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
std::cout << BOOST_CONTEXTOF << std::endl;
}
catch (std::exception& ex)
{

View File

@@ -42,6 +42,14 @@ int main()
int result = f2.get();
BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG;
}
#if ! defined BOOST_NO_CXX14_GENERIC_LAMBDAS
{
boost::future<int> f1 = boost::async(boost::launch::async, []() {return 123;});
boost::future<int> f2 = f1.then([](auto f) {return 2*f.get(); });
int result = f2.get();
BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG;
}
#endif
}
catch (std::exception& ex)
{

View File

@@ -94,6 +94,11 @@ int main()
f.get();
}
#endif
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::future<int> f = compute(-1);
f.wait();
}
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::future<int> f = compute(0);
@@ -124,11 +129,11 @@ int main()
boost::future<int const&> f = boost::make_ready_future(boost::cref(i));
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::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);

View File

@@ -24,7 +24,7 @@
#endif
#include <boost/thread/concurrent_queues/sync_queue.hpp>
void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
void producer(the_ostream & /*mos*/, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
@@ -32,22 +32,22 @@ void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
{
sbq.push(i);
//sbq << i;
mos << "push(" << i << ") "<< sbq.size()<<"\n";
//mos << "push(" << 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(
the_ostream &mos,
the_ostream & /*mos*/,
boost::sync_queue<int> & sbq)
{
using namespace boost;
@@ -57,21 +57,21 @@ void consumer(
int r;
sbq.pull(r);
//sbq >> r;
mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
//mos << i << " pull(" << 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(the_ostream &mos, boost::sync_queue<int> & sbq)
void consumer2(the_ostream &/*mos*/, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
@@ -81,17 +81,17 @@ void consumer2(the_ostream &mos, boost::sync_queue<int> & sbq)
queue_op_status st = sbq.try_pull(r);
if (queue_op_status::closed == st) break;
if (queue_op_status::success == st) {
mos << i << " pull(" << r << ")\n";
//mos << i << " pull(" << r << ")\n";
}
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
mos << "exception !!!\n";
//mos << "exception !!!\n";
}
}
void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
void consumer3(the_ostream &/*mos*/, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
@@ -100,13 +100,13 @@ void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
int r;
queue_op_status res = sbq.wait_pull(r);
if (res==queue_op_status::closed) break;
mos << i << " wait_pull(" << r << ")\n";
//mos << i << " wait_pull(" << r << ")\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
mos << "exception !!!\n";
//mos << "exception !!!\n";
}
}

View File

@@ -27,7 +27,7 @@
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
void producer(the_ostream &mos, boost::queue_back<int> sbq)
void producer(the_ostream &/*mos*/, boost::queue_back<int> sbq)
{
using namespace boost;
try {
@@ -35,22 +35,22 @@ void producer(the_ostream &mos, boost::queue_back<int> sbq)
{
sbq.push(i);
//sbq << i;
mos << "push(" << i << ") " << sbq.size() <<"\n";
//mos << "push(" << 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(
the_ostream &mos,
the_ostream &/*mos*/,
boost::queue_front<int> sbq)
{
using namespace boost;
@@ -60,21 +60,21 @@ void consumer(
int r;
sbq.pull(r);
//sbq >> r;
mos << i << " pull(" << r << ") " << sbq.size() <<"\n";
//mos << i << " pull(" << 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(the_ostream &mos, boost::queue_front<int> sbq)
void consumer2(the_ostream &/*mos*/, boost::queue_front<int> sbq)
{
using namespace boost;
try {
@@ -84,17 +84,17 @@ void consumer2(the_ostream &mos, boost::queue_front<int> sbq)
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";
//mos << i << " try_pull(" << r << ")\n";
}
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
mos << "exception !!!\n";
//mos << "exception !!!\n";
}
}
void consumer3(the_ostream &mos, boost::queue_front<int> sbq)
void consumer3(the_ostream &/*mos*/, boost::queue_front<int> sbq)
{
using namespace boost;
try {
@@ -103,13 +103,13 @@ void consumer3(the_ostream &mos, boost::queue_front<int> sbq)
int r;
queue_op_status res = sbq.wait_pull(r);
if (res==queue_op_status::closed) break;
mos << i << " wait_pull(" << r << ")\n";
//mos << i << " wait_pull(" << r << ")\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
mos << "exception !!!\n";
//mos << "exception !!!\n";
}
}

View File

@@ -32,7 +32,7 @@ counter c;
void change_count()
{
std::cout << "count == " << c.increment() << std::endl;
//std::cout << "count == " << c.increment() << std::endl;
}
int main(int, char*[])

View File

@@ -27,16 +27,16 @@
void p1()
{
std::cout << BOOST_CONTEXTOF << std::endl;
//std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(30));
std::cout << BOOST_CONTEXTOF << std::endl;
//std::cout << BOOST_CONTEXTOF << std::endl;
}
void p2()
{
std::cout << BOOST_CONTEXTOF << std::endl;
//std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
std::cout << BOOST_CONTEXTOF << std::endl;
//std::cout << BOOST_CONTEXTOF << std::endl;
}
int f1()
@@ -54,7 +54,6 @@ int f2(int i)
void submit_some(boost::serial_executor& tp)
{
std::cout << BOOST_CONTEXTOF << std::endl;
for (int i = 0; i < 3; ++i) {
std::cout << BOOST_CONTEXTOF << std::endl;
tp.submit(&p2);
@@ -63,7 +62,6 @@ void submit_some(boost::serial_executor& tp)
std::cout << BOOST_CONTEXTOF << std::endl;
tp.submit(&p1);
}
std::cout << BOOST_CONTEXTOF << std::endl;
}
@@ -75,13 +73,11 @@ void at_th_entry(boost::basic_thread_pool& )
int test_executor_adaptor()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea1(4);
boost::serial_executor ea2(ea1);
@@ -89,7 +85,6 @@ int test_executor_adaptor()
boost::this_thread::sleep_for(boost::chrono::seconds(10));
}
#endif
// std::cout << BOOST_CONTEXTOF << std::endl;
}
catch (std::exception& ex)
{
@@ -102,7 +97,6 @@ int test_executor_adaptor()
return 2;
}
}
// std::cout << BOOST_CONTEXTOF << std::endl;
return 0;
}

View File

@@ -39,7 +39,7 @@ const char* player_name(int state)
if (state == PLAYER_B)
return "PLAYER-B";
throw "bad player";
return 0;
//return 0;
}
void player(int active)
@@ -50,7 +50,7 @@ void player(int active)
while (state < GAME_OVER)
{
std::cout << player_name(active) << ": Play." << std::endl;
//std::cout << player_name(active) << ": Play." << std::endl;
state = other;
cond.notify_all();
do

86
example/this_executor.cpp Normal file
View File

@@ -0,0 +1,86 @@
// 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_THREAD_ID
#include <boost/thread/caller_context.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executors/generic_executor_ref.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <string>
#include <iostream>
#include <boost/thread/caller_context.hpp>
struct current_executor_state_type {
boost::shared_ptr<boost::generic_executor_ref> current_executor_ptr;
template <class Executor>
void set_current_executor(Executor& ex)
{
current_executor_ptr = boost::make_shared<boost::generic_executor_ref>(ex);
}
boost::generic_executor_ref current_executor()
{
if (current_executor_ptr)
return *current_executor_ptr;
else
throw "";
}
};
thread_local current_executor_state_type current_executor_state;
boost::generic_executor_ref current_executor()
{
return current_executor_state.current_executor();
}
void p2()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
std::cout << BOOST_CONTEXTOF << std::endl;
}
void p1()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
current_executor().submit(&p2);
boost::this_thread::sleep_for(boost::chrono::milliseconds(400));
std::cout << BOOST_CONTEXTOF << std::endl;
}
int main()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::basic_thread_pool tp(4,
// at_thread_entry
[](boost::basic_thread_pool& pool)
{
current_executor_state.set_current_executor(pool);
}
);
tp.submit(&p1);
boost::this_thread::sleep_for(boost::chrono::seconds(5));
std::cout << BOOST_CONTEXTOF << std::endl;
return 1;
}

View File

@@ -59,6 +59,7 @@ int main()
threads.remove_thread(th);
BOOST_TEST(! threads.is_thread_in(th));
th->join();
delete th;
}
{
{

View File

@@ -24,6 +24,7 @@ void thread_proc()
increment();
int* p = value.get();
assert(*p == i+1);
(void)(p);
}
}

View File

@@ -1,4 +1,4 @@
// (C) Copyright 2013 Vicente J. Botet Escriba
// (C) Copyright 2013,2015 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -12,6 +12,7 @@
#include <boost/thread/thread.hpp>
#endif
#include <boost/current_function.hpp>
#include <boost/io/ios_state.hpp>
#include <iomanip>
#include <boost/config/abi_prefix.hpp>
@@ -43,9 +44,11 @@ namespace boost
#endif
{
io::ios_flags_saver ifs(os);
os << ctx.filename << "["
os << std::setw(50) << ctx.filename << "["
<< std::setw(4) << std::right << std::dec<< ctx.lineno << "] ";
#if defined BOOST_THREAD_USES_LOG_CURRENT_FUNCTION
os << ctx.func << " " ;
#endif
}
return os;
}

View File

@@ -27,12 +27,12 @@ namespace detail
template <typename Queue>
class deque_adaptor_copyable_only :
public boost::deque_base<typename Queue::value_type>
public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
deque_adaptor_copyable_only() {}
@@ -63,12 +63,12 @@ namespace detail
};
template <typename Queue>
class deque_adaptor_movable_only :
public boost::deque_base<typename Queue::value_type>
public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
@@ -102,12 +102,12 @@ namespace detail
template <typename Queue>
class deque_adaptor_copyable_and_movable :
public boost::deque_base<typename Queue::value_type>
public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
@@ -195,7 +195,7 @@ namespace detail
{
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
virtual ~deque_adaptor() {};
};

View File

@@ -27,12 +27,12 @@ namespace concurrent
namespace detail
{
template <typename ValueType>
template <typename ValueType, class SizeType>
class deque_base_copyable_only
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~deque_base_copyable_only() {};
@@ -58,16 +58,16 @@ namespace detail
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 queue_op_status wait_pull_front(value_type& elem) = 0;
};
template <typename ValueType>
template <typename ValueType, class SizeType>
class deque_base_movable_only
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~deque_base_movable_only() {};
@@ -88,7 +88,7 @@ namespace detail
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
virtual queue_op_status wait_pull_front(value_type& 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;
@@ -97,12 +97,12 @@ namespace detail
};
template <typename ValueType>
template <typename ValueType, class SizeType>
class deque_base_copyable_and_movable
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~deque_base_copyable_and_movable() {};
@@ -129,7 +129,7 @@ namespace detail
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 queue_op_status wait_pull_front(value_type& 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;
@@ -137,7 +137,7 @@ namespace detail
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
};
template <class T,
template <class T, class ST,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__ && ! defined __clang__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
@@ -166,28 +166,28 @@ namespace detail
>
struct deque_base;
template <class T>
struct deque_base<T, true, true> {
typedef deque_base_copyable_and_movable<T> type;
template <class T, class ST>
struct deque_base<T, ST, true, true> {
typedef deque_base_copyable_and_movable<T, ST> type;
};
template <class T>
struct deque_base<T, true, false> {
typedef deque_base_copyable_only<T> type;
template <class T, class ST>
struct deque_base<T, ST, true, false> {
typedef deque_base_copyable_only<T, ST> type;
};
template <class T>
struct deque_base<T, false, true> {
typedef deque_base_movable_only<T> type;
template <class T, class ST>
struct deque_base<T, ST, false, true> {
typedef deque_base_movable_only<T, ST> type;
};
}
template <typename ValueType>
template <class ValueType, class SizeType=std::size_t>
class deque_base :
public detail::deque_base<ValueType>::type
public detail::deque_base<ValueType, SizeType>::type
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~deque_base() {};
};

View File

@@ -37,7 +37,7 @@ namespace detail
public:
typedef ValueType value_type;
typedef Queue underlying_queue_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
typedef queue_op_status op_status;
typedef typename chrono::steady_clock clock;

View File

@@ -37,7 +37,7 @@ namespace detail
public:
typedef ValueType value_type;
typedef Queue underlying_queue_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
typedef queue_op_status op_status;
typedef typename chrono::steady_clock clock;

View File

@@ -27,12 +27,12 @@ namespace detail
template <typename Queue>
class queue_adaptor_copyable_only :
public boost::queue_base<typename Queue::value_type>
public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_adaptor_copyable_only() {}
@@ -63,12 +63,12 @@ namespace detail
};
template <typename Queue>
class queue_adaptor_movable_only :
public boost::queue_base<typename Queue::value_type>
public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
@@ -102,12 +102,12 @@ namespace detail
template <typename Queue>
class queue_adaptor_copyable_and_movable :
public boost::queue_base<typename Queue::value_type>
public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
@@ -195,7 +195,7 @@ namespace detail
{
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
virtual ~queue_adaptor() {};
};

View File

@@ -27,12 +27,12 @@ namespace concurrent
namespace detail
{
template <typename ValueType>
template <typename ValueType, class SizeType>
class queue_base_copyable_only
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_copyable_only() {};
@@ -62,12 +62,12 @@ namespace detail
};
template <typename ValueType>
template <typename ValueType, class SizeType>
class queue_base_movable_only
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_movable_only() {};
@@ -88,7 +88,7 @@ namespace detail
virtual queue_op_status nonblocking_pull(value_type&) = 0;
virtual queue_op_status wait_pull(ValueType& elem) = 0;
virtual queue_op_status wait_pull(value_type& elem) = 0;
virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
@@ -97,12 +97,12 @@ namespace detail
};
template <typename ValueType>
template <typename ValueType, class SizeType>
class queue_base_copyable_and_movable
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_copyable_and_movable() {};
@@ -129,7 +129,7 @@ namespace detail
virtual queue_op_status nonblocking_pull(value_type&) = 0;
virtual queue_op_status wait_push(const value_type& x) = 0;
virtual queue_op_status wait_pull(ValueType& elem) = 0;
virtual queue_op_status wait_pull(value_type& elem) = 0;
virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
@@ -137,7 +137,7 @@ namespace detail
virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
};
template <class T,
template <class T, class ST,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__ && ! defined __clang__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
@@ -166,28 +166,28 @@ namespace detail
>
struct queue_base;
template <class T>
struct queue_base<T, true, true> {
typedef queue_base_copyable_and_movable<T> type;
template <class T, class ST>
struct queue_base<T, ST, true, true> {
typedef queue_base_copyable_and_movable<T, ST> type;
};
template <class T>
struct queue_base<T, true, false> {
typedef queue_base_copyable_only<T> type;
template <class T, class ST>
struct queue_base<T, ST, true, false> {
typedef queue_base_copyable_only<T, ST> type;
};
template <class T>
struct queue_base<T, false, true> {
typedef queue_base_movable_only<T> type;
template <class T, class ST>
struct queue_base<T, ST, false, true> {
typedef queue_base_movable_only<T, ST> type;
};
}
template <typename ValueType>
template <typename ValueType, class SizeType=std::size_t>
class queue_base :
public detail::queue_base<ValueType>::type
public detail::queue_base<ValueType, SizeType>::type
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base() {};
};

View File

@@ -43,12 +43,13 @@ namespace detail {
Compare _compare;
public:
typedef Type value_type;
typedef typename Container::size_type size_type;
explicit priority_queue(const Compare& compare = Compare())
: _elements(), _compare(compare)
{ }
std::size_t size() const
size_type size() const
{
return _elements.size();
}

View File

@@ -10,6 +10,7 @@
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <boost/thread/detail/config.hpp>
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
@@ -150,13 +151,19 @@ namespace concurrent
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem, unique_lock<mutex>& lk)
{
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
if (super::empty(lk))
{
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
if (super::closed(lk)) return queue_op_status::closed;
}
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
if (has_been_closed) return queue_op_status::closed;
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
pull(elem, lk);
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
return queue_op_status::success;
}

View File

@@ -106,6 +106,11 @@ namespace detail
template <class Rep, class Period>
void push(const T& elem, chrono::duration<Rep,Period> const& dura);
template <class Duration>
void push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp);
template <class Rep, class Period>
void push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura);
template <class Duration>
queue_op_status try_push(const T& elem, chrono::time_point<clock,Duration> const& tp);
template <class Rep, class Period>
@@ -158,6 +163,22 @@ namespace detail
push(elem, clock::now() + dura);
}
template <class T, class Clock>
template <class Duration>
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
{
super::push(stype(boost::move(elem),tp));
}
template <class T, class Clock>
template <class Rep, class Period>
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
{
push(boost::move(elem), clock::now() + dura);
}
template <class T, class Clock>
template <class Duration>
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp)
@@ -214,7 +235,7 @@ namespace detail
if (super::closed(lk)) return true;
super::not_empty_.wait(lk);
}
return false;
//return false;
}
///////////////////////////

View File

@@ -21,8 +21,8 @@ namespace boost
template <class T>
class devector
{
typedef vector<T> vector_type;
vector<T> data_;
typedef csbl::vector<T> vector_type;
vector_type data_;
std::size_t front_index_;
BOOST_COPYABLE_AND_MOVABLE(devector)
@@ -58,7 +58,9 @@ namespace boost
}
devector& operator=(BOOST_RV_REF(devector) x)
BOOST_NOEXCEPT_IF(vector<T>::allocator_traits_type::propagate_on_container_move_assignment::value)
#if defined BOOST_THREAD_USES_BOOST_VECTOR
BOOST_NOEXCEPT_IF(vector_type::allocator_traits_type::propagate_on_container_move_assignment::value)
#endif
{
data_ = boost::move(x.data_);
front_index_ = x.front_index_;

View File

@@ -72,13 +72,21 @@ namespace boost
BOOST_SYMBOL_VISIBLE
invoker& operator=(BOOST_THREAD_RV_REF(invoker) f)
{
f_ = boost::move(BOOST_THREAD_RV(f).f_);
if (this != &f)
{
f_ = boost::move(BOOST_THREAD_RV(f).f_);
}
return *this;
}
BOOST_SYMBOL_VISIBLE
invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f)
{
f_ = f.f_;
if (this != &f)
{
f_ = f.f_;
}
return *this;
}
result_type operator()()

View File

@@ -94,6 +94,11 @@ namespace boost
template <typename T> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
namespace detail { \
template <typename T1, typename T2> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, false> \
{}; \
@@ -115,6 +120,11 @@ namespace boost
template <typename T> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
namespace detail { \
template <typename T1, typename T2> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, false> \
{}; \
@@ -136,6 +146,11 @@ namespace boost
template <typename T> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
namespace detail { \
template <typename T1, typename T2> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, false> \
{}; \
@@ -161,6 +176,10 @@ struct enable_move_utility_emulation< TYPE > \
template <typename T> \
struct enable_move_utility_emulation<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
template <typename T1, typename T2> \
struct enable_move_utility_emulation<
#define BOOST_THREAD_DCL_MOVABLE_END > \
{ \
static const bool value = false; \

View File

@@ -228,7 +228,7 @@ namespace boost
};
}
//BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
}
#endif // header

View File

@@ -173,7 +173,6 @@ namespace boost
private:
bool start_thread_noexcept();
bool start_thread_noexcept(const attributes& attr);
//public:
void start_thread()
{
if (!start_thread_noexcept())
@@ -485,9 +484,9 @@ namespace boost
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
bool joined= false;
do {
system_clock::time_point s_now = system_clock::now();
typename Clock::duration d = ceil<nanoseconds>(t-Clock::now());
if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached
joined = try_join_until(s_now + d);

View File

@@ -6,6 +6,7 @@
// (C) Copyright 2007-9 Anthony Williams
#include <list>
#include <boost/thread/csbl/memory/unique_ptr.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/lock_guard.hpp>
@@ -75,7 +76,7 @@ namespace boost
thread* create_thread(F threadfunc)
{
boost::lock_guard<shared_mutex> guard(m);
std::auto_ptr<thread> new_thread(new thread(threadfunc));
boost::csbl::unique_ptr<thread> new_thread(new thread(threadfunc));
threads.push_back(new_thread.get());
return new_thread.release();
}

View File

@@ -13,7 +13,7 @@
#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/thread.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/csbl/vector.hpp>
@@ -30,15 +30,14 @@ namespace executors
/// 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.
typedef thread thread_t;
/// 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;
/// the thread safe work queue
concurrent::sync_queue<work > work_queue;
public:
/**
@@ -61,7 +60,7 @@ namespace executors
catch (...)
{
std::terminate();
return false;
//return false;
}
}
/**
@@ -88,7 +87,9 @@ namespace executors
{
work task;
queue_op_status st = work_queue.wait_pull(task);
if (st == queue_op_status::closed) return;
if (st == queue_op_status::closed) {
return;
}
task();
}
}
@@ -222,7 +223,8 @@ namespace executors
{
// signal to all the worker threads that there will be no more submissions.
close();
// joins all the threads as the threads were scoped_threads
// joins all the threads before destroying the thread pool resources (e.g. the queue).
join();
}
/**
@@ -264,23 +266,28 @@ namespace executors
* \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) {
work_queue.push(boost::move(closure));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work_queue.push(work(closure));
submit(work(closure));
}
#endif
void submit(void (*closure)())
{
work_queue.push(work(closure));
submit(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
work_queue.push(work(boost::forward<Closure>(closure)));
//submit(work(boost::forward<Closure>(closure)));
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
/**

View File

@@ -24,8 +24,8 @@ namespace detail
class priority_executor_base
{
public:
typedef boost::function<void()> work;
//typedef executors::work work;
//typedef boost::function<void()> work;
typedef executors::work_pq work;
protected:
typedef Queue queue_type;
queue_type _workq;

View File

@@ -1,5 +1,5 @@
// Copyright (C) 2014 Ian Forbed
// Copyright (C) 2014 Vicente J. Botet Escriba
// Copyright (C) 2014-2015 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,6 +16,8 @@
#include <boost/atomic.hpp>
#include <boost/function.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
@@ -23,11 +25,10 @@ namespace executors
namespace detail
{
template <class Clock=chrono::steady_clock>
class scheduled_executor_base : public priority_executor_base<concurrent::sync_timed_queue<boost::function<void()>, Clock > >
class scheduled_executor_base : public priority_executor_base<concurrent::sync_timed_queue<executors::work_pq, Clock > >
{
public:
typedef boost::function<void()> work;
//typedef executors::work work;
typedef executors::work_pq work;
typedef Clock clock;
typedef typename clock::duration duration;
typedef typename clock::time_point time_point;
@@ -46,12 +47,12 @@ namespace detail
void submit_at(work w, const time_point& tp)
{
this->_workq.push(w, tp);
this->_workq.push(boost::move(w), tp);
}
void submit_after(work w, const duration& dura)
{
this->_workq.push(w, dura+clock::now());
this->_workq.push(boost::move(w), dura+clock::now());
}
}; //end class
@@ -59,4 +60,7 @@ namespace detail
} //end detail namespace
} //end executors namespace
} //end boost namespace
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -99,9 +99,10 @@ namespace boost
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
work w = boost::move(closure);
//submit(work(boost::forward<Closure>(closure)));
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}

View File

@@ -98,9 +98,6 @@ namespace executors
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>
@@ -115,9 +112,11 @@ namespace executors
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
submit(work(boost::forward<Closure>(closure)));
//submit(work(boost::forward<Closure>(closure)));
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
/**

View File

@@ -121,11 +121,6 @@ namespace boost
*/
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.
@@ -142,24 +137,31 @@ namespace boost
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure)
{
ex->submit(boost::move(closure));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work w ((closure));
submit(boost::move(w));
//work w ((closure));
//submit(boost::move(w));
submit(work(closure));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
submit(boost::move(w));
//submit(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
work w = boost::move(closure);
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}

View File

@@ -54,7 +54,7 @@ namespace executors
catch (...)
{
std::terminate();
return false;
//return false;
}
}
private:
@@ -138,23 +138,29 @@ namespace executors
* \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) {
work_queue.push(boost::move(closure));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work_queue.push(work(closure));
}
submit(work(closure));
}
#endif
void submit(void (*closure)())
{
work_queue.push(work(closure));
submit(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
work_queue.push(work(boost::forward<Closure>(closure)));
//work_queue.push(work(boost::forward<Closure>(closure)));
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
/**

View File

@@ -82,7 +82,7 @@ namespace executors
catch (...)
{
std::terminate();
return false;
//return false;
}
}
private:
@@ -165,23 +165,28 @@ namespace executors
* \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)
{
work_queue.push(boost::move(closure));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work_queue.push(work(closure));
submit(work(closure));
}
#endif
void submit(void (*closure)())
{
work_queue.push(work(closure));
submit(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
work_queue.push(work(boost::forward<Closure>(closure)));
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
/**

View File

@@ -153,7 +153,7 @@ namespace executors
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );

View File

@@ -8,36 +8,23 @@
#define BOOST_THREAD_EXECUTORS_WORK_HPP
#include <boost/thread/detail/config.hpp>
#if ! defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE \
&& ! defined BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
#define BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
//#define BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
#endif
#if defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
#include <boost/thread/detail/nullary_function.hpp>
namespace boost
{
namespace executors
{
typedef detail::nullary_function<void()> work;
}
} // namespace boost
#else
#include <boost/thread/csbl/functional.hpp>
namespace boost
{
namespace executors
{
typedef csbl::function<void()> work;
typedef detail::nullary_function<void()> work;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef detail::nullary_function<void()> work_pq;
//typedef csbl::function<void()> work_pq;
#else
typedef csbl::function<void()> work_pq;
#endif
}
} // namespace boost
#endif
#endif // BOOST_THREAD_EXECUTORS_WORK_HPP

View File

@@ -3,7 +3,7 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost
// (C) Copyright Vicente J. Botet Escriba 2014-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -50,12 +50,13 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
void handle_task_region_exceptions(exception_list& errors)
{
try {
boost::rethrow_exception(boost::current_exception());
//throw boost::current_exception();
throw;
}
catch (task_canceled_exception& ex)
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
catch (task_canceled_exception&)
{
}
#endif
catch (exception_list const& el)
{
for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it)
@@ -94,7 +95,7 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
{
lock_guard<mutex> lk(tr.mtx);
tr.canceled = true;
handle_task_region_exceptions(tr.exs);
throw;
}
}
};
@@ -123,8 +124,6 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
{
wait_for_all(group.begin(), group.end());
#if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
for (group_type::iterator it = group.begin(); it != group.end(); ++it)
{
future<void>& f = *it;
@@ -140,11 +139,9 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
}
}
}
#endif
if (exs.size() != 0)
{
boost::throw_exception(exs);
//throw exs;
}
}
protected:
@@ -187,6 +184,7 @@ protected:
}
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
mutable mutex mtx;
bool canceled;
#endif
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
@@ -195,8 +193,6 @@ protected:
exception_list exs;
typedef csbl::vector<future<void> > group_type;
group_type group;
mutable mutex mtx;
public:
BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&))
@@ -207,11 +203,12 @@ protected:
template<typename F>
void run(BOOST_THREAD_FWD_REF(F) f)
{
lock_guard<mutex> lk(mtx);
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
if (canceled) {
boost::throw_exception(task_canceled_exception());
//throw task_canceled_exception();
{
lock_guard<mutex> lk(mtx);
if (canceled) {
boost::throw_exception(task_canceled_exception());
}
}
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
group.push_back(async(*ex, detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f))));
@@ -229,11 +226,12 @@ protected:
void wait()
{
lock_guard<mutex> lk(mtx);
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
if (canceled) {
boost::throw_exception(task_canceled_exception());
//throw task_canceled_exception{};
{
lock_guard<mutex> lk(mtx);
if (canceled) {
boost::throw_exception(task_canceled_exception());
}
}
#endif
wait_all();
@@ -276,7 +274,6 @@ protected:
}
catch (...)
{
lock_guard<mutex> lk(tr.mtx);
detail::handle_task_region_exceptions(tr.exs);
}
tr.wait_all();
@@ -298,7 +295,6 @@ protected:
}
catch (...)
{
lock_guard<mutex> lk(tr.mtx);
detail::handle_task_region_exceptions(tr.exs);
}
tr.wait_all();

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,7 @@ namespace boost
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
executor = 4,
#endif
inherit = 8,
any = async | deferred
}
BOOST_SCOPED_ENUM_DECLARE_END(launch)

View File

@@ -72,6 +72,7 @@ namespace boost
void wait()
{
boost::unique_lock<boost::mutex> lk(mutex_);
if (count_ == 0) return;
std::size_t generation(generation_);
cond_.wait(lk, detail::not_equal(generation, generation_));
}
@@ -89,6 +90,7 @@ namespace boost
cv_status wait_for(const chrono::duration<Rep, Period>& rel_time)
{
boost::unique_lock<boost::mutex> lk(mutex_);
if (count_ == 0) return cv_status::no_timeout;
std::size_t generation(generation_);
return cond_.wait_for(lk, rel_time, detail::not_equal(generation, generation_))
? cv_status::no_timeout
@@ -101,6 +103,7 @@ namespace boost
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time)
{
boost::unique_lock<boost::mutex> lk(mutex_);
if (count_ == 0) return cv_status::no_timeout;
std::size_t generation(generation_);
return cond_.wait_until(lk, abs_time, detail::not_equal(generation, generation_))
? cv_status::no_timeout

View File

@@ -31,7 +31,7 @@ namespace boost
//]
//[poly_lockable
class poly_lockable : public basic_poly_lockable<Lockable>
class poly_lockable : public basic_poly_lockable
{
public:
@@ -41,7 +41,7 @@ namespace boost
//]
//[timed_poly_lockable
class timed_poly_lockable: public poly_lockable<TimedLock>
class timed_poly_lockable: public poly_lockable
{
public:
virtual ~timed_poly_lockable()=0;

View File

@@ -156,11 +156,11 @@ namespace boost
{
boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
int const res2 = detail::monotonic_pthread_cond_init(cond);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread_cond_init"));
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in detail::monotonic_pthread_cond_init"));
}
}
~condition_variable_any()
@@ -240,6 +240,8 @@ namespace boost
return timed_wait(m,get_system_time()+wait_duration,pred);
}
#endif
#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type,class Duration>
cv_status
@@ -268,22 +270,6 @@ namespace boost
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class lock_type, class Clock, class Duration, class Predicate>
bool
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class lock_type, class Rep, class Period>
cv_status
wait_for(
@@ -299,24 +285,6 @@ namespace boost
}
template <class lock_type, class Rep, class Period, class Predicate>
bool
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
// while (!pred())
// {
// if (wait_for(lock, d) == cv_status::timeout)
// return pred();
// }
// return true;
}
template <class lock_type>
cv_status wait_until(
lock_type& lk,
@@ -329,6 +297,89 @@ namespace boost
else return cv_status::timeout;
}
#endif
#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type, class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<chrono::steady_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return steady_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
template <class lock_type, class Clock, class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
steady_clock::time_point s_now = steady_clock::now();
typename Clock::time_point c_now = Clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class lock_type, class Rep, class Period>
cv_status
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, c_now + ceil<nanoseconds>(d));
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
inline cv_status wait_until(
unique_lock<mutex>& lk,
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type, class Clock, class Duration, class Predicate>
bool
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class lock_type, class Rep, class Period, class Predicate>
bool
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
}
#endif
void notify_one() BOOST_NOEXCEPT
{

View File

@@ -28,6 +28,26 @@
namespace boost
{
namespace detail {
inline int monotonic_pthread_cond_init(pthread_cond_t& cond) {
#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
pthread_condattr_t attr;
int res = pthread_condattr_init(&attr);
if (res)
{
return res;
}
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
res=pthread_cond_init(&cond,&attr);
pthread_condattr_destroy(&attr);
return res;
#else
return pthread_cond_init(&cond,NULL);
#endif
}
}
class condition_variable
{
@@ -56,19 +76,19 @@ namespace boost
condition_variable()
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
int const res=pthread_mutex_init(&internal_mutex,NULL);
int res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
}
#endif
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
res = detail::monotonic_pthread_cond_init(cond);
if (res)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
#endif
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable::condition_variable() constructor failed in pthread_cond_init"));
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init"));
}
}
~condition_variable()
@@ -94,7 +114,6 @@ namespace boost
while(!pred()) wait(m);
}
#if defined BOOST_THREAD_USES_DATETIME
inline bool timed_wait(
unique_lock<mutex>& m,
@@ -120,6 +139,15 @@ namespace boost
unique_lock<mutex>& m,
duration_type const& wait_duration)
{
if (wait_duration.is_pos_infinity())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
return true;
}
if (wait_duration.is_special())
{
return true;
}
return timed_wait(m,get_system_time()+wait_duration);
}
@@ -149,10 +177,24 @@ namespace boost
unique_lock<mutex>& m,
duration_type const& wait_duration,predicate_type pred)
{
if (wait_duration.is_pos_infinity())
{
while (!pred())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
}
return true;
}
if (wait_duration.is_special())
{
return pred();
}
return timed_wait(m,get_system_time()+wait_duration,pred);
}
#endif
#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class Duration>
@@ -182,20 +224,6 @@ namespace boost
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class Clock, class Duration, class Predicate>
bool
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class Rep, class Period>
@@ -213,6 +241,90 @@ namespace boost
}
inline cv_status wait_until(
unique_lock<mutex>& lk,
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<chrono::steady_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return steady_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
template <class Clock, class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
steady_clock::time_point s_now = steady_clock::now();
typename Clock::time_point c_now = Clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class Rep, class Period>
cv_status
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, c_now + ceil<nanoseconds>(d));
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
inline cv_status wait_until(
unique_lock<mutex>& lk,
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration, class Predicate>
bool
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class Rep, class Period, class Predicate>
bool
@@ -222,13 +334,6 @@ namespace boost
Predicate pred)
{
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
// while (!pred())
// {
// if (wait_for(lock, d) == cv_status::timeout)
// return pred();
// }
// return true;
}
#endif
@@ -242,18 +347,7 @@ namespace boost
void notify_one() BOOST_NOEXCEPT;
void notify_all() BOOST_NOEXCEPT;
#ifdef BOOST_THREAD_USES_CHRONO
inline cv_status wait_until(
unique_lock<mutex>& lk,
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
};
BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);

View File

@@ -1,12 +1,13 @@
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// (C) Copyright 2011,2012,2015 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
#include <boost/assert.hpp>
#include <pthread.h>
#include <boost/throw_exception.hpp>
#include <boost/core/ignore_unused.hpp>
@@ -26,13 +27,12 @@
#endif
#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L
#if (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \
|| (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21)
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
#endif
#include <boost/config/abi_prefix.hpp>
@@ -123,10 +123,12 @@ namespace boost
void unlock()
{
int res = posix::pthread_mutex_unlock(&m);
if (res)
{
boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
}
(void)res;
BOOST_ASSERT(res == 0);
// if (res)
// {
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
// }
}
bool try_lock()
@@ -219,10 +221,12 @@ namespace boost
void unlock()
{
int res = posix::pthread_mutex_unlock(&m);
if (res)
{
boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
}
(void)res;
BOOST_ASSERT(res == 0);
// if (res)
// {
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
// }
}
bool try_lock()

View File

@@ -214,7 +214,7 @@ namespace boost
thread_detail::commit_once_region(flag);
}
}
#if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
template<typename Function>
inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
{
@@ -302,7 +302,7 @@ namespace boost
}
}
#endif // __SUNPRO_CC
#endif
}

View File

@@ -27,16 +27,19 @@
#endif
#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L
#if (defined _POSIX_TIMEOUTS && (_POSIX_TIMEOUTS-0)>=200112L) \
|| (defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ >= 21)
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
#if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \
|| defined __ANDROID__
#define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
#endif
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK)
#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
#endif
@@ -48,7 +51,7 @@ namespace boost
{
private:
pthread_mutex_t m;
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_cond_t cond;
bool is_locked;
pthread_t owner;
@@ -58,7 +61,7 @@ namespace boost
BOOST_THREAD_NO_COPYABLE(recursive_mutex)
recursive_mutex()
{
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_mutexattr_t attr;
int const init_attr_res=pthread_mutexattr_init(&attr);
@@ -99,12 +102,12 @@ namespace boost
~recursive_mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));

View File

@@ -115,8 +115,13 @@ namespace boost
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
std::map<void const*,boost::detail::tss_data_node> tss_data;
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// These data must be at the end so that the access to the other fields doesn't change
// when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined.
// Another option is to have them always
pthread_mutex_t* cond_mutex;
pthread_cond_t* current_cond;
//#endif
typedef std::vector<std::pair<condition_variable*, mutex*>
//, hidden_allocator<std::pair<condition_variable*, mutex*> >
> notify_list_t;
@@ -136,8 +141,10 @@ namespace boost
thread_handle(0),
done(false),join_started(false),joined(false),
thread_exit_callbacks(0),
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
cond_mutex(0),
current_cond(0),
//#endif
notify(),
async_states_()
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS

View File

@@ -28,6 +28,7 @@
namespace boost
{
typedef shared_mutex shared_timed_mutex;
namespace sync
{
#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES

View File

@@ -91,7 +91,19 @@ namespace boost
cv.wait_until(lk, t);
}
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC && defined BOOST_CHRONO_HAS_CLOCK_STEADY
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d > duration<Rep, Period>::zero())
{
steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d);
sleep_until(c_timeout);
}
}
#elif defined BOOST_THREAD_SLEEP_FOR_IS_STEADY
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
@@ -127,7 +139,8 @@ namespace boost
using namespace chrono;
if (d > duration<Rep, Period>::zero())
{
steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d);
//system_clock::time_point c_timeout = time_point_cast<system_clock::duration>(system_clock::now() + ceil<nanoseconds>(d));
system_clock::time_point c_timeout = system_clock::now() + ceil<system_clock::duration>(d);
sleep_until(c_timeout);
}
}

View File

@@ -339,8 +339,8 @@ namespace boost
{
if (wait_duration.is_pos_infinity())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
return true;
wait(m); // or do_wait(m,detail::timeout::sentinel());
return true;
}
if (wait_duration.is_special())
{
@@ -362,6 +362,18 @@ namespace boost
template<typename duration_type,typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
{
if (wait_duration.is_pos_infinity())
{
while (!pred())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
}
return true;
}
if (wait_duration.is_special())
{
return pred();
}
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
#endif

View File

@@ -139,6 +139,7 @@ namespace boost
void lock_shared()
{
#if defined BOOST_THREAD_USES_DATETIME
BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
#else
@@ -389,6 +390,7 @@ namespace boost
void lock()
{
#if defined BOOST_THREAD_USES_DATETIME
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
#else
@@ -739,6 +741,7 @@ namespace boost
new_state.upgrade=false;
bool const last_reader=!--new_state.shared_count;
new_state.shared_waiting=0;
if(last_reader)
{
if(new_state.exclusive_waiting)
@@ -746,7 +749,6 @@ namespace boost
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);

View File

@@ -280,12 +280,13 @@ namespace boost
{
interruptible_wait(abs_time);
}
#ifdef BOOST_THREAD_USES_CHRONO
inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
{
interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
}
#endif
// #11322 sleep_for() nanoseconds overload will always return too early on windows
//#ifdef BOOST_THREAD_USES_CHRONO
// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
// {
// interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
// }
//#endif
namespace no_interruption_point
{
bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
@@ -306,12 +307,13 @@ namespace boost
{
non_interruptible_wait(abs_time);
}
#ifdef BOOST_THREAD_USES_CHRONO
inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
{
non_interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
}
#endif
// #11322 sleep_for() nanoseconds overload will always return too early on windows
//#ifdef BOOST_THREAD_USES_CHRONO
// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
// {
// non_interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
// }
//#endif
}
}

View File

@@ -35,6 +35,7 @@ namespace boost
typedef HANDLE handle;
typedef SYSTEM_INFO system_info;
typedef unsigned __int64 ticks_type;
typedef FARPROC farproc_t;
unsigned const infinite=INFINITE;
unsigned const timeout=WAIT_TIMEOUT;
handle const invalid_handle_value=INVALID_HANDLE_VALUE;
@@ -45,7 +46,7 @@ namespace boost
unsigned const create_event_manual_reset = 0x00000001;
unsigned const event_all_access = EVENT_ALL_ACCESS;
unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS;
# ifdef BOOST_NO_ANSI_APIS
# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
@@ -58,25 +59,28 @@ namespace boost
using ::CreateSemaphoreExW;
# endif
using ::OpenEventW;
using ::GetModuleHandleW;
# else
using ::CreateMutexA;
using ::CreateEventA;
using ::OpenEventA;
using ::CreateSemaphoreA;
using ::GetModuleHandleA;
# endif
#if BOOST_PLAT_WINDOWS_RUNTIME
using ::GetNativeSystemInfo;
using ::GetTickCount64;
#else
using ::GetSystemInfo;
using ::GetTickCount;
#endif
using ::CloseHandle;
using ::ReleaseMutex;
using ::ReleaseSemaphore;
using ::SetEvent;
using ::ResetEvent;
using ::WaitForMultipleObjectsEx;
using ::WaitForSingleObjectEx;
using ::WaitForMultipleObjectsEx;
using ::WaitForSingleObjectEx;
using ::GetCurrentProcessId;
using ::GetCurrentThreadId;
using ::GetCurrentThread;
@@ -86,7 +90,8 @@ namespace boost
using ::SleepEx;
using ::Sleep;
using ::QueueUserAPC;
#endif
using ::GetProcAddress;
#endif
}
}
}
@@ -135,6 +140,7 @@ namespace boost
typedef void* handle;
typedef _SYSTEM_INFO system_info;
typedef unsigned __int64 ticks_type;
typedef int (__stdcall *farproc_t)();
unsigned const infinite=~0U;
unsigned const timeout=258U;
handle const invalid_handle_value=(handle)(-1);
@@ -160,17 +166,20 @@ namespace boost
__declspec(dllimport) void* __stdcall CreateSemaphoreExW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*,unsigned long,unsigned long);
# endif
__declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
__declspec(dllimport) void* __stdcall GetModuleHandleW(wchar_t const*);
# else
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
__declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
__declspec(dllimport) void* __stdcall GetModuleHandleA(char const*);
# endif
#if BOOST_PLAT_WINDOWS_RUNTIME
__declspec(dllimport) void __stdcall GetNativeSystemInfo(_SYSTEM_INFO*);
__declspec(dllimport) ticks_type __stdcall GetTickCount64();
#else
__declspec(dllimport) void __stdcall GetSystemInfo(_SYSTEM_INFO*);
__declspec(dllimport) unsigned long __stdcall GetTickCount();
#endif
__declspec(dllimport) int __stdcall CloseHandle(void*);
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
@@ -183,6 +192,7 @@ namespace boost
__declspec(dllimport) void __stdcall Sleep(unsigned long);
typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
__declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
__declspec(dllimport) farproc_t __stdcall GetProcAddress(void *, const char *);
#endif
# ifndef UNDER_CE
@@ -216,17 +226,10 @@ namespace boost
{
namespace win32
{
namespace detail { typedef int (__stdcall *farproc_t)(); typedef ticks_type (__stdcall *gettickcount64_t)(); }
namespace detail { typedef ticks_type (__stdcall *gettickcount64_t)(); }
#if !BOOST_PLAT_WINDOWS_RUNTIME
extern "C"
{
__declspec(dllimport) detail::farproc_t __stdcall GetProcAddress(void *, const char *);
#if !defined(BOOST_NO_ANSI_APIS)
__declspec(dllimport) void * __stdcall GetModuleHandleA(const char *);
#else
__declspec(dllimport) void * __stdcall GetModuleHandleW(const wchar_t *);
#endif
__declspec(dllimport) unsigned long __stdcall GetTickCount();
#ifdef _MSC_VER
long _InterlockedCompareExchange(long volatile *, long, long);
#pragma intrinsic(_InterlockedCompareExchange)
@@ -283,21 +286,22 @@ namespace boost
}
// Oops, we weren't called often enough, we're stuck
return 0xFFFFFFFF;
return 0xFFFFFFFF;
}
#else
#endif
inline detail::gettickcount64_t GetTickCount64_()
{
static detail::gettickcount64_t gettickcount64impl;
if(gettickcount64impl)
return gettickcount64impl;
// GetTickCount and GetModuleHandle are not allowed in the Windows Runtime,
// and kernel32 isn't used in Windows Phone.
#if BOOST_PLAT_WINDOWS_RUNTIME
gettickcount64impl = &GetTickCount64;
#else
detail::farproc_t addr=GetProcAddress(
#else
farproc_t addr=GetProcAddress(
#if !defined(BOOST_NO_ANSI_APIS)
GetModuleHandleA("KERNEL32.DLL"),
#else
@@ -308,7 +312,7 @@ namespace boost
gettickcount64impl=(detail::gettickcount64_t) addr;
else
gettickcount64impl=&GetTickCount64emulation;
#endif
#endif
return gettickcount64impl;
}
@@ -339,14 +343,14 @@ namespace boost
handle const res = win32::CreateEventW(0, type, state, mutex_name);
#else
handle const res = win32::CreateEventExW(
0,
mutex_name,
0,
mutex_name,
type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0,
event_all_access);
#endif
return res;
}
inline handle create_anonymous_event(event_type type,initial_event_state state)
{
handle const res = create_event(0, type, state);
@@ -370,7 +374,7 @@ namespace boost
#endif
return res;
}
inline handle create_anonymous_semaphore(long initial_count,long max_count)
{
handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count);
@@ -398,20 +402,20 @@ namespace boost
{
BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
}
inline void get_system_info(system_info *info)
{
#if BOOST_PLAT_WINDOWS_RUNTIME
win32::GetNativeSystemInfo(info);
win32::GetNativeSystemInfo(info);
#else
win32::GetSystemInfo(info);
#endif
}
inline void sleep(unsigned long milliseconds)
{
if(milliseconds == 0)
{
{
#if BOOST_PLAT_WINDOWS_RUNTIME
std::this_thread::yield();
#else
@@ -421,13 +425,13 @@ namespace boost
else
{
#if BOOST_PLAT_WINDOWS_RUNTIME
::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0);
::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0);
#else
::boost::detail::win32::Sleep(milliseconds);
#endif
}
}
#if BOOST_PLAT_WINDOWS_RUNTIME
class BOOST_THREAD_DECL scoped_winrt_thread
{
@@ -635,7 +639,7 @@ namespace boost
}
old=current;
}
while(true);
while(true) ;
return (old&value)!=0;
}
@@ -652,7 +656,7 @@ namespace boost
}
old=current;
}
while(true);
while(true) ;
return (old&value)!=0;
}
}

View File

@@ -15,7 +15,7 @@
#include <pthread.h>
#include <stdlib.h>
#include <memory>
#include <string.h> // memcmp.
namespace boost
{
namespace thread_detail
@@ -42,7 +42,6 @@ namespace boost
}
}
#if defined BOOST_THREAD_PATCH
const pthread_once_t pthread_once_init_value=PTHREAD_ONCE_INIT;
struct BOOST_THREAD_DECL delete_epoch_tss_key_on_dlclose_t
{
@@ -58,7 +57,6 @@ namespace boost
}
};
delete_epoch_tss_key_on_dlclose_t delete_epoch_tss_key_on_dlclose;
#endif
}
uintmax_atomic_t& get_once_per_thread_epoch()

View File

@@ -35,6 +35,7 @@
#include <string>
#include <set>
#include <vector>
#include <string.h> // memcmp.
namespace boost
{
@@ -80,6 +81,8 @@ namespace boost
static void tls_destructor(void* data)
{
boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
//boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(data)->shared_from_this();
if(thread_info)
{
while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks)
@@ -96,13 +99,10 @@ namespace boost
}
delete current_node;
}
for(std::map<void const*,tss_data_node>::iterator next=thread_info->tss_data.begin(),
current,
end=thread_info->tss_data.end();
next!=end;)
while (!thread_info->tss_data.empty())
{
current=next;
++next;
std::map<void const*,detail::tss_data_node>::iterator current
= thread_info->tss_data.begin();
if(current->second.func && (current->second.value!=0))
{
(*current->second.func)(current->second.value);
@@ -118,8 +118,6 @@ namespace boost
}
}
#if defined BOOST_THREAD_PATCH
struct delete_current_thread_tls_key_on_dlclose_t
{
delete_current_thread_tls_key_on_dlclose_t()
@@ -127,14 +125,14 @@ namespace boost
}
~delete_current_thread_tls_key_on_dlclose_t()
{
if (current_thread_tls_init_flag.epoch!=BOOST_ONCE_INITIAL_FLAG_VALUE)
const boost::once_flag uninitialized = BOOST_ONCE_INIT;
if (memcmp(&current_thread_tls_init_flag, &uninitialized, sizeof(boost::once_flag)))
{
pthread_key_delete(current_thread_tls_key);
}
}
};
delete_current_thread_tls_key_on_dlclose_t delete_current_thread_tls_key_on_dlclose;
#endif
void create_current_thread_tls_key()
{
@@ -161,7 +159,8 @@ namespace boost
{
static void* thread_proxy(void* param)
{
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
//boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->shared_from_this();
thread_info->self.reset();
detail::set_current_thread_data(thread_info.get());
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
@@ -255,7 +254,6 @@ namespace boost
{
thread_info->self.reset();
return false;
// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create"));
}
return true;
}
@@ -269,7 +267,6 @@ namespace boost
{
thread_info->self.reset();
return false;
// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create"));
}
int detached_state;
res = pthread_attr_getdetachstate(h, &detached_state);
@@ -277,7 +274,6 @@ namespace boost
{
thread_info->self.reset();
return false;
// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_attr_getdetachstate"));
}
if (PTHREAD_CREATE_DETACHED==detached_state)
{

View File

@@ -25,6 +25,7 @@
#if defined BOOST_THREAD_USES_DATETIME
#include <boost/date_time/posix_time/conversion.hpp>
#endif
#include <boost/thread/csbl/memory/unique_ptr.hpp>
#include <memory>
#include <algorithm>
#ifndef UNDER_CE
@@ -44,7 +45,7 @@
#include <wrl\ftm.h>
#include <windows.system.threading.h>
#pragma comment(lib, "runtimeobject.lib")
#endif
#endif
namespace boost
{
@@ -153,7 +154,7 @@ namespace boost
DWORD WINAPI ThreadProxy(LPVOID args)
{
std::auto_ptr<ThreadProxyData> data(reinterpret_cast<ThreadProxyData*>(args));
boost::csbl::unique_ptr<ThreadProxyData> data(reinterpret_cast<ThreadProxyData*>(args));
DWORD ret=data->start_address_(data->arglist_);
return ret;
}
@@ -198,7 +199,7 @@ namespace boost
namespace detail
{
std::atomic_uint threadCount;
bool win32::scoped_winrt_thread::start(thread_func address, void *parameter, unsigned int *thrdId)
{
Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IThreadPoolStatics> threadPoolFactory;
@@ -220,7 +221,7 @@ namespace boost
m_completionHandle = completionHandle;
// Create new work item.
Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem =
Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem =
Microsoft::WRL::Callback<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::System::Threading::IWorkItemHandler, Microsoft::WRL::FtmBase>>
([address, parameter, completionHandle](ABI::Windows::Foundation::IAsyncAction *)
{
@@ -274,13 +275,10 @@ namespace boost
}
boost::detail::heap_delete(current_node);
}
for(std::map<void const*,detail::tss_data_node>::iterator next=current_thread_data->tss_data.begin(),
current,
end=current_thread_data->tss_data.end();
next!=end;)
while (!current_thread_data->tss_data.empty())
{
current=next;
++next;
std::map<void const*,detail::tss_data_node>::iterator current
= current_thread_data->tss_data.begin();
if(current->second.func && (current->second.value!=0))
{
(*current->second.func)(current->second.value);
@@ -346,7 +344,7 @@ namespace boost
return true;
#endif
}
bool thread::start_thread_noexcept(const attributes& attr)
{
#if BOOST_PLAT_WINDOWS_RUNTIME
@@ -367,7 +365,7 @@ namespace boost
return true;
#endif
}
thread::thread(detail::thread_data_ptr data):
thread_info(data)
{}
@@ -529,8 +527,11 @@ namespace boost
unsigned thread::physical_concurrency() BOOST_NOEXCEPT
{
#if BOOST_PLAT_WINDOWS_RUNTIME || (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
return hardware_concurrency();
// a bit too strict: Windows XP with SP3 would be sufficient
#if BOOST_PLAT_WINDOWS_RUNTIME \
|| ( BOOST_USE_WINAPI_VERSION <= BOOST_WINAPI_VERSION_WINXP ) \
|| ( ( defined(__MINGW32__) && !defined(__MINGW64__) ) && _WIN32_WINNT < 0x0600)
return 0;
#else
unsigned cores = 0;
DWORD size = 0;
@@ -648,7 +649,7 @@ namespace boost
} Detailed;
} Reason;
} REASON_CONTEXT, *PREASON_CONTEXT;
static REASON_CONTEXT default_reason_context={0/*POWER_REQUEST_CONTEXT_VERSION*/, 0x00000001/*POWER_REQUEST_CONTEXT_SIMPLE_STRING*/, (LPWSTR)L"generic"};
//static REASON_CONTEXT default_reason_context={0/*POWER_REQUEST_CONTEXT_VERSION*/, 0x00000001/*POWER_REQUEST_CONTEXT_SIMPLE_STRING*/, (LPWSTR)L"generic"};
typedef BOOL (WINAPI *setwaitabletimerex_t)(HANDLE, const LARGE_INTEGER *, LONG, PTIMERAPCROUTINE, LPVOID, PREASON_CONTEXT, ULONG);
static inline BOOL WINAPI SetWaitableTimerEx_emulation(HANDLE hTimer, const LARGE_INTEGER *lpDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext, ULONG TolerableDelay)
{
@@ -718,7 +719,8 @@ namespace boost
if(time_left.milliseconds/20>tolerable) // 5%
tolerable=time_left.milliseconds/20;
LARGE_INTEGER due_time=get_due_time(target_time);
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
//bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,NULL,tolerable)!=0;
if(set_time_succeeded)
{
timeout_index=handle_count;
@@ -802,7 +804,8 @@ namespace boost
if(time_left.milliseconds/20>tolerable) // 5%
tolerable=time_left.milliseconds/20;
LARGE_INTEGER due_time=get_due_time(target_time);
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
//bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,NULL,tolerable)!=0;
if(set_time_succeeded)
{
timeout_index=handle_count;

View File

@@ -31,7 +31,8 @@ project
<toolset>gcc:<cxxflags>-Wno-long-long
#<toolset>gcc:<cxxflags>-ansi
#<toolset>gcc:<cxxflags>-fpermissive
<toolset>gcc:<cxxflags>-Wno-variadic-macros
<toolset>gcc-4:<cxxflags>-Wno-variadic-macros
<toolset>gcc-5:<cxxflags>-Wno-variadic-macros
#<toolset>gcc:<cxxflags>-Wunused-local-typedefs
<toolset>gcc:<cxxflags>-Wunused-function
<toolset>gcc:<cxxflags>-Wno-unused-parameter
@@ -297,6 +298,8 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run test_9856.cpp ]
[ thread-compile test_10963.cpp : : test_10963_c ]
[ thread-run test_10964.cpp ]
[ thread-test test_11053.cpp ]
[ thread-run test_11266.cpp ]
;
@@ -809,7 +812,7 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2 ../example/executor.cpp : ex_executor ]
[ thread-run2 ../example/generic_executor_ref.cpp : ex_generic_executor_ref ]
[ thread-run2 ../example/serial_executor.cpp : ex_serial_executor ]
[ thread-run2 ../example/serial_executor_cont.cpp : ex_serial_executor_cont ]
#[ thread-run2 ../example/serial_executor_cont.cpp : ex_serial_executor_cont ]
[ thread-run2 ../example/future_when_all.cpp : ex_future_when_all ]
[ thread-run2 ../example/parallel_accumulate.cpp : ex_parallel_accumulate ]
[ thread-run2 ../example/parallel_quick_sort.cpp : ex_parallel_quick_sort ]
@@ -946,9 +949,22 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2-noit ./experimental/parallel/v2/task_region_pass.cpp : task_region_p ]
;
explicit ts_other ;
test-suite ts_other
:
[ thread-run2 ../example/this_executor.cpp : ex_this_executor ]
[ thread-run2 ../example/default_executor.cpp : ex_default_executor ]
;
explicit ts_ ;
test-suite ts_
:
#[ thread-run test_11256.cpp ]
#[ thread-run test_11256.cpp ]
#[ thread-run test_11499.cpp ]
#[ thread-run test_11611.cpp ]
;
}

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2014 Vicente J. Botet Escriba
// Copyright (C) 2014-2015 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -132,7 +132,9 @@ void run_exception_1()
{
std::cout << "task3" << std::endl;
});
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
BOOST_TEST(false);
#endif
});
BOOST_TEST(false);
}

View File

@@ -17,6 +17,7 @@
#include <boost/thread/future.hpp>
#include <boost/thread/thread.hpp>
#include <boost/core/ref.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_USES_CHRONO
@@ -128,49 +129,49 @@ int main()
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
}
}
// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
// {
// typedef int& T;
// {
// boost::promise<T> p;
// boost::future<T> f = p.get_future();
//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
// boost::thread(func3, boost::move(p)).detach();
//#else
// int j=5;
// p.set_value(j);
//#endif
// BOOST_TEST(f.valid());
// int k=4;
// BOOST_TEST(f.get_or(k) == 5);
//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
// BOOST_TEST(!f.valid());
//#endif
// }
// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
// {
// boost::promise<T> p;
// boost::future<T> f = p.get_future();
//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
// boost::thread(func4, boost::move(p)).detach();
//#else
// p.set_exception(boost::make_exception_ptr(3.5));
//#endif
// try
// {
// BOOST_TEST(f.valid());
// int j=4;
// BOOST_TEST(f.get_or(j) == 4);
// }
// catch (...)
// {
// BOOST_TEST(false);
// }
//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
// BOOST_TEST(!f.valid());
//#endif
// }
// }
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
typedef int& T;
{
boost::promise<T> p;
boost::future<T> f = p.get_future();
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
boost::thread(func3, boost::move(p)).detach();
#else
int j=5;
p.set_value(j);
#endif
BOOST_TEST(f.valid());
int k=4;
BOOST_TEST(f.get_or(boost::ref(k)) == 5);
#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
BOOST_TEST(!f.valid());
#endif
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::promise<T> p;
boost::future<T> f = p.get_future();
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
boost::thread(func4, boost::move(p)).detach();
#else
p.set_exception(boost::make_exception_ptr(3.5));
#endif
try
{
BOOST_TEST(f.valid());
int j=4;
BOOST_TEST(f.get_or(boost::ref(j)) == 4);
}
catch (...)
{
BOOST_TEST(false);
}
#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
BOOST_TEST(!f.valid());
#endif
}
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;

View File

@@ -17,6 +17,7 @@
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cassert>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
@@ -31,6 +32,8 @@ int p1()
int p2(boost::future<int> f)
{
assert(f.is_ready());
BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG;
BOOST_TEST(f.valid());
int i = f.get();
@@ -41,6 +44,7 @@ int p2(boost::future<int> f)
void p3(boost::future<int> f)
{
assert(f.is_ready());
BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG;
BOOST_TEST(f.valid());
int i = f.get();

View File

@@ -20,6 +20,7 @@
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executor.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cassert>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
@@ -34,6 +35,7 @@ int p1()
int p2(boost::future<int> f)
{
assert(f.is_ready());
BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG;
BOOST_TEST(f.valid());
int i = f.get();
@@ -44,6 +46,7 @@ int p2(boost::future<int> f)
void p3(boost::future<int> f)
{
assert(f.is_ready());
BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG;
BOOST_TEST(f.valid());
int i = f.get();
@@ -114,6 +117,14 @@ int main()
BOOST_TEST(f2.get()==4);
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::basic_thread_pool ex(1);
boost::future<int> f1 = boost::async(p1);
boost::future<int> f21 = f1.then(ex, &p2);
boost::future<int> f2= f21.then(&p2);
BOOST_TEST(f2.get()==4);
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::basic_thread_pool ex(1);
boost::future<int> f1 = boost::async(p1);

View File

@@ -54,7 +54,7 @@ int main()
BOOST_TEST(i == 1);
}
catch(std::exception& ex)
catch(std::exception& )
{
BOOST_TEST(false);
}

View File

@@ -104,6 +104,14 @@ int main()
BOOST_TEST(f2.get()==2);
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::basic_thread_pool ex(1);
boost::shared_future<int> f1 = boost::async(p1).share();
boost::shared_future<int> f21 = f1.then(ex, &p2).share();
boost::future<int> f2= f21.then(ex, &p2);
BOOST_TEST(f2.get()==4);
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::basic_thread_pool ex(1);
boost::shared_future<int> f1 = boost::async(p1).share();

View File

@@ -281,7 +281,7 @@ int main()
BOOST_TEST(res[1].is_ready());
BOOST_TEST(res[1].get() == 321);
}
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD
// fixme darwin-4.8.0_11 terminate called without an active exception
{ // deferred future copy-constructible
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);

View File

@@ -152,7 +152,7 @@ int main()
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
}
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD
// fixme darwin-4.8.0_11 terminate called without an active exception
{ // deferred future copy-constructible
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);

View File

@@ -236,7 +236,7 @@ int main()
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
}
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD
// fixme darwin-4.8.0_11 terminate called without an active exception
{ // deferred future copy-constructible
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);

View File

@@ -283,7 +283,7 @@ int main()
BOOST_TEST(res[1].is_ready());
BOOST_TEST(res[1].get() == 321);
}
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD
// fixme darwin-4.8.0_11 terminate called without an active exception
{ // deferred future copy-constructible
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);

View File

@@ -125,7 +125,7 @@ int main()
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
}
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD
// fixme darwin-4.8.0_11 terminate called without an active exception
{ // deferred future copy-constructible
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);

View File

@@ -225,7 +225,7 @@ int main()
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
}
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD
// fixme darwin-4.8.0_11 terminate called without an active exception
{ // deferred future copy-constructible
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);

View File

@@ -21,9 +21,9 @@
class non_copyable
{
BOOST_THREAD_MOVABLE_ONLY(non_copyable)
int val;
public:
BOOST_THREAD_MOVABLE_ONLY(non_copyable)
non_copyable(int v) : val(v){}
non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
@@ -185,7 +185,7 @@ int main()
// empty queue try_push lvalue succeeds
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
int i;
int i=0;
BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());

View File

@@ -74,7 +74,7 @@ void f()
}
{
time_point t0 = Clock::now();
while (true)
for (;;)
{
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
auto

View File

@@ -21,9 +21,9 @@
class non_copyable
{
BOOST_THREAD_MOVABLE_ONLY(non_copyable)
int val;
public:
BOOST_THREAD_MOVABLE_ONLY(non_copyable)
non_copyable(int v) : val(v){}
non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
@@ -185,7 +185,7 @@ int main()
// empty queue try_push lvalue succeeds
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_back<int> q(sq);
int i;
int i=0;
BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());

View File

@@ -29,7 +29,7 @@ int main()
boost::recursive_mutex::native_handle_type h = m.native_handle();
BOOST_TEST(h);
#else
#error "Test not applicable: BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE not defined for this platform as not supported"
#error "Test not applicable: BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE not defined for this platform as not supported"
#endif
return boost::report_errors();

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
// Copyright (C) 2013,2015 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -76,7 +76,7 @@ int main()
BOOST_TEST(! q.closed());
}
#if 0
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue push rvalue/non_copyable succeeds
boost::sync_deque<non_copyable> q;
@@ -137,11 +137,11 @@ int main()
BOOST_TEST(! q.closed());
}
#if 0
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_deque<non_copyable> q;
BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable()));
BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -179,8 +179,7 @@ int main()
BOOST_TEST(! q.closed());
}
#if 0
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
boost::sync_deque<non_copyable> q;

View File

@@ -105,7 +105,7 @@ void atomic_pull(sync_pq* q, boost::atomic<int>* sum)
const int val = q->pull();
sum->fetch_add(val);
}
catch(std::exception& e ){
catch(std::exception& ){
break;
}
}
@@ -147,7 +147,7 @@ void move_between_queues(sync_pq* q1, sync_pq* q2)
const int val = q1->pull();
q2->push(val);
}
catch(std::exception& e){
catch(std::exception& ){
break;
}
}

View File

@@ -1,5 +1,5 @@
// Copyright (C) 2014 Ian Forbed
// Copyright (C) 2014 Vicente J. Botet Escriba
// Copyright (C) 2014,2015 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -149,17 +149,15 @@ int main()
//test_pull_until_when_not_empty();
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if 0
{
// empty queue try_push rvalue/non-copyable succeeds
boost::concurrent::sync_priority_queue<non_copyable> q;
BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable()));
BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
//fixme
// empty queue try_push rvalue/non-copyable succeeds
@@ -183,17 +181,16 @@ int main()
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
// {
// // empty queue try_push rvalue succeeds
// boost::concurrent::sync_priority_queue<int> q;
// BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
// BOOST_TEST(! q.empty());
// BOOST_TEST(! q.full());
// BOOST_TEST_EQ(q.size(), 1u);
// BOOST_TEST(! q.closed());
// }
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if 0
{
// empty queue try_push rvalue succeeds
boost::concurrent::sync_priority_queue<int> q;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue nonblocking_push rvalue/non-copyable succeeds
boost::concurrent::sync_priority_queue<non_copyable> q;
@@ -203,17 +200,16 @@ int main()
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
// {
// // empty queue nonblocking_push rvalue/non-copyable succeeds
// boost::concurrent::sync_priority_queue<non_copyable> q;
// non_copyable nc(1);
// BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
// BOOST_TEST(! q.empty());
// BOOST_TEST(! q.full());
// BOOST_TEST_EQ(q.size(), 1u);
// BOOST_TEST(! q.closed());
// }
{
// empty queue nonblocking_push rvalue/non-copyable succeeds
boost::concurrent::sync_priority_queue<non_copyable> q;
non_copyable nc(1);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
// Copyright (C) 2013,2015 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -47,7 +47,7 @@ int main()
BOOST_TEST(! q.closed());
}
#if 0
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue push rvalue/non_copyable succeeds
boost::sync_queue<non_copyable> q;
@@ -108,11 +108,11 @@ int main()
BOOST_TEST(! q.closed());
}
#if 0
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable()));
BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -150,7 +150,7 @@ int main()
BOOST_TEST(! q.closed());
}
#if 0
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue nonblocking_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;

View File

@@ -8,9 +8,12 @@
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_PROVIDES_EXECUTORS
#include <boost/thread/future.hpp>
#include <boost/static_assert.hpp>
#include <cassert>
#include <boost/thread/executors/basic_thread_pool.hpp>
struct TestCallback
@@ -19,12 +22,14 @@ struct TestCallback
result_type operator()(boost::future<void> future) const
{
assert(future.is_ready());
future.get();
return boost::make_ready_future();
}
result_type operator()(boost::future<boost::future<void> > future) const
{
assert(future.is_ready());
future.get();
return boost::make_ready_future();
}
@@ -33,12 +38,24 @@ struct TestCallback
int main()
{
#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS
{
boost::promise<void> test_promise;
boost::future<void> test_future(test_promise.get_future());
auto f1 = test_future.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<boost::future<void> > >::value);
}
{
boost::basic_thread_pool executor;
boost::promise<void> test_promise;
boost::future<void> test_future(test_promise.get_future());
auto f1 = test_future.then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<boost::future<void> > >::value);
}
#endif
return 0;
}

View File

@@ -8,9 +8,12 @@
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_PROVIDES_EXECUTORS
#include <boost/thread/future.hpp>
#include <boost/static_assert.hpp>
#include <cassert>
#include <boost/thread/executors/basic_thread_pool.hpp>
struct TestCallback
{
@@ -18,13 +21,44 @@ struct TestCallback
result_type operator()(boost::future<void> future) const
{
future.get();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
assert(future.is_ready());
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
future.wait();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
return boost::make_ready_future();
}
result_type operator()(boost::future<boost::future<void> > future) const
{
future.get();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
assert(future.is_ready());
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
assert(future.get().is_ready());
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
//boost::future<void> ff = future.get();
return boost::make_ready_future();
}
result_type operator()(boost::shared_future<void> future) const
{
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
assert(future.is_ready());
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
future.wait();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
return boost::make_ready_future();
}
result_type operator()(boost::shared_future<boost::future<void> > future) const
{
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
assert(future.is_ready());
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
assert(future.get().is_ready());
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
//boost::future<void> ff = future.get();
return boost::make_ready_future();
}
};
@@ -35,6 +69,9 @@ void p1()
int main()
{
const int number_of_tests = 2;
(void)(number_of_tests);
#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
@@ -43,34 +80,111 @@ int main()
f1.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
auto f1 = boost::make_ready_future().then(TestCallback());
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
auto f2 = f1.unwrap();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
f2.wait();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
auto f1 = boost::make_ready_future().then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.unwrap();
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
f2.wait();
boost::future<void> f2 = f1.get();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
auto f1 = boost::make_ready_future().then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f3 = f1.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
f3.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
auto f1 = boost::make_ready_future().then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.unwrap();
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
auto f3 = f2.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
f3.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
boost::make_ready_future().then(
TestCallback()).unwrap().then(TestCallback()).get();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
boost::future<void> f = boost::async(p1);
f.then(
TestCallback()).unwrap().then(TestCallback()).get();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
auto f1 = boost::make_ready_future().then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f3 = f1.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
f3.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
boost::basic_thread_pool executor;
auto f1 = boost::make_ready_future().then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f3 = f1.then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
f3.wait();
}
#if 1
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
// fixme
for (int i=0; i< number_of_tests; i++)
{
boost::basic_thread_pool executor(2);
auto f1 = boost::make_ready_future().then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
std::cout << __FILE__ << "[" << __LINE__ << "] " << int(f1.valid()) << std::endl;
auto f2 = f1.unwrap();
std::cout << __FILE__ << "[" << __LINE__ << "] " << int(f2.valid()) << std::endl;
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
auto f3 = f2.then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
f3.wait();
}
#endif
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
boost::basic_thread_pool executor;
auto f1 = boost::make_ready_future().then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.unwrap();
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
auto f3 = f2.then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
f3.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
#endif
return 0;
}

70
test/test_11053.cpp Normal file
View File

@@ -0,0 +1,70 @@
// Copyright (C) 2015 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 4
#include <boost/thread.hpp>
#include <boost/thread/tss.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
struct A
{
void DoWork()
{
std::cout << "A: doing work\n";
if (!m_ptr.get())
m_ptr.reset(new WorkSpace());
// do not very much
for (size_t i = 0; i < 10; ++i)
m_ptr->a += 10;
}
private:
struct WorkSpace
{
int a;
WorkSpace() : a(0) {}
};
boost::thread_specific_ptr<WorkSpace> m_ptr;
};
struct B
{
void DoWork()
{
std::cout << "B: doing work\n";
if (!m_ptr.get())
m_ptr.reset(new A());
m_ptr->DoWork();
}
private:
boost::thread_specific_ptr<A> m_ptr;
};
struct C
{
void DoWork()
{
std::cout << "C: doing work\n";
if (!m_ptr.get())
m_ptr.reset(new B());
m_ptr->DoWork();
}
private:
boost::thread_specific_ptr<B> m_ptr;
};
int main(int ac, char** av)
{
std::cout << "test starting\n";
boost::shared_ptr<C> p_C(new C);
boost::thread cWorker(&C::DoWork, p_C);
cWorker.join();
std::cout << "test stopping\n";
return 0;
}

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