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

Compare commits

..

2 Commits

14 changed files with 349 additions and 387 deletions

View File

@@ -58,15 +58,11 @@ Please take a look at [@http://www.boost.org/development/tests/master/developer/
* [@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] (condition_variable_any::wait_until + recursive_mutex + steady_clock) timer expires after computer time is set forward on Ubuntu 64-bit
* [@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
* [@http://svn.boost.org/trac/boost/ticket/11795 #11795] Incorrect version specification for documentation of thread destructor
* [@http://svn.boost.org/trac/boost/ticket/11796 #11796] Thread move assignment operator, does not detach previous thread data
* [@http://svn.boost.org/trac/boost/ticket/11817 #11817] 'sync_queue_is_closed' was not declared in boost/thread/executors/thread_executor.hpp
* [@http://svn.boost.org/trac/boost/ticket/11818 #11818] future.then will be blocked if promise is set after the invocation of then
[heading Version 4.5.0 - boost 1.58]

View File

@@ -326,7 +326,7 @@ Using a `shared_future` solves the issue
[heading share()]
Naming the return type when declaring the `shared_future` is needed; auto is not available within template argument lists.
Namming the return type when declaring the `shared_future` is needed; auto is not available within template argument lists.
Here `share()` could be used to simplify the code
void better_second_use( type arg ) {
@@ -344,7 +344,7 @@ Here `share()` could be used to simplify the code
[heading Writing on get()]
The user can either read or write the future variable.
The user can either read or write the future avariable.
void write_to_get( type arg ) {
@@ -365,7 +365,7 @@ The user can either read or write the future variable.
This works because the `shared_future<>::get()` function returns a non-const reference to the appropriate storage.
Of course the access to this storage must be ensured by the user. The library doesn't ensure the access to the internal storage is thread safe.
There has been some work by the C++ standard committee on an `atomic_future` that behaves as an `atomic` variable, that is thread_safe,
There has been some work by the C++ standard committe on an `atomic_future` that behaves as an `atomic` variable, that is is thread_safe,
and a `shared_future` that can be shared between several threads, but there were not enough consensus and time to get it ready for C++11.
[endsect]
@@ -444,7 +444,7 @@ 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.
* Executor: Providing an overload to `.then`, to take an executor 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 executor must outlive the continuation.
* Launch policy: if the additional flexibility that the executor provides is not required.

View File

@@ -110,10 +110,10 @@ where
* `q` denotes a value of type `Q`,
* `e` denotes a value of type Q::value_type,
* `u` denotes a value of type Q::size_type,
* `lve` denotes an lvalue reference of type Q::value_type,
* `rve` denotes an rvalue reference of type Q::value_type:
* `lve` denotes a lvalue referece of type Q::value_type,
* `rve` denotes a rvalue referece of type Q::value_type:
[/* `spe` denotes a shared_ptr<Q::value_type>]
* `qs` denotes a variable of of type `queue_op_status`,
* `qs` denotes a variable of of type `queus_op_status`,
[/////////////////////////////////////]
@@ -246,8 +246,8 @@ where
* `e` denotes a value of type `Q::value_type`,
* `s` denotes a value of type `queue_status`,
* `u` denotes a value of type `Q::size_type`,
* `lve` denotes an lvalue reference of type Q::value_type,
* `rve` denotes an rvalue reference of type Q::value_type:
* `lve` denotes a lvalue referece of type Q::value_type,
* `rve` denotes a rvalue referece of type Q::value_type:
[/* `spe` denotes a shared_ptr<Q::value_type>]
@@ -357,8 +357,8 @@ where
* `q` denotes a value of type `Q`,
* `e` denotes a value of type Q::value_type,
* `s` denotes a value of type `queue_status`,
* `lve` denotes an lvalue reference of type Q::value_type,
* `rve` denotes an rvalue reference of type Q::value_type:
* `lve` denotes a lvalue referece of type Q::value_type,
* `rve` denotes a rvalue referece of type Q::value_type:
[/* `spe` denotes a shared_ptr<Q::value_type>]
@@ -545,7 +545,7 @@ Closed queues add the following valid expressions
[[Return:] [
- If the queue is closed return `queue_op_status::closed`,
- If the queue is closed retun `queue_op_status::closed`,
- otherwise, return `queue_op_status::success` if no exception is thrown.

View File

@@ -255,7 +255,7 @@ does not complete when the specified time has elapsed or reached respectively.
[endsect]
[section:destructor1 Destructor V1-2]
[section:destructor1 Destructor V1]
When the __thread__ object that represents a thread of execution is destroyed the thread becomes ['detached]. Once a thread is
detached, it will continue executing until the invocation of the function or callable object supplied on construction has completed,
@@ -264,7 +264,7 @@ object. In this case, the __thread__ object ceases to represent the now-detached
[endsect]
[section:destructor2 Destructor V3-X]
[section:destructor2 Destructor V2]
When the __thread__ object that represents a thread of execution is destroyed the program terminates if the thread is __joinable__.
@@ -280,7 +280,7 @@ You can use a thread_joiner to ensure that the thread has been joined at the thr
{
boost::thread t(my_func);
boost::thread_joiner g(t);
// do something else
// do someting else
} // here the thread_joiner destructor will join the thread before it is destroyed.
[endsect]
@@ -410,7 +410,7 @@ Of course all the synchronization facilities provided by Boost.Thread are also a
The `boost::this_thread` interrupt related functions behave in a degraded mode when called from a thread created using the native interface, i.e. `boost::this_thread::interruption_enabled()` returns false. As consequence the use of `boost::this_thread::disable_interruption` and `boost::this_thread::restore_interruption` will do nothing and calls to `boost::this_thread::interruption_point()` will be just ignored.
As the single way to interrupt a thread is through a __thread__ instance, `interruption_request()` will return false for the native threads.
As the single way to interrupt a thread is through a __thread__ instance, `interruption_request()` wiil returns false for the native threads.
[heading `pthread_exit` POSIX limitation]
@@ -964,7 +964,7 @@ predefined __interruption_points__ with interruption enabled .]]
[section:hardware_concurrency Static member function `hardware_concurrency()`]
unsigned hardware_concurrency() noexcept;
unsigned hardware_concurrency() noexecpt;
[variablelist
@@ -979,7 +979,7 @@ or 0 if this information is not available.]]
[section:physical_concurrency Static member function `physical_concurrency()`]
unsigned physical_concurrency() noexcept;
unsigned physical_concurrency() noexecpt;
[variablelist
@@ -1290,7 +1290,7 @@ instances of __thread_id__ `a` and `b` is the same if `a==b`, and different if `
[variablelist
[[Effects:] [Constructs a thread attributes instance with its default values.]]
[[Effects:] [Constructs a thread atrributes instance with its default values.]]
[[Throws:] [Nothing]]
@@ -1532,7 +1532,7 @@ do not throw exceptions. __thread_interrupted__ if the current thread of executi
[variablelist
[[Effects:] [Suspends the current thread until the duration specified
[[Effects:] [Suspends the current thread until the duration specified by
by `rel_time` has elapsed.]]
[[Throws:] [Nothing if operations of chrono::duration<Rep, Period> do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted.]]

View File

@@ -41,28 +41,10 @@ int main()
for (int i=0; i< number_of_tests; i++)
try
{
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
boost::future<int> inner_future = boost::async(boost::launch::async, &p2);
inner_future.wait();
int ii = inner_future.get();
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
}
#endif
{
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
boost::future<int> inner_future = outer_future.unwrap();
inner_future.wait();
int ii = inner_future.get();
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
}
{
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
boost::future<int> inner_future = outer_future.unwrap();
int ii = inner_future.get();
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
}
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
boost::future<int> inner_future = outer_future.unwrap();
int ii = inner_future.get();
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{

View File

@@ -99,7 +99,7 @@ namespace boost
result_type
execute(tuple_indices<Indices...>)
{
return detail::invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
return invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
}
};
@@ -136,7 +136,7 @@ namespace boost
result_type
execute(tuple_indices<Indices...>)
{
return detail::invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
return invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
}
};
//BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END
@@ -190,7 +190,7 @@ namespace boost
{} \
\
result_type operator()() { \
return detail::invoke(boost::move(fp_) \
return invoke(boost::move(fp_) \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \
); \
} \
@@ -315,7 +315,7 @@ namespace boost
result_type operator()()
{
return detail::invoke(boost::move(fp_)
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -381,7 +381,7 @@ namespace boost
result_type operator()()
{
return detail::invoke(boost::move(fp_)
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -442,7 +442,7 @@ namespace boost
result_type operator()()
{
return detail::invoke(boost::move(fp_)
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -498,7 +498,7 @@ namespace boost
result_type operator()()
{
return detail::invoke(boost::move(fp_)
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -549,7 +549,7 @@ namespace boost
result_type operator()()
{
return detail::invoke(boost::move(fp_)
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -595,7 +595,7 @@ namespace boost
result_type operator()()
{
return detail::invoke(boost::move(fp_)
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -636,7 +636,7 @@ namespace boost
result_type operator()()
{
return detail::invoke(boost::move(fp_)
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -672,7 +672,7 @@ namespace boost
result_type operator()()
{
return detail::invoke(boost::move(fp_)
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
);
@@ -703,7 +703,7 @@ namespace boost
result_type operator()()
{
return detail::invoke(boost::move(fp_)
return invoke(boost::move(fp_)
, boost::move(v0_)
);
}

View File

@@ -72,7 +72,7 @@ namespace boost
void run2(tuple_indices<Indices...>)
{
detail::invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...);
invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...);
}
void run()
{
@@ -354,8 +354,6 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
if (joinable()) std::terminate();
#else
detach();
#endif
thread_info=BOOST_THREAD_RV(other).thread_info;
BOOST_THREAD_RV(other).thread_info.reset();

View File

@@ -17,7 +17,6 @@
#include <boost/thread/thread_only.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/csbl/vector.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/config/abi_prefix.hpp>

View File

@@ -94,6 +94,9 @@
namespace boost
{
struct executor_arg_t {};
template <class T>
shared_ptr<T> static_shared_from_this(T* that)
{
@@ -160,7 +163,6 @@ namespace boost
boost::function<void()> callback;
// This declaration should be only included conditionally, but is included to maintain the same layout.
continuations_type continuations;
executor_ptr_type ex;
// This declaration should be only included conditionally, but is included to maintain the same layout.
virtual void launch_continuation()
@@ -173,44 +175,26 @@ namespace boost
is_deferred_(false),
is_constructed(false),
policy_(launch::none),
continuations(),
ex()
continuations()
{}
shared_state_base(exceptional_ptr const& ex):
exception(ex.ptr_),
shared_state_base(exceptional_ptr const& excp):
exception(excp.ptr_),
done(true),
is_valid_(true),
is_deferred_(false),
is_constructed(false),
policy_(launch::none),
continuations(),
ex()
continuations()
{}
virtual ~shared_state_base()
{
}
executor_ptr_type get_executor()
virtual executor_ptr_type get_executor_ptr(boost::unique_lock<boost::mutex>&)
{
return ex;
}
void set_executor_policy(executor_ptr_type aex)
{
set_executor();
ex = aex;
}
void set_executor_policy(executor_ptr_type aex, boost::lock_guard<boost::mutex>&)
{
set_executor();
ex = aex;
}
void set_executor_policy(executor_ptr_type aex, boost::unique_lock<boost::mutex>&)
{
set_executor();
ex = aex;
return executor_ptr_type();
}
bool valid(boost::unique_lock<boost::mutex>&) { return is_valid_; }
@@ -532,8 +516,8 @@ namespace boost
shared_state():
result()
{}
shared_state(exceptional_ptr const& ex):
detail::shared_state_base(ex), result()
shared_state(exceptional_ptr const& excp):
detail::shared_state_base(excp), result()
{}
@@ -678,8 +662,8 @@ namespace boost
result(0)
{}
shared_state(exceptional_ptr const& ex):
detail::shared_state_base(ex), result(0)
shared_state(exceptional_ptr const& excp):
detail::shared_state_base(excp), result(0)
{}
~shared_state()
@@ -745,8 +729,8 @@ namespace boost
shared_state()
{}
shared_state(exceptional_ptr const& ex):
detail::shared_state_base(ex)
shared_state(exceptional_ptr const& excp):
detail::shared_state_base(excp)
{}
void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
@@ -795,6 +779,40 @@ namespace boost
shared_state& operator=(shared_state const&);
};
template <typename T, typename Executor>
struct executor_shared_state: shared_state<T> {
typedef Executor executor_type;
executor_type& ex;
executor_ptr_type ex_ptr;
executor_shared_state(Executor& ex):
shared_state<T>(),
ex(ex)
{
this->set_executor();
}
executor_shared_state(Executor& ex, exceptional_ptr const& excp):
shared_state<T>(excp),
ex(ex)
{
this->set_executor();
}
executor_type& get_executor()
{
return ex;
}
executor_ptr_type get_executor_ptr(boost::unique_lock<boost::mutex>&)
{
if (! ex_ptr)
{
ex_ptr.reset(new executor_ref<Executor>(ex));
}
return ex_ptr;
}
};
/////////////////////////
/// future_async_shared_state_base
/////////////////////////
@@ -1227,8 +1245,8 @@ namespace boost
typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
static //BOOST_CONSTEXPR
future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) {
return future_ptr(new detail::shared_state<R>(ex));
future_ptr make_exceptional_future_ptr(exceptional_ptr const& excp) {
return future_ptr(new detail::shared_state<R>(excp));
}
future_ptr future_;
@@ -1246,8 +1264,8 @@ namespace boost
//BOOST_CONSTEXPR
basic_future(exceptional_ptr const& ex)
: future_(make_exceptional_future_ptr(ex))
basic_future(exceptional_ptr const& excp)
: future_(make_exceptional_future_ptr(excp))
{
}
@@ -1607,8 +1625,8 @@ namespace boost
BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
//BOOST_CONSTEXPR
BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
base_type(ex) {}
BOOST_THREAD_FUTURE(exceptional_ptr const& excp):
base_type(excp) {}
~BOOST_THREAD_FUTURE() {
}
@@ -1865,8 +1883,8 @@ namespace boost
BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
//BOOST_CONSTEXPR
BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
base_type(ex) {}
BOOST_THREAD_FUTURE(exceptional_ptr const& excp):
base_type(excp) {}
~BOOST_THREAD_FUTURE() {
}
@@ -2031,8 +2049,8 @@ namespace boost
BOOST_CONSTEXPR shared_future()
{}
//BOOST_CONSTEXPR
shared_future(exceptional_ptr const& ex):
base_type(ex) {}
shared_future(exceptional_ptr const& excp):
base_type(excp) {}
~shared_future()
{}
@@ -2153,6 +2171,15 @@ namespace boost
future_obtained = false;
}
#endif
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
template <class Executor>
promise(boost::executor_arg_t, Executor& ex):
future_(new detail::executor_shared_state<R, Executor>(ex)),
future_obtained(false)
{
}
#endif
promise():
#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
future_(),
@@ -2197,18 +2224,6 @@ namespace boost
std::swap(future_obtained,other.future_obtained);
}
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
void set_executor(executor_ptr_type aex)
{
lazy_init();
if (future_.get()==0)
{
boost::throw_exception(promise_moved());
}
boost::lock_guard<boost::mutex> lk(future_->mutex);
future_->set_executor_policy(aex, lk);
}
#endif
// Result retrieval
BOOST_THREAD_FUTURE<R> get_future()
{
@@ -2291,9 +2306,9 @@ namespace boost
future_->mark_exceptional_finish_internal(p, lock);
}
template <typename E>
void set_exception(E ex)
void set_exception(E excp)
{
set_exception(boost::copy_exception(ex));
set_exception(boost::copy_exception(excp));
}
// setting the result with deferred notification
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
@@ -2333,9 +2348,9 @@ namespace boost
future_->set_exception_at_thread_exit(e);
}
template <typename E>
void set_exception_at_thread_exit(E ex)
void set_exception_at_thread_exit(E excp)
{
set_exception_at_thread_exit(boost::copy_exception(ex));
set_exception_at_thread_exit(boost::copy_exception(excp));
}
template<typename F>
@@ -2381,6 +2396,14 @@ namespace boost
future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) );
future_obtained = false;
}
#endif
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
template <class Executor>
promise(boost::executor_arg_t, Executor& ex):
future_(new detail::executor_shared_state<R&, Executor>(ex)),
future_obtained(false)
{
}
#endif
promise():
#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
@@ -2464,9 +2487,9 @@ namespace boost
future_->mark_exceptional_finish_internal(p, lock);
}
template <typename E>
void set_exception(E ex)
void set_exception(E excp)
{
set_exception(boost::copy_exception(ex));
set_exception(boost::copy_exception(excp));
}
// setting the result with deferred notification
@@ -2488,9 +2511,9 @@ namespace boost
future_->set_exception_at_thread_exit(e);
}
template <typename E>
void set_exception_at_thread_exit(E ex)
void set_exception_at_thread_exit(E excp)
{
set_exception_at_thread_exit(boost::copy_exception(ex));
set_exception_at_thread_exit(boost::copy_exception(excp));
}
template<typename F>
@@ -2533,6 +2556,14 @@ namespace boost
future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) );
future_obtained = false;
}
#endif
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
template <class Executor>
promise(boost::executor_arg_t, Executor& ex):
future_(new detail::executor_shared_state<void, Executor>(ex)),
future_obtained(false)
{
}
#endif
promise():
#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
@@ -2620,9 +2651,9 @@ namespace boost
future_->mark_exceptional_finish_internal(p,lock);
}
template <typename E>
void set_exception(E ex)
void set_exception(E excp)
{
set_exception(boost::copy_exception(ex));
set_exception(boost::copy_exception(excp));
}
// setting the result with deferred notification
@@ -2644,9 +2675,9 @@ namespace boost
future_->set_exception_at_thread_exit(e);
}
template <typename E>
void set_exception_at_thread_exit(E ex)
void set_exception_at_thread_exit(E excp)
{
set_exception_at_thread_exit(boost::copy_exception(ex));
set_exception_at_thread_exit(boost::copy_exception(excp));
}
template<typename F>
@@ -3469,15 +3500,6 @@ namespace boost
return *this;
}
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
void set_executor(executor_ptr_type aex)
{
if (!valid())
boost::throw_exception(task_moved());
boost::lock_guard<boost::mutex> lk(task->mutex);
task->set_executor_policy(aex, lk);
}
#endif
void reset() {
if (!valid())
boost::throw_exception(future_error(system::make_error_code(future_errc::no_state)));
@@ -3664,6 +3686,9 @@ namespace detail
typename decay<ArgTypes>::type...
)>::type>
async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
typedef typename boost::result_of<typename decay<F>::type(
typename decay<ArgTypes>::type...
)>::type R;
typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
typedef typename BF::result_type Rp;
@@ -3841,22 +3866,21 @@ namespace detail {
/////////////////////////
/// future_executor_shared_state_base
/////////////////////////
template<typename Rp>
struct future_executor_shared_state: shared_state<Rp>
template<typename Rp, typename Ex>
struct future_executor_shared_state: executor_shared_state<Rp, Ex>
{
typedef shared_state<Rp> base_type;
typedef executor_shared_state<Rp, Ex> base_type;
protected:
public:
future_executor_shared_state() {
future_executor_shared_state(Ex& ex) : base_type(ex) {
}
template <class Fp, class Executor>
void init(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f)
template <class Fp>
void init(BOOST_THREAD_FWD_REF(Fp) f)
{
typedef typename decay<Fp>::type Cont;
this->set_executor_policy(executor_ptr_type(new executor_ref<Executor>(ex)));
shared_state_nullary_task<Rp,Cont> t(this->shared_from_this(), boost::forward<Fp>(f));
ex.submit(boost::move(t));
this->ex.submit(boost::move(t));
}
~future_executor_shared_state() {}
@@ -3868,9 +3892,9 @@ namespace detail {
template <class Rp, class Fp, class Executor>
BOOST_THREAD_FUTURE<Rp>
make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) {
shared_ptr<future_executor_shared_state<Rp> >
h(new future_executor_shared_state<Rp>());
h->init(ex, boost::forward<Fp>(f));
shared_ptr<future_executor_shared_state<Rp, Executor> >
h(new future_executor_shared_state<Rp, Executor>(ex));
h->init(boost::forward<Fp>(f));
return BOOST_THREAD_FUTURE<Rp>(h);
}
@@ -4151,16 +4175,16 @@ namespace detail {
template <typename T>
BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr ex) {
BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr excp) {
promise<T> p;
p.set_exception(ex);
p.set_exception(excp);
return BOOST_THREAD_MAKE_RV_REF(p.get_future());
}
template <typename T, typename E>
BOOST_THREAD_FUTURE<T> make_exceptional_future(E ex) {
BOOST_THREAD_FUTURE<T> make_exceptional_future(E excp) {
promise<T> p;
p.set_exception(boost::copy_exception(ex));
p.set_exception(boost::copy_exception(excp));
return BOOST_THREAD_MAKE_RV_REF(p.get_future());
}
@@ -4171,8 +4195,8 @@ namespace detail {
return BOOST_THREAD_MAKE_RV_REF(p.get_future());
}
template <typename T>
BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) {
return make_exceptional_future<T>(ex);
BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr excp) {
return make_exceptional_future<T>(excp);
}
#if 0
@@ -4226,11 +4250,23 @@ namespace detail
{
F parent;
Fp continuation;
shared_ptr<shared_state_base> centinel;
public:
continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
: parent(boost::move(f)),
continuation(boost::move(c))
: ShSt(),
parent(boost::move(f)),
continuation(boost::move(c)),
centinel(parent.future_)
{
}
template <class Ex>
continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c, Ex& ex)
: ShSt(ex),
parent(boost::move(f)),
continuation(boost::move(c)),
centinel(parent.future_)
{
}
@@ -4245,31 +4281,6 @@ namespace detail
} catch(...) {
this->mark_exceptional_finish();
}
// make sure parent is really cleared to prevent memory "leaks"
this->parent = F();
}
void call(boost::unique_lock<boost::mutex>& lck) {
try {
relocker relock(lck);
// neither continuation nor parent are protected by the lock - call() must only
// be called once, and no one else must modify it.
Rp res = this->continuation(boost::move(this->parent));
// make sure parent is really cleared to prevent memory "leaks"
this->parent = F();
relock.lock();
this->mark_finished_with_result_internal(boost::move(res), lck);
} catch (...) {
this->mark_exceptional_finish_internal(current_exception(), lck);
// make sure parent is really cleared to prevent memory "leaks"
relocker relock(lck);
this->parent = F();
}
}
static void run(shared_ptr<boost::detail::shared_state_base> that_)
@@ -4286,11 +4297,23 @@ namespace detail
{
F parent;
Fp continuation;
shared_ptr<shared_state_base> centinel;
public:
continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
: parent(boost::move(f)),
continuation(boost::move(c))
: ShSt(),
parent(boost::move(f)),
continuation(boost::move(c)),
centinel(parent.future_)
{
}
template <class Ex>
continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c, Ex& ex)
: ShSt(ex),
parent(boost::move(f)),
continuation(boost::move(c)),
centinel(parent.future_)
{
}
@@ -4307,29 +4330,6 @@ namespace detail
} catch(...) {
this->mark_exceptional_finish();
}
// make sure parent is really cleared to prevent memory "leaks"
this->parent = F();
}
void call(boost::unique_lock<boost::mutex>& lck) {
try {
{
relocker relock(lck);
// neither continuation nor parent are protected by the lock - call() must only
// be called once, and no one else must modify it.
this->continuation(boost::move(this->parent));
// make sure parent is really cleared to prevent memory "leaks"
this->parent = F();
}
this->mark_finished_with_result_internal(lck);
} catch (...) {
this->mark_exceptional_finish_internal(current_exception(), lck);
// make sure parent is really cleared to prevent memory "leaks"
relocker relock(lck);
this->parent = F();
}
}
static void run(shared_ptr<boost::detail::shared_state_base> that_)
@@ -4413,27 +4413,25 @@ namespace detail
namespace detail {
template<typename F, typename Rp, typename Fp>
struct future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
template<typename F, typename Rp, typename Fp, typename Ex>
struct future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp,executor_shared_state<Rp, Ex> >
{
typedef continuation_shared_state<F,Rp,Fp> base_type;
typedef continuation_shared_state<F,Rp,Fp,executor_shared_state<Rp, Ex> > base_type;
public:
future_executor_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
: base_type(boost::move(f), boost::forward<Fp>(c))
future_executor_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c, Ex& ex)
: base_type(boost::move(f), boost::forward<Fp>(c), ex)
{
}
template <class Ex>
void init(boost::unique_lock<boost::mutex> &lk, Ex& ex)
void init(boost::unique_lock<boost::mutex> &lk)
{
this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk);
this->base_type::init(lk);
}
void launch_continuation() {
run_it<base_type> fct(static_shared_from_this(this));
this->get_executor()->submit(boost::move(fct));
this->get_executor().submit(boost::move(fct));
}
~future_executor_continuation_shared_state() {}
@@ -4474,28 +4472,26 @@ namespace detail {
/////////////////////////
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
template<typename F, typename Rp, typename Fp>
struct shared_future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp>
template<typename F, typename Rp, typename Fp, class Ex>
struct shared_future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp,executor_shared_state<Rp, Ex> >
{
typedef continuation_shared_state<F,Rp,Fp> base_type;
typedef continuation_shared_state<F,Rp,Fp,executor_shared_state<Rp, Ex> > base_type;
public:
shared_future_executor_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
: base_type(boost::move(f), boost::forward<Fp>(c))
shared_future_executor_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c, Ex& ex)
: base_type(boost::move(f), boost::forward<Fp>(c), ex)
{
}
template <class Ex>
void init(boost::unique_lock<boost::mutex> &lk, Ex& ex)
void init(boost::unique_lock<boost::mutex> &lk)
{
this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk);
this->base_type::init(lk);
}
void launch_continuation() {
run_it<base_type> fct(static_shared_from_this(this));
this->get_executor()->submit(boost::move(fct));
this->get_executor().submit(boost::move(fct));
}
~shared_future_executor_continuation_shared_state() {}
@@ -4516,12 +4512,62 @@ namespace detail {
this->set_deferred();
}
virtual void execute(boost::unique_lock<boost::mutex>& lk) {
this->parent.wait();
this->call(lk);
virtual void launch_continuation() {
boost::unique_lock<boost::mutex> lk(this->mutex);
if (this->is_deferred_) {
this->is_deferred_=false;
this->execute(lk);
}
}
virtual void launch_continuation() { }
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
try {
Fp local_fuct=boost::move(this->continuation);
F ftmp = boost::move(this->parent);
relocker relock(lck);
Rp res = local_fuct(boost::move(ftmp));
relock.lock();
this->mark_finished_with_result_internal(boost::move(res), lck);
} catch (...) {
this->mark_exceptional_finish_internal(current_exception(), lck);
}
}
};
template<typename F, typename Fp>
struct future_deferred_continuation_shared_state<F,void,Fp>: continuation_shared_state<F,void,Fp>
{
typedef continuation_shared_state<F,void,Fp> base_type;
public:
future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
: base_type(boost::move(f), boost::forward<Fp>(c))
{
this->set_deferred();
}
~future_deferred_continuation_shared_state() {
}
virtual void launch_continuation() {
boost::unique_lock<boost::mutex> lk(this->mutex);
if (this->is_deferred_) {
this->is_deferred_=false;
this->execute(lk);
}
}
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
try {
Fp local_fuct=boost::move(this->continuation);
F ftmp = boost::move(this->parent);
relocker relock(lck);
local_fuct(boost::move(ftmp));
relock.lock();
this->mark_finished_with_result_internal(lck);
} catch (...) {
this->mark_exceptional_finish_internal(current_exception(), lck);
}
}
};
//////////////////////////
@@ -4539,12 +4585,59 @@ namespace detail {
this->set_deferred();
}
virtual void execute(boost::unique_lock<boost::mutex>& lk) {
this->parent.wait();
this->call(lk);
virtual void launch_continuation() {
boost::unique_lock<boost::mutex> lk(this->mutex);
if (this->is_deferred_) {
this->is_deferred_=false;
this->execute(lk);
}
}
virtual void launch_continuation() { }
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
try {
Fp local_fuct=boost::move(this->continuation);
F ftmp = this->parent;
relocker relock(lck);
Rp res = local_fuct(ftmp);
relock.lock();
this->mark_finished_with_result_internal(boost::move(res), lck);
} catch (...) {
this->mark_exceptional_finish_internal(current_exception(), lck);
}
}
};
template<typename F, typename Fp>
struct shared_future_deferred_continuation_shared_state<F,void,Fp>: continuation_shared_state<F,void,Fp>
{
typedef continuation_shared_state<F,void,Fp> base_type;
public:
shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
: base_type(boost::move(f), boost::forward<Fp>(c))
{
this->set_deferred();
}
virtual void launch_continuation() {
boost::unique_lock<boost::mutex> lk(this->mutex);
if (this->is_deferred_) {
this->is_deferred_=false;
this->execute(lk);
}
}
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
try {
Fp local_fuct=boost::move(this->continuation);
F ftmp = this->parent;
relocker relock(lck);
local_fuct(ftmp);
relock.lock();
this->mark_finished_with_result_internal(lck);
} catch (...) {
this->mark_exceptional_finish_internal(current_exception(), lck);
}
}
};
////////////////////////////////
@@ -4589,9 +4682,9 @@ namespace detail {
boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
BOOST_THREAD_FWD_REF(Fp) c) {
typedef typename decay<Fp>::type Cont;
shared_ptr<future_executor_continuation_shared_state<F,Rp, Cont> >
h(new future_executor_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
h->init(lock, ex);
shared_ptr<future_executor_continuation_shared_state<F,Rp, Cont, Ex> >
h(new future_executor_continuation_shared_state<F,Rp, Cont, Ex>(boost::move(f), boost::forward<Fp>(c), ex));
h->init(lock);
return BOOST_THREAD_FUTURE<Rp>(h);
}
@@ -4637,9 +4730,9 @@ namespace detail {
boost::unique_lock<boost::mutex> &lock, F f,
BOOST_THREAD_FWD_REF(Fp) c) {
typedef typename decay<Fp>::type Cont;
shared_ptr<shared_future_executor_continuation_shared_state<F, Rp, Cont> >
h(new shared_future_executor_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c)));
h->init(lock, ex);
shared_ptr<shared_future_executor_continuation_shared_state<F, Rp, Cont, Ex> >
h(new shared_future_executor_continuation_shared_state<F, Rp, Cont, Ex>(f, boost::forward<Fp>(c), ex));
h->init(lock);
return BOOST_THREAD_FUTURE<Rp>(h);
}
@@ -4657,23 +4750,21 @@ namespace detail {
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
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());
assert(this->future_->get_executor_ptr(lock));
typedef executor Ex;
Ex& ex = *(this->future_->get_executor());
Ex& ex = *(this->future_->get_executor_ptr(lock));
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)
)));
@@ -4686,14 +4777,15 @@ namespace detail {
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());
assert(this->future_->get_executor_ptr(lock));
typedef executor Ex;
Ex& ex = *(this->future_->get_executor());
Ex& ex = *(this->future_->get_executor_ptr(lock));
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)
)));
@@ -4721,10 +4813,7 @@ namespace detail {
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
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)
)));
@@ -4745,12 +4834,10 @@ namespace detail {
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
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)
)));
@@ -4775,10 +4862,7 @@ namespace detail {
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
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)
@@ -4789,9 +4873,9 @@ namespace detail {
)));
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
assert(this->future_->get_executor());
assert(this->future_->get_executor_ptr(lock));
typedef executor Ex;
Ex& ex = *(this->future_->get_executor());
Ex& ex = *(this->future_->get_executor_ptr(lock));
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)
)));
@@ -4809,9 +4893,9 @@ namespace detail {
)));
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
assert(this->future_->get_executor());
assert(this->future_->get_executor_ptr(lock));
typedef executor Ex;
Ex& ex = *(this->future_->get_executor());
Ex& ex = *(this->future_->get_executor_ptr(lock));
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)
)));
@@ -4841,10 +4925,7 @@ namespace detail {
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
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)
)));
@@ -4867,10 +4948,7 @@ namespace detail {
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
launch policy = this->launch_policy(lock);
if (underlying_cast<int>(policy) & int(launch::deferred)) {
@@ -4903,13 +4981,14 @@ namespace detail {
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());
Ex& ex = *(this->future_->get_executor_ptr(lock));
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)
)));
@@ -4922,13 +5001,14 @@ namespace detail {
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());
Ex& ex = *(this->future_->get_executor_ptr(lock));
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)
)));
@@ -4982,6 +5062,7 @@ namespace detail {
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)
)));
@@ -5150,11 +5231,7 @@ namespace detail
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
{
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
}
#endif

View File

@@ -68,14 +68,17 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
pthread_mutex_t* the_mutex = &internal_mutex;
guard.activate(m);
do {
res = pthread_cond_wait(&cond,&internal_mutex);
} while (res == EINTR);
#else
//boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
#endif
do {
res = pthread_cond_wait(&cond,the_mutex);
} while (res == EINTR);
#endif
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
@@ -96,17 +99,18 @@ namespace boost
boost::throw_exception(condition_error(EPERM, "boost::condition_variable::do_wait_until() failed precondition mutex not owned"));
}
#endif
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
int cond_res;
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
pthread_mutex_t* the_mutex = &internal_mutex;
guard.activate(m);
cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
#else
//boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
#endif
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
#endif
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
@@ -174,7 +178,7 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
#else
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
#endif
guard.activate(m);
res=pthread_cond_wait(&cond,&internal_mutex);
@@ -401,7 +405,7 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
#else
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
#endif
guard.activate(m);
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
@@ -419,6 +423,8 @@ namespace boost
}
return true;
}
};
}

View File

@@ -80,8 +80,8 @@ namespace boost
{
static void tls_destructor(void* data)
{
//boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(data)->shared_from_this();
boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
//boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(data)->shared_from_this();
if(thread_info)
{
@@ -110,7 +110,10 @@ namespace boost
thread_info->tss_data.erase(current);
}
}
thread_info->self.reset();
if (thread_info) // fixme: should we test this?
{
thread_info->self.reset();
}
}
}
}

View File

@@ -963,8 +963,6 @@ rule thread-compile ( sources : reqs * : name )
#[ thread-run test_11256.cpp ]
#[ thread-run test_11499.cpp ]
#[ thread-run test_11611.cpp ]
#[ thread-run test_11818.cpp ]
[ thread-run test_11796.cpp ]
;

View File

@@ -1,33 +0,0 @@
// Copyright (C) 2015 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>
boost::thread th;
int main()
{
for (auto ti = 0; ti < 1000; ti++)
{
th = boost::thread([ti]()
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
std::cout << ti << std::endl;
});
}
std::string st;
std::cin >> st;
// for (int i = 0; i < 10; ++i) {
// std::cout << "." << i << std::endl;
// boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
// }
th.join();
return 0;
}

View File

@@ -1,64 +0,0 @@
// Copyright (C) 2014 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 4
#include <boost/config.hpp>
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/future.hpp>
#include <boost/thread/thread.hpp>
#include <thread>
int main()
{
{
boost::promise<int> promise;
boost::future<int> future = promise.get_future();
boost::future<int> result =
future.then
(
boost::launch::deferred,
[](boost::future<int> && f)
{
std::cout << std::this_thread::get_id() << ": callback" << std::endl;
std::cout << "The value is: " << f.get() << std::endl;
return f.get();
}
);
// We could not reach here.
std::cout << std::this_thread::get_id() << ": function" << std::endl;
promise.set_value(0);
}
{
boost::promise<int> promise;
boost::shared_future<int> future = promise.get_future().share();
boost::future<int> result =
future.then
(
boost::launch::deferred,
[](boost::shared_future<int> && f)
{
std::cout << std::this_thread::get_id() << ": callback" << std::endl;
std::cout << "The value is: " << f.get() << std::endl;
return f.get();
}
);
// We could not reach here.
std::cout << std::this_thread::get_id() << ": function" << std::endl;
promise.set_value(0);
}
return 0;
}