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

Compare commits

...

74 Commits

Author SHA1 Message Date
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
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
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
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
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
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
c50d0ac4ba try to fix issue with continuation on unwrap shared state. 2015-05-03 16:51:41 +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
58 changed files with 1165 additions and 777 deletions

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)
@@ -411,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.]]
@@ -431,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.]]
@@ -814,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,6 +8,51 @@
[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/11424 #11424] Provide shared_timed_mutex as an alternative name for shared_mutex and deprecate the use of shared_mutex as a timed mutex
[*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/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/11158 #11158] Pthread thread deadlock when faketime used
* [@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/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/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
[heading Version 4.5.0 - boost 1.58]
[*Know Bugs:]

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

@@ -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).
@@ -344,7 +345,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 +885,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,7 +898,7 @@ 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.]]
@@ -907,10 +908,10 @@ All the functions create a shared state that is associated with the returned fut
- The continuation is called when the object's shared state is ready (has a value or exception stored).
- The continuation launches according to the specified policy or scheduler.
- The continuation launches according to the specified policy or executor.
- When the scheduler or launch policy is not provided the continuation inherits the
parent's launch policy or scheduler.
- When the executor or launch policy is not provided the continuation inherits the
parent's launch policy or executor.
- 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`.
@@ -1361,7 +1362,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,7 +1376,7 @@ 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.]]
@@ -1383,17 +1384,17 @@ second parameter.]]
- The continuation is called when the object's shared state is ready (has a value or exception stored).
- The continuation launches according to the specified policy or scheduler.
- The continuation launches according to the specified policy or executor.
- When the scheduler or launch policy is not provided the continuation inherits the
parent's launch policy or scheduler.
- When the executor or launch policy is not provided the continuation inherits the
parent's launch policy or executor.
- 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
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

@@ -7,8 +7,10 @@
[section:tutorial Tutorial]
[@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

@@ -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
@@ -48,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)
@@ -78,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)
{
@@ -154,7 +190,7 @@ int main()
{
return test_executor_adaptor();
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
#if 0 && defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
&& defined BOOST_THREAD_PROVIDES_EXECUTORS \
&& ! defined BOOST_NO_CXX11_RVALUE_REFERENCES

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

@@ -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

View File

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

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

@@ -235,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

@@ -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

@@ -484,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

@@ -60,7 +60,7 @@ namespace executors
catch (...)
{
std::terminate();
return false;
//return false;
}
}
/**
@@ -87,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();
}
}
@@ -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

@@ -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

@@ -53,7 +53,7 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
throw;
}
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
catch (task_canceled_exception& ex)
catch (task_canceled_exception&)
{
}
#endif

File diff suppressed because it is too large Load Diff

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,
@@ -174,6 +193,8 @@ namespace boost
}
#endif
#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class Duration>
@@ -203,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>
@@ -234,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
@@ -243,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
@@ -263,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

@@ -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

@@ -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,7 @@ namespace boost
cv.wait_until(lk, t);
}
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
#if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY && ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)

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

@@ -46,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
@@ -59,7 +59,7 @@ namespace boost
using ::CreateSemaphoreExW;
# endif
using ::OpenEventW;
using ::GetModuleGandleW;
using ::GetModuleHandleW;
# else
using ::CreateMutexA;
using ::CreateEventA;
@@ -79,8 +79,8 @@ namespace boost
using ::ReleaseSemaphore;
using ::SetEvent;
using ::ResetEvent;
using ::WaitForMultipleObjectsEx;
using ::WaitForSingleObjectEx;
using ::WaitForMultipleObjectsEx;
using ::WaitForSingleObjectEx;
using ::GetCurrentProcessId;
using ::GetCurrentThreadId;
using ::GetCurrentThread;
@@ -91,7 +91,7 @@ namespace boost
using ::Sleep;
using ::QueueUserAPC;
using ::GetProcAddress;
#endif
#endif
}
}
}
@@ -286,7 +286,7 @@ namespace boost
}
// Oops, we weren't called often enough, we're stuck
return 0xFFFFFFFF;
return 0xFFFFFFFF;
}
#else
#endif
@@ -295,12 +295,12 @@ namespace boost
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
#else
farproc_t addr=GetProcAddress(
#if !defined(BOOST_NO_ANSI_APIS)
GetModuleHandleA("KERNEL32.DLL"),
@@ -312,7 +312,7 @@ namespace boost
gettickcount64impl=(detail::gettickcount64_t) addr;
else
gettickcount64impl=&GetTickCount64emulation;
#endif
#endif
return gettickcount64impl;
}
@@ -343,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);
@@ -374,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);
@@ -402,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
@@ -425,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
{
@@ -639,7 +639,7 @@ namespace boost
}
old=current;
}
while(true);
while(true) ;
return (old&value)!=0;
}
@@ -656,7 +656,7 @@ namespace boost
}
old=current;
}
while(true);
while(true) ;
return (old&value)!=0;
}
}

View File

@@ -15,9 +15,7 @@
#include <pthread.h>
#include <stdlib.h>
#include <memory>
#if defined BOOST_THREAD_PATCH
#include <string.h> // memcmp.
#endif
namespace boost
{
namespace thread_detail
@@ -44,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
{
@@ -60,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
{
@@ -117,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()
@@ -134,7 +133,6 @@ namespace boost
}
};
delete_current_thread_tls_key_on_dlclose_t delete_current_thread_tls_key_on_dlclose;
#endif
void create_current_thread_tls_key()
{

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
@@ -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;
}
@@ -526,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;
@@ -645,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)
{
@@ -715,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;
@@ -799,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

@@ -811,7 +811,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 ]
@@ -958,7 +958,12 @@ rule thread-compile ( sources : reqs * : name )
explicit ts_ ;
test-suite ts_
:
#[ thread-run test_11256.cpp ]
#[ thread-run test_11256.cpp ]
#[ thread-run test_11499.cpp ]
#[ thread-run test_11611.cpp ]
[ thread-run2-noit ./sync/futures/shared_future/then_executor_pass.cpp : shared_future__then_executor_p2 ]
[ thread-run2-noit ./sync/futures/future/then_executor_pass.cpp : future__then_executor_p2 ]
;

View File

@@ -117,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

@@ -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

@@ -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

@@ -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

@@ -38,6 +38,27 @@ struct TestCallback
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();
}
};
@@ -49,6 +70,7 @@ 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;
@@ -74,11 +96,17 @@ int main()
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
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);
boost::future<void> f2 = f1.get();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
}
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++)
@@ -113,8 +141,6 @@ int main()
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++)
{

56
test/test_11499.cpp Normal file
View File

@@ -0,0 +1,56 @@
// Copyright (C) 2014 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 4
#include <boost/thread/shared_mutex.hpp>
#include <thread>
#include <mutex>
#include <shared_mutex>
#include <atomic>
#include <vector>
using MutexT = boost::shared_mutex;
using ReaderLockT = std::lock_guard<MutexT>;
using WriterLockT = std::shared_lock<MutexT>;
MutexT gMutex;
std::atomic<bool> running(true);
void myread()
{
long reads = 0;
while (running && reads < 100000)
{
ReaderLockT lock(gMutex);
std::this_thread::yield();
++reads;
}
}
int main()
{
using namespace std;
vector<thread> threads;
for (int i = 0; i < 256; ++i)
{
threads.emplace_back(thread(myread));
}
// string str;
//
// getline(std::cin, str);
running = false;
for (auto& thread : threads)
{
thread.join();
}
return 0;
}

48
test/test_11611.cpp Normal file
View File

@@ -0,0 +1,48 @@
// Copyright (C) 2014 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//#define BOOST_THREAD_VERSION 4
#include <iostream>
//#include <thread>
#define BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_PROVIDES_EXECUTORS
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#include <boost/thread/executors/loop_executor.hpp>
#include <boost/thread/executors/serial_executor_cont.hpp>
#include <boost/thread/executors/serial_executor.hpp>
#include <boost/thread/thread.hpp>
using namespace std;
int main()
{
boost::loop_executor ex;
//thread t([&ex]()
boost::thread t([&ex]()
{
ex.loop();
});
{
//boost::serial_executor_cont serial(ex);
boost::serial_executor serial(ex);
for (size_t i = 0; i < 100000; i++)
serial.submit([i] {
//std::cout << i << ".";
});
serial.close();
}
ex.close();
t.join();
std::cout << "end" << std::endl;
return 0;
}

View File

@@ -35,6 +35,7 @@ BOOST_AUTO_TEST_CASE(test_native_handle)
boost::thread_attributes attrs;
boost::thread_attributes::native_handle_type* h = attrs.native_handle();
(void)(h); // unused
#if defined(BOOST_THREAD_PLATFORM_WIN32)
// ... window version
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
@@ -75,3 +76,4 @@ BOOST_AUTO_TEST_CASE(test_creation_with_attrs)
timed_test(&do_test_creation_with_attrs, 1);
}

View File

@@ -30,7 +30,7 @@ int boostThreadLocksTest::firstFunction(boostThreadLocksTest *pBoostThreadLocksT
std::cout<<"Returning from "<<boost::this_thread::get_id()<<" "<<"firstFunction"<<std::endl;
return(0);
}
int boostThreadLocksTest::secondFunction(boostThreadLocksTest */*pBoostThreadLocksTest*/, boost::upgrade_lock<boost::shared_mutex>& upgr) {
int boostThreadLocksTest::secondFunction(boostThreadLocksTest *, boost::upgrade_lock<boost::shared_mutex>& upgr) {
std::cout<<"Before Exclusive Locking "<<boost::this_thread::get_id()<<" "<<"secondFunction"<<std::endl;
boost::upgrade_to_unique_lock<boost::shared_mutex> localUniqueLock(upgr);
std::cout<<"After Exclusive Locking "<<boost::this_thread::get_id()<<" "<<"secondFunction"<<std::endl;

View File

@@ -45,7 +45,7 @@ void thread()
#endif
}
}
BOOST_CATCH (boost::lock_error& le)
BOOST_CATCH (boost::lock_error& )
{
//BOOST_THREAD_LOG << "lock_error exception thrd>" << BOOST_THREAD_END_LOG;
}

View File

@@ -28,7 +28,7 @@ int main()
{
typedef boost::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
//typedef Clock::duration duration;
boost::chrono::milliseconds ms(500);
time_point t0 = Clock::now();
boost::this_thread::sleep_until(t0 + ms);
@@ -43,7 +43,7 @@ int main()
{
typedef boost::chrono::system_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
//typedef Clock::duration duration;
boost::chrono::milliseconds ms(500);
time_point t0 = Clock::now();
boost::this_thread::sleep_until(t0 + ms);
@@ -58,7 +58,7 @@ int main()
{
typedef boost::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
//typedef Clock::duration duration;
boost::chrono::milliseconds ms(500);
time_point t0 = Clock::now();
boost::this_thread::no_interruption_point::sleep_until(t0 + ms);
@@ -73,7 +73,7 @@ int main()
{
typedef boost::chrono::system_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
//typedef Clock::duration duration;
boost::chrono::milliseconds ms(500);
time_point t0 = Clock::now();
boost::this_thread::no_interruption_point::sleep_until(t0 + ms);