mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
2 Commits
boost-1.60
...
feature/as
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e427659a4 | ||
|
|
c108444e78 |
@@ -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]
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.]]
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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_)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ]
|
||||
|
||||
;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user