/usr/include/boost/thread
Edit: /usr/include/boost/thread/future.hpp (203792B)
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_FUTURE_HPP
#define BOOST_THREAD_FUTURE_HPP
#include
// boost::thread::future requires exception handling
// due to boost::exception::exception_ptr dependency
//#define BOOST_THREAD_CONTINUATION_SYNC
#ifdef BOOST_NO_EXCEPTIONS
namespace boost
{
namespace detail {
struct shared_state_base {
void notify_deferred() {}
};
}
}
#else
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
#include
#else
#include
#endif
#include
#include
#ifdef BOOST_THREAD_USES_CHRONO
#include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include
#include
#if ! defined BOOST_NO_CXX11_ALLOCATOR
#include
#endif
#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
#include
#include
#endif
#include
#include
#include
#include
#if defined BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_FUTURE future
#else
#define BOOST_THREAD_FUTURE unique_future
#endif
namespace boost
{
template
shared_ptr static_shared_from_this(T* that)
{
return static_pointer_cast(that->shared_from_this());
}
template
shared_ptr static_shared_from_this(T const* that)
{
return static_pointer_cast(that->shared_from_this());
}
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
#else
namespace executors {
class executor;
}
using executors::executor;
#endif
typedef shared_ptr executor_ptr_type;
namespace detail
{
struct relocker
{
boost::unique_lock& lock_;
relocker(boost::unique_lock& lk):
lock_(lk)
{
lock_.unlock();
}
~relocker()
{
if (! lock_.owns_lock()) {
lock_.lock();
}
}
void lock() {
if (! lock_.owns_lock()) {
lock_.lock();
}
}
private:
relocker& operator=(relocker const&);
};
struct shared_state_base : enable_shared_from_this
{
typedef std::list waiter_list;
typedef waiter_list::iterator notify_when_ready_handle;
// This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout.
typedef shared_ptr continuation_ptr_type;
typedef std::vector continuations_type;
boost::exception_ptr exception;
bool done;
bool is_valid_;
bool is_deferred_;
bool is_constructed;
launch policy_;
mutable boost::mutex mutex;
boost::condition_variable waiters;
waiter_list external_waiters;
boost::function 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()
{
}
shared_state_base():
done(false),
is_valid_(true),
is_deferred_(false),
is_constructed(false),
policy_(launch::none),
continuations(),
ex_()
{}
shared_state_base(exceptional_ptr const& ex):
exception(ex.ptr_),
done(true),
is_valid_(true),
is_deferred_(false),
is_constructed(false),
policy_(launch::none),
continuations(),
ex_()
{}
virtual ~shared_state_base()
{
}
bool is_done()
{
return done;
}
executor_ptr_type get_executor()
{
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&)
{
set_executor();
ex_ = aex;
}
void set_executor_policy(executor_ptr_type aex, boost::unique_lock&)
{
set_executor();
ex_ = aex;
}
bool valid(boost::unique_lock&) { return is_valid_; }
bool valid() {
boost::unique_lock lk(this->mutex);
return valid(lk);
}
void invalidate(boost::unique_lock&) { is_valid_ = false; }
void invalidate() {
boost::unique_lock lk(this->mutex);
invalidate(lk);
}
void validate(boost::unique_lock&) { is_valid_ = true; }
void validate() {
boost::unique_lock lk(this->mutex);
validate(lk);
}
void set_deferred()
{
is_deferred_ = true;
policy_ = launch::deferred;
}
void set_async()
{
is_deferred_ = false;
policy_ = launch::async;
}
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
void set_executor()
{
is_deferred_ = false;
policy_ = launch::executor;
}
#else
void set_executor()
{
}
#endif
notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
{
boost::unique_lock lock(this->mutex);
do_callback(lock);
return external_waiters.insert(external_waiters.end(),&cv);
}
void unnotify_when_ready(notify_when_ready_handle it)
{
boost::lock_guard lock(this->mutex);
external_waiters.erase(it);
}
#if 0
// this inline definition results in ODR. See https://github.com/boostorg/thread/issues/193
// to avoid it, we define the function on the derived templates using the macro BOOST_THREAD_DO_CONTINUATION
#define BOOST_THREAD_DO_CONTINUATION
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
void do_continuation(boost::unique_lock& lock)
{
if (! continuations.empty()) {
continuations_type the_continuations = continuations;
continuations.clear();
relocker rlk(lock);
for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) {
(*it)->launch_continuation();
}
}
}
#else
void do_continuation(boost::unique_lock&)
{
}
#endif
#else
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#define BOOST_THREAD_DO_CONTINUATION \
void do_continuation(boost::unique_lock& lock) \
{ \
if (! this->continuations.empty()) { \
continuations_type the_continuations = this->continuations; \
this->continuations.clear(); \
relocker rlk(lock); \
for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) { \
(*it)->launch_continuation(); \
} \
} \
}
#else
#define BOOST_THREAD_DO_CONTINUATION \
void do_continuation(boost::unique_lock&) \
{ \
}
#endif
virtual void do_continuation(boost::unique_lock&) = 0;
#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock& lock)
{
continuations.push_back(continuation);
if (done) {
do_continuation(lock);
}
}
#endif
void mark_finished_internal(boost::unique_lock& lock)
{
done=true;
waiters.notify_all();
for(waiter_list::const_iterator it=external_waiters.begin(),
end=external_waiters.end();it!=end;++it)
{
(*it)->notify_all();
}
do_continuation(lock);
}
void notify_deferred()
{
boost::unique_lock lock(this->mutex);
mark_finished_internal(lock);
}
void do_callback(boost::unique_lock& lock)
{
if(callback && !done)
{
boost::function local_callback=callback;
relocker relock(lock);
local_callback();
}
}
virtual bool run_if_is_deferred()
{
boost::unique_lock lk(this->mutex);
if (is_deferred_)
{
is_deferred_=false;
execute(lk);
return true;
}
else
return false;
}
virtual bool run_if_is_deferred_or_ready()
{
boost::unique_lock lk(this->mutex);
if (is_deferred_)
{
is_deferred_=false;
execute(lk);
return true;
}
else
return done;
}
void wait_internal(boost::unique_lock &lk, bool rethrow=true)
{
do_callback(lk);
if (is_deferred_)
{
is_deferred_=false;
execute(lk);
}
waiters.wait(lk, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
if(rethrow && exception)
{
boost::rethrow_exception(exception);
}
}
virtual void wait(boost::unique_lock& lock, bool rethrow=true)
{
wait_internal(lock, rethrow);
}
void wait(bool rethrow=true)
{
boost::unique_lock lock(this->mutex);
wait(lock, rethrow);
}
#if defined BOOST_THREAD_USES_DATETIME
template
bool timed_wait(Duration const& rel_time)
{
boost::unique_lock lock(this->mutex);
if (is_deferred_)
return false;
do_callback(lock);
return waiters.timed_wait(lock, rel_time, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
}
bool timed_wait_until(boost::system_time const& target_time)
{
boost::unique_lock lock(this->mutex);
if (is_deferred_)
return false;
do_callback(lock);
return waiters.timed_wait(lock, target_time, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template
future_status
wait_until(const chrono::time_point& abs_time)
{
boost::unique_lock lock(this->mutex);
if (is_deferred_)
return future_status::deferred;
do_callback(lock);
if(!waiters.wait_until(lock, abs_time, boost::bind(&shared_state_base::is_done, boost::ref(*this))))
{
return future_status::timeout;
}
return future_status::ready;
}
#endif
void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock& lock)
{
exception=e;
mark_finished_internal(lock);
}
void mark_exceptional_finish()
{
boost::unique_lock lock(this->mutex);
mark_exceptional_finish_internal(boost::current_exception(), lock);
}
void set_exception_deferred(exception_ptr e)
{
unique_lock lk(this->mutex);
if (has_value(lk))
{
throw_exception(promise_already_satisfied());
}
exception=e;
this->is_constructed = true;
}
void set_exception_at_thread_exit(exception_ptr e)
{
set_exception_deferred(e);
// unique_lock lk(this->mutex);
// if (has_value(lk))
// {
// throw_exception(promise_already_satisfied());
// }
// exception=e;
// this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
bool has_value() const
{
boost::lock_guard lock(this->mutex);
return done && ! exception;
}
bool has_value(unique_lock& ) const
{
return done && ! exception;
}
bool has_exception() const
{
boost::lock_guard lock(this->mutex);
return done && exception;
}
launch launch_policy(boost::unique_lock&) const
{
return policy_;
}
future_state::state get_state(boost::unique_lock&) const
{
if(!done)
{
return future_state::waiting;
}
else
{
return future_state::ready;
}
}
future_state::state get_state() const
{
boost::lock_guard guard(this->mutex);
if(!done)
{
return future_state::waiting;
}
else
{
return future_state::ready;
}
}
exception_ptr get_exception_ptr()
{
boost::unique_lock lock(this->mutex);
wait_internal(lock, false);
return exception;
}
template
void set_wait_callback(F f,U* u)
{
boost::lock_guard lock(this->mutex);
callback=boost::bind(f,boost::ref(*u));
}
virtual void execute(boost::unique_lock&) {}
private:
shared_state_base(shared_state_base const&);
shared_state_base& operator=(shared_state_base const&);
};
// Used to create stand-alone futures
template
struct shared_state:
detail::shared_state_base
{
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
typedef boost::optional storage_type;
#else
typedef boost::csbl::unique_ptr storage_type;
#endif
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef T const& source_reference_type;
typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
typedef T move_dest_type;
#elif defined BOOST_THREAD_USES_MOVE
typedef typename conditional::value,T,T const&>::type source_reference_type;
typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
typedef T move_dest_type;
#else
typedef T& source_reference_type;
typedef typename conditional::value, BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
typedef typename conditional::value, BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
#endif
typedef const T& shared_future_get_result_type;
storage_type result;
shared_state():
result()
{}
shared_state(exceptional_ptr const& ex):
detail::shared_state_base(ex), result()
{}
// locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
BOOST_THREAD_DO_CONTINUATION
void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock& lock)
{
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
result = result_;
#else
result.reset(new T(result_));
#endif
this->mark_finished_internal(lock);
}
void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock& lock)
{
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
result = boost::move(result_);
#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
result.reset(new T(boost::move(result_)));
#else
result.reset(new T(static_cast(result_)));
#endif
this->mark_finished_internal(lock);
}
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template
void mark_finished_with_result_internal(boost::unique_lock& lock, BOOST_THREAD_FWD_REF(Args)... args)
{
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
result.emplace(boost::forward(args)...);
#else
result.reset(new T(boost::forward(args)...));
#endif
this->mark_finished_internal(lock);
}
#endif
void mark_finished_with_result(source_reference_type result_)
{
boost::unique_lock lock(this->mutex);
this->mark_finished_with_result_internal(result_, lock);
}
void mark_finished_with_result(rvalue_source_type result_)
{
boost::unique_lock lock(this->mutex);
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
mark_finished_with_result_internal(boost::move(result_), lock);
#else
mark_finished_with_result_internal(static_cast(result_), lock);
#endif
}
storage_type& get_storage(boost::unique_lock& lk)
{
wait_internal(lk);
return result;
}
virtual move_dest_type get(boost::unique_lock& lk)
{
return boost::move(*get_storage(lk));
}
move_dest_type get()
{
boost::unique_lock lk(this->mutex);
return this->get(lk);
}
virtual shared_future_get_result_type get_sh(boost::unique_lock& lk)
{
return *get_storage(lk);
}
shared_future_get_result_type get_sh()
{
boost::unique_lock lk(this->mutex);
return this->get_sh(lk);
}
void set_value_deferred(source_reference_type result_)
{
unique_lock lk(this->mutex);
if (this->has_value(lk))
{
throw_exception(promise_already_satisfied());
}
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
result = result_;
#else
result.reset(new T(result_));
#endif
this->is_constructed = true;
}
void set_value_deferred(rvalue_source_type result_)
{
unique_lock lk(this->mutex);
if (this->has_value(lk))
{
throw_exception(promise_already_satisfied());
}
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
result = boost::move(result_);
#else
result.reset(new T(boost::move(result_)));
#endif
#else
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
result = boost::move(result_);
#else
result.reset(new T(static_cast(result_)));
#endif
#endif
this->is_constructed = true;
}
void set_value_at_thread_exit(source_reference_type result_)
{
set_value_deferred(result_);
// unique_lock lk(this->mutex);
// if (this->has_value(lk))
// {
// throw_exception(promise_already_satisfied());
// }
//#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
// result = result_;
//#else
// result.reset(new T(result_));
//#endif
//
// this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
void set_value_at_thread_exit(rvalue_source_type result_)
{
set_value_deferred(boost::move(result_));
// unique_lock lk(this->mutex);
// if (this->has_value(lk))
// throw_exception(promise_already_satisfied());
//
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
//#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
// result = boost::move(result_);
//#else
// result.reset(new T(boost::move(result_)));
//#endif
//#else
//#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
// result = boost::move(result_);
//#else
// result.reset(new T(static_cast(result_)));
//#endif
//#endif
// this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
private:
shared_state(shared_state const&);
shared_state& operator=(shared_state const&);
};
template
struct shared_state:
detail::shared_state_base
{
typedef T* storage_type;
typedef T& source_reference_type;
typedef T& move_dest_type;
typedef T& shared_future_get_result_type;
T* result;
shared_state():
result(0)
{}
shared_state(exceptional_ptr const& ex):
detail::shared_state_base(ex), result(0)
{}
// locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
BOOST_THREAD_DO_CONTINUATION
void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock& lock)
{
result= &result_;
mark_finished_internal(lock);
}
void mark_finished_with_result(source_reference_type result_)
{
boost::unique_lock lock(this->mutex);
mark_finished_with_result_internal(result_, lock);
}
virtual T& get(boost::unique_lock& lock)
{
wait_internal(lock);
return *result;
}
T& get()
{
boost::unique_lock lk(this->mutex);
return get(lk);
}
virtual T& get_sh(boost::unique_lock& lock)
{
wait_internal(lock);
return *result;
}
T& get_sh()
{
boost::unique_lock lock(this->mutex);
return get_sh(lock);
}
void set_value_deferred(T& result_)
{
unique_lock lk(this->mutex);
if (this->has_value(lk))
{
throw_exception(promise_already_satisfied());
}
result= &result_;
this->is_constructed = true;
}
void set_value_at_thread_exit(T& result_)
{
set_value_deferred(result_);
// unique_lock lk(this->mutex);
// if (this->has_value(lk))
// throw_exception(promise_already_satisfied());
// result= &result_;
// this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
private:
shared_state(shared_state const&);
shared_state& operator=(shared_state const&);
};
template<>
struct shared_state:
detail::shared_state_base
{
typedef void shared_future_get_result_type;
typedef void move_dest_type;
shared_state()
{}
shared_state(exceptional_ptr const& ex):
detail::shared_state_base(ex)
{}
// locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
BOOST_THREAD_DO_CONTINUATION
void mark_finished_with_result_internal(boost::unique_lock& lock)
{
mark_finished_internal(lock);
}
void mark_finished_with_result()
{
boost::unique_lock lock(this->mutex);
mark_finished_with_result_internal(lock);
}
virtual void get(boost::unique_lock& lock)
{
this->wait_internal(lock);
}
void get()
{
boost::unique_lock lock(this->mutex);
this->get(lock);
}
virtual void get_sh(boost::unique_lock& lock)
{
this->wait_internal(lock);
}
void get_sh()
{
boost::unique_lock lock(this->mutex);
this->get_sh(lock);
}
void set_value_deferred()
{
unique_lock lk(this->mutex);
if (this->has_value(lk))
{
throw_exception(promise_already_satisfied());
}
this->is_constructed = true;
}
void set_value_at_thread_exit()
{
set_value_deferred();
// unique_lock lk(this->mutex);
// if (this->has_value(lk))
// {
// throw_exception(promise_already_satisfied());
// }
// this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
private:
shared_state(shared_state const&);
shared_state& operator=(shared_state const&);
};
/////////////////////////
/// future_async_shared_state_base
/////////////////////////
template
struct future_async_shared_state_base: shared_state