mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 21:52:07 +00:00
Compare commits
29 Commits
feature/no
...
feature/ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0317c5206 | ||
|
|
06d2571ec6 | ||
|
|
fdaba4efe7 | ||
|
|
8a7cd83123 | ||
|
|
98a5e343f8 | ||
|
|
89d8e18c82 | ||
|
|
d9492530bd | ||
|
|
f6c732b124 | ||
|
|
dcc3227668 | ||
|
|
b3d237731a | ||
|
|
4321b59c1e | ||
|
|
67759325eb | ||
|
|
8153e2a652 | ||
|
|
7876163c68 | ||
|
|
805fa41a4e | ||
|
|
0e6376d93a | ||
|
|
bf1fc5158e | ||
|
|
1e4e9ab84c | ||
|
|
88ab663ac5 | ||
|
|
9a4fbbec5d | ||
|
|
c7df715709 | ||
|
|
730cb550e6 | ||
|
|
a3497e1ffc | ||
|
|
f25bc8bbab | ||
|
|
0f6a3ebbe5 | ||
|
|
287100119a | ||
|
|
d9594e7fc8 | ||
|
|
855e56076b | ||
|
|
3c6a183aa3 |
@@ -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
|
||||
|
||||
@@ -23,7 +23,13 @@ Please take a look at [@http://www.boost.org/development/tests/master/developer/
|
||||
|
||||
[*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:]
|
||||
|
||||
@@ -35,23 +41,28 @@ Please take a look at [@http://www.boost.org/development/tests/master/developer/
|
||||
* [@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/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/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]
|
||||
|
||||
|
||||
@@ -29,9 +29,11 @@
|
||||
|
||||
enum class launch
|
||||
{
|
||||
none = unspecified,
|
||||
async = unspecified,
|
||||
deferred = unspecified,
|
||||
executor = unspecified,
|
||||
inherit = unspecified,
|
||||
any = async | deferred
|
||||
};
|
||||
|
||||
@@ -165,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>`]
|
||||
@@ -902,25 +917,37 @@ future object as a parameter. The second function takes a executor as the first
|
||||
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 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`.
|
||||
|
||||
- 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`.
|
||||
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`.
|
||||
|
||||
]]
|
||||
@@ -1380,22 +1407,38 @@ shared_future object as a parameter. The second function takes an executor as th
|
||||
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 executor.
|
||||
- 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 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`.
|
||||
|
||||
- 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
|
||||
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`
|
||||
`launch::deferred`.
|
||||
|
||||
]]
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
[library Thread
|
||||
[quickbook 1.5]
|
||||
[version 4.5.0]
|
||||
[version 4.6.0]
|
||||
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
|
||||
[copyright 2007-11 Anthony Williams]
|
||||
[copyright 2011-15 Vicente J. Botet Escriba]
|
||||
|
||||
@@ -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()()
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
// boost::thread::future requires exception handling
|
||||
// due to boost::exception::exception_ptr dependency
|
||||
|
||||
#define BOOST_THREAD_CONTINUATION_SYNC
|
||||
//#define BOOST_THREAD_FUTURE_BLOCKING
|
||||
//#define BOOST_THREAD_CONTINUATION_SYNC
|
||||
#define BOOST_THREAD_FUTURE_BLOCKING
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
@@ -4224,8 +4224,8 @@ namespace detail
|
||||
//////////////////////
|
||||
// detail::continuation_shared_state
|
||||
//////////////////////
|
||||
template<typename F, typename Rp, typename Fp, template <class> class ShSt=shared_state>
|
||||
struct continuation_shared_state: ShSt<Rp>
|
||||
template<typename F, typename Rp, typename Fp, class ShSt=shared_state<Rp> >
|
||||
struct continuation_shared_state: ShSt
|
||||
{
|
||||
F parent;
|
||||
Fp continuation;
|
||||
@@ -4261,8 +4261,8 @@ namespace detail
|
||||
~continuation_shared_state() {}
|
||||
};
|
||||
|
||||
template<typename F, typename Fp, template <class> class ShSt>
|
||||
struct continuation_shared_state<F, void, Fp, ShSt>: ShSt<void>
|
||||
template<typename F, typename Fp, class ShSt>
|
||||
struct continuation_shared_state<F, void, Fp, ShSt>: ShSt
|
||||
{
|
||||
F parent;
|
||||
Fp continuation;
|
||||
@@ -4304,9 +4304,9 @@ namespace detail
|
||||
/////////////////////////
|
||||
|
||||
template<typename F, typename Rp, typename Fp>
|
||||
struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base>
|
||||
struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> >
|
||||
{
|
||||
typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base> base_type;
|
||||
typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > base_type;
|
||||
public:
|
||||
future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
||||
: base_type(boost::move(f), boost::forward<Fp>(c))
|
||||
@@ -4404,9 +4404,9 @@ namespace detail {
|
||||
/////////////////////////
|
||||
|
||||
template<typename F, typename Rp, typename Fp>
|
||||
struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base>
|
||||
struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> >
|
||||
{
|
||||
typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base> base_type;
|
||||
typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > base_type;
|
||||
|
||||
public:
|
||||
shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
|
||||
@@ -4725,12 +4725,39 @@ namespace detail {
|
||||
)));
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
|
||||
assert(this->future_->get_executor());
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else if (underlying_cast<int>(policy) & int(launch::inherit)) {
|
||||
|
||||
launch policy = this->launch_policy(lock);
|
||||
if (underlying_cast<int>(policy) & int(launch::async)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
} else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
||||
this->future_->wait_internal(lock);
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
|
||||
assert(this->future_->get_executor());
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
@@ -4763,12 +4790,32 @@ namespace detail {
|
||||
template <typename F>
|
||||
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
|
||||
BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) {
|
||||
|
||||
#ifndef BOOST_THREAD_CONTINUATION_SYNC
|
||||
return this->then(this->launch_policy(), boost::forward<F>(func));
|
||||
#else
|
||||
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
launch policy = this->launch_policy(lock);
|
||||
if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
||||
this->future_->wait_internal(lock);
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
} else {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// template<typename F>
|
||||
// auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
||||
// auto future<future<R2> >::then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
||||
////////////////////////////////
|
||||
template <typename R2>
|
||||
template <typename F>
|
||||
@@ -4789,12 +4836,38 @@ namespace detail {
|
||||
)));
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
|
||||
assert(this->future_->get_executor());
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else if (underlying_cast<int>(policy) & int(launch::inherit)) {
|
||||
launch policy = this->launch_policy(lock);
|
||||
|
||||
if (underlying_cast<int>(policy) & int(launch::async)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
} else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
|
||||
assert(this->future_->get_executor());
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
@@ -4831,7 +4904,26 @@ namespace detail {
|
||||
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
|
||||
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(BOOST_THREAD_FWD_REF(F) func) {
|
||||
|
||||
#ifndef BOOST_THREAD_CONTINUATION_SYNC
|
||||
return this->then(this->launch_policy(), boost::forward<F>(func));
|
||||
#else
|
||||
typedef BOOST_THREAD_FUTURE<R2> R;
|
||||
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
launch policy = this->launch_policy(lock);
|
||||
|
||||
if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
} else {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -4864,6 +4956,32 @@ namespace detail {
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else if (underlying_cast<int>(policy) & int(launch::inherit)) {
|
||||
|
||||
launch policy = this->launch_policy(lock);
|
||||
if (underlying_cast<int>(policy) & int(launch::async)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
} else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
||||
this->future_->wait_internal(lock);
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
}
|
||||
|
||||
} else {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
|
||||
lock, *this, boost::forward<F>(func)
|
||||
@@ -4898,8 +5016,25 @@ namespace detail {
|
||||
template <typename F>
|
||||
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
|
||||
shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) const {
|
||||
|
||||
#ifndef BOOST_THREAD_CONTINUATION_SYNC
|
||||
return this->then(this->launch_policy(), boost::forward<F>(func));
|
||||
#else
|
||||
typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
launch policy = this->launch_policy(lock);
|
||||
if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
||||
this->future_->wait_internal(lock);
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
} else {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace detail
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -91,7 +91,19 @@ namespace boost
|
||||
cv.wait_until(lk, t);
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY && ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -962,8 +963,7 @@ rule thread-compile ( sources : reqs * : name )
|
||||
#[ 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 ]
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -151,10 +151,12 @@ int main()
|
||||
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(1);
|
||||
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);
|
||||
@@ -167,6 +169,7 @@ int main()
|
||||
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++)
|
||||
{
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
#define BOOST_TEST_MODULE Boost.Threads: 2309
|
||||
#include <boost/test/unit_test.hpp>
|
||||
//#define BOOST_TEST_MODULE Boost.Threads: 2309
|
||||
//#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -40,7 +41,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test)
|
||||
void ticket_2309_test()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -57,9 +58,13 @@
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_CHECK(false && "exception raised");
|
||||
BOOST_TEST(false && "exception raised");
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
ticket_2309_test();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user