mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-19 02:12:24 +00:00
re-factor futures
This commit is contained in:
@@ -427,7 +427,7 @@ public:
|
||||
};
|
||||
|
||||
struct context_initializer {
|
||||
context_initializer() noexcept;
|
||||
context_initializer();
|
||||
~context_initializer() noexcept;
|
||||
};
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@ future< typename std::result_of< Fn( Args ... ) >::type >
|
||||
async( Fn && fn, Args && ... args) {
|
||||
typedef typename std::result_of< Fn( Args ... ) >::type result_type;
|
||||
|
||||
packaged_task< result_type( typename std::decay< Args >::type ... ) > pt(
|
||||
std::forward< Fn >( fn) );
|
||||
future< result_type > f( pt.get_future() );
|
||||
fiber( std::move( pt), std::forward< Args >( args) ... ).detach();
|
||||
packaged_task< result_type( typename std::decay< Args >::type ... ) > pt{
|
||||
std::forward< Fn >( fn) };
|
||||
future< result_type > f{ pt.get_future() };
|
||||
fiber{ std::move( pt), std::forward< Args >( args) ... }.detach();
|
||||
return f;
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ future< typename std::result_of< Fn( Args ... ) >::type >
|
||||
async( std::allocator_arg_t, StackAllocator salloc, Fn && fn, Args && ... args) {
|
||||
typedef typename std::result_of< Fn( Args ... ) >::type result_type;
|
||||
|
||||
packaged_task< result_type( typename std::decay< Args >::type ... ) > pt(
|
||||
std::forward< Fn >( fn) );
|
||||
future< result_type > f( pt.get_future() );
|
||||
fiber( salloc, std::move( pt), std::forward< Args >( args) ... ).detach();
|
||||
packaged_task< result_type( typename std::decay< Args >::type ... ) > pt{
|
||||
std::forward< Fn >( fn) };
|
||||
future< result_type > f{ pt.get_future() };
|
||||
fiber{ salloc, std::move( pt), std::forward< Args >( args) ... }.detach();
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,17 +34,17 @@ namespace boost {
|
||||
namespace fibers {
|
||||
namespace detail {
|
||||
|
||||
template< typename R >
|
||||
class shared_state {
|
||||
class shared_state_base {
|
||||
private:
|
||||
std::atomic< std::size_t > use_count_{ 0 };
|
||||
mutable mutex mtx_{};
|
||||
mutable condition waiters_{};
|
||||
bool ready_{ false };
|
||||
typename std::aligned_storage< sizeof( R), alignof( R) >::type storage_[1]{};
|
||||
std::exception_ptr except_{};
|
||||
std::atomic< std::size_t > use_count_{ 0 };
|
||||
mutable condition waiters_{};
|
||||
|
||||
void mark_ready_and_notify_( std::unique_lock< mutex > & lk) {
|
||||
protected:
|
||||
mutable mutex mtx_{};
|
||||
bool ready_{ false };
|
||||
std::exception_ptr except_{};
|
||||
|
||||
void mark_ready_and_notify_( std::unique_lock< mutex > & lk) noexcept {
|
||||
ready_ = true;
|
||||
lk.unlock();
|
||||
waiters_.notify_all();
|
||||
@@ -58,6 +58,103 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) {
|
||||
if ( ready_) {
|
||||
throw promise_already_satisfied();
|
||||
}
|
||||
except_ = except;
|
||||
mark_ready_and_notify_( lk);
|
||||
}
|
||||
|
||||
std::exception_ptr get_exception_ptr_( std::unique_lock< mutex > & lk) {
|
||||
wait_( lk);
|
||||
return except_;
|
||||
}
|
||||
|
||||
void wait_( std::unique_lock< mutex > & lk) const {
|
||||
waiters_.wait( lk, [this](){ return ready_; });
|
||||
}
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for_( std::unique_lock< mutex > & lk,
|
||||
std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
return waiters_.wait_for( lk, timeout_duration, [this](){ return ready_; })
|
||||
? future_status::ready
|
||||
: future_status::timeout;
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until_( std::unique_lock< mutex > & lk,
|
||||
std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
return waiters_.wait_until( lk, timeout_time, [this](){ return ready_; })
|
||||
? future_status::ready
|
||||
: future_status::timeout;
|
||||
}
|
||||
|
||||
virtual void deallocate_future() noexcept = 0;
|
||||
|
||||
public:
|
||||
shared_state_base() = default;
|
||||
|
||||
virtual ~shared_state_base() noexcept = default;
|
||||
|
||||
shared_state_base( shared_state_base const&) = delete;
|
||||
shared_state_base & operator=( shared_state_base const&) = delete;
|
||||
|
||||
void owner_destroyed() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
owner_destroyed_( lk);
|
||||
}
|
||||
|
||||
void set_exception( std::exception_ptr except) {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
set_exception_( except, lk);
|
||||
}
|
||||
|
||||
std::exception_ptr get_exception_ptr() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return get_exception_ptr_( lk);
|
||||
}
|
||||
|
||||
void wait() const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
wait_( lk);
|
||||
}
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return wait_for_( lk, timeout_duration);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return wait_until_( lk, timeout_time);
|
||||
}
|
||||
|
||||
void reset() noexcept {
|
||||
ready_ = false;
|
||||
}
|
||||
|
||||
friend inline
|
||||
void intrusive_ptr_add_ref( shared_state_base * p) noexcept {
|
||||
++p->use_count_;
|
||||
}
|
||||
|
||||
friend inline
|
||||
void intrusive_ptr_release( shared_state_base * p) noexcept {
|
||||
if ( 0 == --p->use_count_) {
|
||||
p->deallocate_future();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template< typename R >
|
||||
class shared_state : public shared_state_base {
|
||||
private:
|
||||
typename std::aligned_storage< sizeof( R), alignof( R) >::type storage_[1]{};
|
||||
|
||||
void set_value_( R const& value, std::unique_lock< mutex > & lk) {
|
||||
if ( ready_) {
|
||||
throw promise_already_satisfied();
|
||||
@@ -74,14 +171,6 @@ private:
|
||||
mark_ready_and_notify_( lk);
|
||||
}
|
||||
|
||||
void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) {
|
||||
if ( ready_) {
|
||||
throw promise_already_satisfied();
|
||||
}
|
||||
except_ = except;
|
||||
mark_ready_and_notify_( lk);
|
||||
}
|
||||
|
||||
R & get_( std::unique_lock< mutex > & lk) {
|
||||
wait_( lk);
|
||||
if ( except_) {
|
||||
@@ -90,34 +179,6 @@ private:
|
||||
return * reinterpret_cast< R * >( storage_);
|
||||
}
|
||||
|
||||
std::exception_ptr get_exception_ptr_( std::unique_lock< mutex > & lk) {
|
||||
wait_( lk);
|
||||
return except_;
|
||||
}
|
||||
|
||||
void wait_( std::unique_lock< mutex > & lk) const {
|
||||
waiters_.wait( lk, [this](){ return ready_; });
|
||||
}
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for_( std::unique_lock< mutex > & lk,
|
||||
std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
return waiters_.wait_for( lk, timeout_duration, [this](){ return ready_; })
|
||||
? future_status::ready
|
||||
: future_status::timeout;
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until_( std::unique_lock< mutex > & lk,
|
||||
std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
return waiters_.wait_until( lk, timeout_time, [this](){ return ready_; })
|
||||
? future_status::ready
|
||||
: future_status::timeout;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void deallocate_future() = 0;
|
||||
|
||||
public:
|
||||
typedef intrusive_ptr< shared_state > ptr_t;
|
||||
|
||||
@@ -132,11 +193,6 @@ public:
|
||||
shared_state( shared_state const&) = delete;
|
||||
shared_state & operator=( shared_state const&) = delete;
|
||||
|
||||
void owner_destroyed() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
owner_destroyed_( lk);
|
||||
}
|
||||
|
||||
void set_value( R const& value) {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
set_value_( value, lk);
|
||||
@@ -147,78 +203,16 @@ public:
|
||||
set_value_( std::move( value), lk);
|
||||
}
|
||||
|
||||
void set_exception( std::exception_ptr except) {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
set_exception_( except, lk);
|
||||
}
|
||||
|
||||
R & get() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return get_( lk);
|
||||
}
|
||||
|
||||
std::exception_ptr get_exception_ptr() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return get_exception_ptr_( lk);
|
||||
}
|
||||
|
||||
void wait() const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
wait_( lk);
|
||||
}
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return wait_for_( lk, timeout_duration);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return wait_until_( lk, timeout_time);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
ready_ = false;
|
||||
}
|
||||
|
||||
friend inline
|
||||
void intrusive_ptr_add_ref( shared_state * p) noexcept {
|
||||
++p->use_count_;
|
||||
}
|
||||
|
||||
friend inline
|
||||
void intrusive_ptr_release( shared_state * p) {
|
||||
if ( 0 == --p->use_count_) {
|
||||
p->deallocate_future();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template< typename R >
|
||||
class shared_state< R & > {
|
||||
class shared_state< R & > : public shared_state_base {
|
||||
private:
|
||||
std::atomic< std::size_t > use_count_{ 0 };
|
||||
mutable mutex mtx_{};
|
||||
mutable condition waiters_{};
|
||||
bool ready_{ false };
|
||||
R * value_{ nullptr };
|
||||
std::exception_ptr except_{};
|
||||
|
||||
void mark_ready_and_notify_( std::unique_lock< mutex > & lk) {
|
||||
ready_ = true;
|
||||
lk.unlock();
|
||||
waiters_.notify_all();
|
||||
}
|
||||
|
||||
void owner_destroyed_( std::unique_lock< mutex > & lk) {
|
||||
if ( ! ready_) {
|
||||
set_exception_(
|
||||
std::make_exception_ptr( broken_promise() ),
|
||||
lk);
|
||||
}
|
||||
}
|
||||
|
||||
void set_value_( R & value, std::unique_lock< mutex > & lk) {
|
||||
if ( ready_) {
|
||||
@@ -228,14 +222,6 @@ private:
|
||||
mark_ready_and_notify_( lk);
|
||||
}
|
||||
|
||||
void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) {
|
||||
if ( ready_) {
|
||||
throw promise_already_satisfied();
|
||||
}
|
||||
except_ = except;
|
||||
mark_ready_and_notify_( lk);
|
||||
}
|
||||
|
||||
R & get_( std::unique_lock< mutex > & lk) {
|
||||
wait_( lk);
|
||||
if ( except_) {
|
||||
@@ -244,129 +230,30 @@ private:
|
||||
return * value_;
|
||||
}
|
||||
|
||||
std::exception_ptr get_exception_ptr_( std::unique_lock< mutex > & lk) {
|
||||
wait_( lk);
|
||||
return except_;
|
||||
}
|
||||
|
||||
void wait_( std::unique_lock< mutex > & lk) const {
|
||||
waiters_.wait( lk, [this](){ return ready_; });
|
||||
}
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for_( std::unique_lock< mutex > & lk,
|
||||
std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
return waiters_.wait_for( lk, timeout_duration, [this](){ return ready_; })
|
||||
? future_status::ready
|
||||
: future_status::timeout;
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until_( std::unique_lock< mutex > & lk,
|
||||
std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
return waiters_.wait_until( lk, timeout_time, [this](){ return ready_; })
|
||||
? future_status::ready
|
||||
: future_status::timeout;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void deallocate_future() = 0;
|
||||
|
||||
public:
|
||||
typedef intrusive_ptr< shared_state > ptr_t;
|
||||
|
||||
shared_state() = default;
|
||||
|
||||
virtual ~shared_state() noexcept {
|
||||
}
|
||||
virtual ~shared_state() noexcept = default;
|
||||
|
||||
shared_state( shared_state const&) = delete;
|
||||
shared_state & operator=( shared_state const&) = delete;
|
||||
|
||||
void owner_destroyed() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
owner_destroyed_( lk);
|
||||
}
|
||||
|
||||
void set_value( R & value) {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
set_value_( value, lk);
|
||||
}
|
||||
|
||||
void set_exception( std::exception_ptr except) {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
set_exception_( except, lk);
|
||||
}
|
||||
|
||||
R & get() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return get_( lk);
|
||||
}
|
||||
|
||||
std::exception_ptr get_exception_ptr() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return get_exception_ptr_( lk);
|
||||
}
|
||||
|
||||
void wait() const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
wait_( lk);
|
||||
}
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return wait_for_( lk, timeout_duration);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return wait_until_( lk, timeout_time);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
ready_ = false;
|
||||
}
|
||||
|
||||
friend inline
|
||||
void intrusive_ptr_add_ref( shared_state * p) noexcept {
|
||||
++p->use_count_;
|
||||
}
|
||||
|
||||
friend inline
|
||||
void intrusive_ptr_release( shared_state * p) {
|
||||
if ( 0 == --p->use_count_) {
|
||||
p->deallocate_future();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class shared_state< void > {
|
||||
class shared_state< void > : public shared_state_base {
|
||||
private:
|
||||
std::atomic< std::size_t > use_count_{ 0 };
|
||||
mutable mutex mtx_{};
|
||||
mutable condition waiters_{};
|
||||
bool ready_{ false };
|
||||
std::exception_ptr except_{};
|
||||
|
||||
inline
|
||||
void mark_ready_and_notify_( std::unique_lock< mutex > & lk) {
|
||||
ready_ = true;
|
||||
lk.unlock();
|
||||
waiters_.notify_all();
|
||||
}
|
||||
|
||||
inline
|
||||
void owner_destroyed_( std::unique_lock< mutex > & lk) {
|
||||
if ( ! ready_) {
|
||||
set_exception_(
|
||||
std::make_exception_ptr( broken_promise() ),
|
||||
lk);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void set_value_( std::unique_lock< mutex > & lk) {
|
||||
if ( ready_) {
|
||||
@@ -375,15 +262,6 @@ private:
|
||||
mark_ready_and_notify_( lk);
|
||||
}
|
||||
|
||||
inline
|
||||
void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) {
|
||||
if ( ready_) {
|
||||
throw promise_already_satisfied();
|
||||
}
|
||||
except_ = except;
|
||||
mark_ready_and_notify_( lk);
|
||||
}
|
||||
|
||||
inline
|
||||
void get_( std::unique_lock< mutex > & lk) {
|
||||
wait_( lk);
|
||||
@@ -392,111 +270,27 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
std::exception_ptr get_exception_ptr_( std::unique_lock< mutex > & lk) {
|
||||
wait_( lk);
|
||||
return except_;
|
||||
}
|
||||
|
||||
inline
|
||||
void wait_( std::unique_lock< mutex > & lk) const {
|
||||
waiters_.wait( lk, [this](){ return ready_; });
|
||||
}
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for_( std::unique_lock< mutex > & lk,
|
||||
std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
return waiters_.wait_for( lk, timeout_duration, [this](){ return ready_; })
|
||||
? future_status::ready
|
||||
: future_status::timeout;
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until_( std::unique_lock< mutex > & lk,
|
||||
std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
return waiters_.wait_until( lk, timeout_time, [this](){ return ready_; })
|
||||
? future_status::ready
|
||||
: future_status::timeout;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void deallocate_future() = 0;
|
||||
|
||||
public:
|
||||
typedef intrusive_ptr< shared_state > ptr_t;
|
||||
|
||||
shared_state() = default;
|
||||
|
||||
virtual ~shared_state() noexcept {
|
||||
}
|
||||
virtual ~shared_state() noexcept = default;
|
||||
|
||||
shared_state( shared_state const&) = delete;
|
||||
shared_state & operator=( shared_state const&) = delete;
|
||||
|
||||
inline
|
||||
void owner_destroyed() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
owner_destroyed_( lk);
|
||||
}
|
||||
|
||||
inline
|
||||
void set_value() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
set_value_( lk);
|
||||
}
|
||||
|
||||
inline
|
||||
void set_exception( std::exception_ptr except) {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
set_exception_( except, lk);
|
||||
}
|
||||
|
||||
inline
|
||||
void get() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
get_( lk);
|
||||
}
|
||||
|
||||
inline
|
||||
std::exception_ptr get_exception_ptr() {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return get_exception_ptr_( lk);
|
||||
}
|
||||
|
||||
inline
|
||||
void wait() const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
wait_( lk);
|
||||
}
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return wait_for_( lk, timeout_duration);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
std::unique_lock< mutex > lk( mtx_);
|
||||
return wait_until_( lk, timeout_time);
|
||||
}
|
||||
|
||||
inline
|
||||
void reset() {
|
||||
ready_ = false;
|
||||
}
|
||||
|
||||
friend inline
|
||||
void intrusive_ptr_add_ref( shared_state * p) noexcept {
|
||||
++p->use_count_;
|
||||
}
|
||||
|
||||
friend inline
|
||||
void intrusive_ptr_release( shared_state * p) {
|
||||
if ( 0 == --p->use_count_) {
|
||||
p->deallocate_future();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -32,14 +32,14 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void deallocate_future() {
|
||||
void deallocate_future() noexcept override final {
|
||||
destroy_( alloc_, this);
|
||||
}
|
||||
|
||||
private:
|
||||
allocator_t alloc_;
|
||||
|
||||
static void destroy_( allocator_t & alloc, shared_state_object * p) {
|
||||
static void destroy_( allocator_t & alloc, shared_state_object * p) noexcept {
|
||||
alloc.destroy( p);
|
||||
alloc.deallocate( p, 1);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
alloc_( alloc) {
|
||||
}
|
||||
|
||||
void run( Args && ... args) {
|
||||
void run( Args && ... args) override final {
|
||||
try {
|
||||
this->set_value(
|
||||
boost::context::detail::do_invoke(
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void deallocate_future() {
|
||||
void deallocate_future() noexcept override final {
|
||||
destroy_( alloc_, this);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
Fn fn_;
|
||||
allocator_t alloc_;
|
||||
|
||||
static void destroy_( allocator_t & alloc, task_object * p) {
|
||||
static void destroy_( allocator_t & alloc, task_object * p) noexcept {
|
||||
alloc.destroy( p);
|
||||
alloc.deallocate( p, 1);
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
alloc_( alloc) {
|
||||
}
|
||||
|
||||
void run( Args && ... args) {
|
||||
void run( Args && ... args) override final {
|
||||
try {
|
||||
boost::context::detail::do_invoke(
|
||||
fn_, std::make_tuple( std::forward< Args >( args) ... ) );
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void deallocate_future() {
|
||||
void deallocate_future() noexcept override final {
|
||||
destroy_( alloc_, this);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ private:
|
||||
Fn fn_;
|
||||
allocator_t alloc_;
|
||||
|
||||
static void destroy_( allocator_t & alloc, task_object * p) {
|
||||
static void destroy_( allocator_t & alloc, task_object * p) noexcept {
|
||||
alloc.destroy( p);
|
||||
alloc.deallocate( p, 1);
|
||||
}
|
||||
|
||||
@@ -20,556 +20,446 @@
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
namespace detail {
|
||||
|
||||
template< typename R >
|
||||
class packaged_task;
|
||||
struct future_base {
|
||||
typedef typename shared_state< R >::ptr_t ptr_t;
|
||||
|
||||
template< typename R >
|
||||
class promise;
|
||||
ptr_t state_{};
|
||||
|
||||
constexpr future_base() noexcept = default;
|
||||
|
||||
explicit future_base( ptr_t const& p) noexcept :
|
||||
state_{ p } {
|
||||
}
|
||||
|
||||
~future_base() noexcept = default;
|
||||
|
||||
future_base( future_base const& other) :
|
||||
state_{ other.state_ } {
|
||||
}
|
||||
|
||||
future_base( future_base && other) noexcept :
|
||||
state_{ other.state_ } {
|
||||
other.state_.reset();
|
||||
}
|
||||
|
||||
future_base & operator=( future_base const& other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
state_ = other.state_;
|
||||
return * this;
|
||||
}
|
||||
|
||||
future_base & operator=( future_base && other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
state_ = other.state_;
|
||||
other.state_.reset();
|
||||
return * this;
|
||||
}
|
||||
|
||||
bool valid() const noexcept {
|
||||
return nullptr != state_.get();
|
||||
}
|
||||
|
||||
std::exception_ptr get_exception_ptr() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
return state_->get_exception_ptr();
|
||||
}
|
||||
|
||||
void wait() const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
state_->wait();
|
||||
}
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
return state_->wait_for( timeout_duration);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
return state_->wait_until( timeout_time);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template< typename R >
|
||||
class shared_future;
|
||||
|
||||
template< typename R >
|
||||
class future {
|
||||
class future : private detail::future_base< R > {
|
||||
private:
|
||||
typedef typename detail::shared_state< R >::ptr_t ptr_t;
|
||||
typedef detail::future_base< R > base_t;
|
||||
|
||||
friend class shared_future< R >;
|
||||
|
||||
ptr_t state_;
|
||||
|
||||
public:
|
||||
future() noexcept :
|
||||
state_() {
|
||||
}
|
||||
constexpr future() noexcept = default;
|
||||
|
||||
explicit future( ptr_t const& p) noexcept :
|
||||
state_( p) {
|
||||
}
|
||||
|
||||
~future() noexcept {
|
||||
explicit future( typename base_t::ptr_t const& p) noexcept :
|
||||
base_t{ p } {
|
||||
}
|
||||
|
||||
future( future const&) = delete;
|
||||
future & operator=( future const&) = delete;
|
||||
|
||||
future( future< R > && other) noexcept :
|
||||
state_( std::move( other.state_) ) {
|
||||
future( future && other) noexcept :
|
||||
base_t{ std::forward< future >( other) } {
|
||||
}
|
||||
|
||||
future & operator=( future< R > && other) noexcept {
|
||||
if ( this != & other) {
|
||||
state_ = std::move( other.state_);
|
||||
}
|
||||
future & operator=( future && other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
base_t::operator=( std::forward< future >( other) );
|
||||
return * this;
|
||||
}
|
||||
|
||||
bool valid() const noexcept {
|
||||
return nullptr != state_.get();
|
||||
}
|
||||
|
||||
shared_future< R > share();
|
||||
|
||||
R get() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
if ( ! base_t::valid() ) {
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
ptr_t tmp;
|
||||
tmp.swap( state_);
|
||||
typename base_t::ptr_t tmp{};
|
||||
tmp.swap( base_t::state_);
|
||||
return std::move( tmp->get() );
|
||||
}
|
||||
|
||||
std::exception_ptr get_exception_ptr() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->get_exception_ptr();
|
||||
}
|
||||
|
||||
void wait() const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
state_->wait();
|
||||
}
|
||||
using base_t::valid;
|
||||
using base_t::get_exception_ptr;
|
||||
using base_t::wait;
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_for( timeout_duration);
|
||||
return base_t::wait_for( timeout_duration);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_until( timeout_time);
|
||||
return base_t::wait_until( timeout_time);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename R >
|
||||
class future< R & > {
|
||||
class future< R & > : private detail::future_base< R & > {
|
||||
private:
|
||||
typedef typename detail::shared_state< R & >::ptr_t ptr_t;
|
||||
typedef detail::future_base< R & > base_t;
|
||||
|
||||
friend class shared_future< R & >;
|
||||
|
||||
ptr_t state_;
|
||||
|
||||
public:
|
||||
future() noexcept :
|
||||
state_() {
|
||||
}
|
||||
constexpr future() noexcept = default;
|
||||
|
||||
explicit future( ptr_t const& p) noexcept :
|
||||
state_( p) {
|
||||
}
|
||||
|
||||
~future() noexcept {
|
||||
explicit future( typename base_t::ptr_t const& p) noexcept :
|
||||
base_t{ p } {
|
||||
}
|
||||
|
||||
future( future const&) = delete;
|
||||
future & operator=( future const&) = delete;
|
||||
|
||||
future( future< R & > && other) noexcept :
|
||||
state_( std::move( other.state_) ) {
|
||||
future( future && other) noexcept :
|
||||
base_t{ std::forward< future >( other) } {
|
||||
}
|
||||
|
||||
future & operator=( future< R & > && other) noexcept {
|
||||
if ( this != & other) {
|
||||
state_ = std::move( other.state_);
|
||||
}
|
||||
future & operator=( future && other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
base_t::operator=( std::forward< future >( other) );
|
||||
return * this;
|
||||
}
|
||||
|
||||
bool valid() const noexcept {
|
||||
return nullptr != state_.get();
|
||||
}
|
||||
|
||||
shared_future< R & > share();
|
||||
|
||||
R & get() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
if ( ! base_t::valid() ) {
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
ptr_t tmp;
|
||||
tmp.swap( state_);
|
||||
typename base_t::ptr_t tmp{};
|
||||
tmp.swap( base_t::state_);
|
||||
return tmp->get();
|
||||
}
|
||||
|
||||
std::exception_ptr get_exception_ptr() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->get_exception_ptr();
|
||||
}
|
||||
|
||||
void wait() const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
state_->wait();
|
||||
}
|
||||
using base_t::valid;
|
||||
using base_t::get_exception_ptr;
|
||||
using base_t::wait;
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_for( timeout_duration);
|
||||
return base_t::wait_for( timeout_duration);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_until( timeout_time);
|
||||
return base_t::wait_until( timeout_time);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class future< void > {
|
||||
class future< void > : private detail::future_base< void > {
|
||||
private:
|
||||
typedef detail::shared_state< void >::ptr_t ptr_t;
|
||||
typedef detail::future_base< void > base_t;
|
||||
|
||||
friend class shared_future< void >;
|
||||
|
||||
ptr_t state_;
|
||||
|
||||
public:
|
||||
future() noexcept :
|
||||
state_() {
|
||||
}
|
||||
constexpr future() noexcept = default;
|
||||
|
||||
explicit future( ptr_t const& p) noexcept :
|
||||
state_( p) {
|
||||
}
|
||||
|
||||
~future() noexcept {
|
||||
explicit future( base_t::ptr_t const& p) noexcept :
|
||||
base_t{ p } {
|
||||
}
|
||||
|
||||
future( future const&) = delete;
|
||||
future & operator=( future const&) = delete;
|
||||
|
||||
inline
|
||||
future( future< void > && other) noexcept :
|
||||
state_( std::move( other.state_) ) {
|
||||
future( future && other) noexcept :
|
||||
base_t{ std::forward< future >( other) } {
|
||||
}
|
||||
|
||||
inline
|
||||
future & operator=( future< void > && other) noexcept {
|
||||
if ( this != & other) {
|
||||
state_ = std::move( other.state_);
|
||||
}
|
||||
future & operator=( future && other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
base_t::operator=( std::forward< future >( other) );
|
||||
return * this;
|
||||
}
|
||||
|
||||
inline
|
||||
bool valid() const noexcept {
|
||||
return nullptr != state_.get();
|
||||
}
|
||||
|
||||
shared_future< void > share();
|
||||
|
||||
inline
|
||||
void get() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
if ( ! base_t::valid() ) {
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
ptr_t tmp;
|
||||
tmp.swap( state_);
|
||||
base_t::ptr_t tmp{};
|
||||
tmp.swap( base_t::state_);
|
||||
tmp->get();
|
||||
}
|
||||
|
||||
inline
|
||||
std::exception_ptr get_exception_ptr() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->get_exception_ptr();
|
||||
}
|
||||
|
||||
inline
|
||||
void wait() const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
state_->wait();
|
||||
}
|
||||
using base_t::valid;
|
||||
using base_t::get_exception_ptr;
|
||||
using base_t::wait;
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_for( timeout_duration);
|
||||
return base_t::wait_for( timeout_duration);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_until( timeout_time);
|
||||
return base_t::wait_until( timeout_time);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< typename R >
|
||||
class shared_future {
|
||||
class shared_future : private detail::future_base< R > {
|
||||
private:
|
||||
typedef typename detail::shared_state< R >::ptr_t ptr_t;
|
||||
typedef detail::future_base< R > base_t;
|
||||
|
||||
friend class future< R >;
|
||||
|
||||
ptr_t state_;
|
||||
|
||||
explicit shared_future( ptr_t const& p) noexcept :
|
||||
state_( p) {
|
||||
explicit shared_future( typename base_t::ptr_t const& p) noexcept :
|
||||
base_t{ p } {
|
||||
}
|
||||
|
||||
public:
|
||||
shared_future() noexcept :
|
||||
state_() {
|
||||
}
|
||||
constexpr shared_future() noexcept = default;
|
||||
|
||||
~shared_future() noexcept {
|
||||
}
|
||||
~shared_future() noexcept = default;
|
||||
|
||||
shared_future( shared_future const& other) :
|
||||
state_( other.state_) {
|
||||
base_t{ other } {
|
||||
}
|
||||
|
||||
shared_future( shared_future && other) noexcept :
|
||||
state_( std::move( other.state_) ) {
|
||||
base_t{ std::forward< shared_future >( other) } {
|
||||
}
|
||||
|
||||
shared_future( future< R > && other) noexcept :
|
||||
state_( std::move( other.state_) ) {
|
||||
base_t{ std::forward< future< R > >( other) } {
|
||||
}
|
||||
|
||||
shared_future & operator=( shared_future const& other) noexcept {
|
||||
if ( this != & other) {
|
||||
state_ = other.state_;
|
||||
}
|
||||
if ( this == & other) return * this;
|
||||
base_t::operator=( other);
|
||||
return * this;
|
||||
}
|
||||
|
||||
shared_future & operator=( shared_future && other) noexcept {
|
||||
if ( this != & other) {
|
||||
state_= std::move( other.state_);
|
||||
}
|
||||
if ( this == & other) return * this;
|
||||
base_t::operator=( std::forward< shared_future >( other) );
|
||||
return * this;
|
||||
}
|
||||
|
||||
shared_future & operator=( future< R > && other) noexcept {
|
||||
state_ = std::move( other.state_);
|
||||
base_t::operator=( std::forward< future< R > >( other) );
|
||||
return * this;
|
||||
}
|
||||
|
||||
bool valid() const noexcept {
|
||||
return nullptr != state_.get();
|
||||
}
|
||||
|
||||
R const& get() const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
return state_->get();
|
||||
return base_t::state_->get();
|
||||
}
|
||||
|
||||
std::exception_ptr get_exception_ptr() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->get_exception_ptr();
|
||||
}
|
||||
|
||||
void wait() const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
state_->wait();
|
||||
}
|
||||
using base_t::valid;
|
||||
using base_t::get_exception_ptr;
|
||||
using base_t::wait;
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_for( timeout_duration);
|
||||
return base_t::wait_for( timeout_duration);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_until( timeout_time);
|
||||
return base_t::wait_until( timeout_time);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename R >
|
||||
class shared_future< R & > {
|
||||
class shared_future< R & > : private detail::future_base< R & > {
|
||||
private:
|
||||
typedef typename detail::shared_state< R & >::ptr_t ptr_t;
|
||||
typedef detail::future_base< R & > base_t;
|
||||
|
||||
friend class future< R & >;
|
||||
|
||||
ptr_t state_;
|
||||
|
||||
explicit shared_future( ptr_t const& p) noexcept :
|
||||
state_( p) {
|
||||
explicit shared_future( typename base_t::ptr_t const& p) noexcept :
|
||||
base_t{ p } {
|
||||
}
|
||||
|
||||
public:
|
||||
shared_future() noexcept :
|
||||
state_() {
|
||||
}
|
||||
constexpr shared_future() noexcept = default;
|
||||
|
||||
~shared_future() noexcept {
|
||||
}
|
||||
~shared_future() noexcept = default;
|
||||
|
||||
shared_future( shared_future const& other) :
|
||||
state_( other.state_) {
|
||||
base_t{ other } {
|
||||
}
|
||||
|
||||
shared_future( shared_future && other) noexcept :
|
||||
state_( std::move( other.state_) ) {
|
||||
base_t{ std::forward< shared_future >( other) } {
|
||||
}
|
||||
|
||||
shared_future( future< R & > && other) noexcept :
|
||||
state_( std::move( other.state_) ) {
|
||||
base_t{ std::forward< future< R & > >( other) } {
|
||||
}
|
||||
|
||||
shared_future & operator=( shared_future const& other) noexcept {
|
||||
if ( this != & other) {
|
||||
state_ = other.state_;
|
||||
}
|
||||
if ( this == & other) return * this;
|
||||
base_t::operator=( other);
|
||||
return * this;
|
||||
}
|
||||
|
||||
shared_future & operator=( shared_future && other) noexcept {
|
||||
if ( this != & other) {
|
||||
state_ = std::move( other.state_);
|
||||
}
|
||||
if ( this == & other) return * this;
|
||||
base_t::operator=( std::forward< shared_future >( other) );
|
||||
return * this;
|
||||
}
|
||||
|
||||
shared_future & operator=( future< R & > && other) noexcept {
|
||||
state_ = std::move( other.state_);
|
||||
base_t::operator=( std::forward< future< R & > >( other) );
|
||||
return * this;
|
||||
}
|
||||
|
||||
bool valid() const noexcept {
|
||||
return nullptr != state_.get();
|
||||
}
|
||||
|
||||
R & get() const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
return state_->get();
|
||||
return base_t::state_->get();
|
||||
}
|
||||
|
||||
std::exception_ptr get_exception_ptr() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->get_exception_ptr();
|
||||
}
|
||||
|
||||
void wait() const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
state_->wait();
|
||||
}
|
||||
using base_t::valid;
|
||||
using base_t::get_exception_ptr;
|
||||
using base_t::wait;
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_for( timeout_duration);
|
||||
return base_t::wait_for( timeout_duration);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_until( timeout_time);
|
||||
return base_t::wait_until( timeout_time);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class shared_future< void > {
|
||||
class shared_future< void > : private detail::future_base< void > {
|
||||
private:
|
||||
typedef detail::shared_state< void >::ptr_t ptr_t;
|
||||
typedef detail::future_base< void > base_t;
|
||||
|
||||
friend class future< void >;
|
||||
|
||||
ptr_t state_;
|
||||
|
||||
shared_future( ptr_t const& p) noexcept :
|
||||
state_( p) {
|
||||
explicit shared_future( base_t::ptr_t const& p) noexcept :
|
||||
base_t{ p } {
|
||||
}
|
||||
|
||||
public:
|
||||
shared_future() noexcept :
|
||||
state_() {
|
||||
}
|
||||
constexpr shared_future() noexcept = default;
|
||||
|
||||
~shared_future() noexcept {
|
||||
}
|
||||
~shared_future() noexcept = default;
|
||||
|
||||
inline
|
||||
shared_future( shared_future const& other) :
|
||||
state_( other.state_) {
|
||||
base_t{ other } {
|
||||
}
|
||||
|
||||
inline
|
||||
shared_future( shared_future && other) noexcept :
|
||||
state_( std::move( other.state_) ) {
|
||||
base_t{ std::forward< shared_future >( other) } {
|
||||
}
|
||||
|
||||
inline
|
||||
shared_future( future< void > && other) noexcept :
|
||||
state_( std::move( other.state_) ) {
|
||||
base_t{ std::forward< future< void > >( other) } {
|
||||
}
|
||||
|
||||
inline
|
||||
shared_future & operator=( shared_future const& other) noexcept
|
||||
{
|
||||
if ( this != & other) {
|
||||
state_ = other.state_;
|
||||
}
|
||||
shared_future & operator=( shared_future const& other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
base_t::operator=( other);
|
||||
return * this;
|
||||
}
|
||||
|
||||
inline
|
||||
shared_future & operator=( shared_future && other) noexcept {
|
||||
if ( this != & other) {
|
||||
state_ = std::move( other.state_);
|
||||
}
|
||||
if ( this == & other) return * this;
|
||||
base_t::operator=( std::forward< shared_future >( other) );
|
||||
return * this;
|
||||
}
|
||||
|
||||
inline
|
||||
shared_future & operator=( future< void > && other) noexcept {
|
||||
state_ = std::move( other.state_);
|
||||
base_t::operator=( std::forward< future< void > >( other) );
|
||||
return * this;
|
||||
}
|
||||
|
||||
inline
|
||||
bool valid() const noexcept {
|
||||
return nullptr != state_.get();
|
||||
}
|
||||
|
||||
inline
|
||||
void get() const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
state_->get();
|
||||
base_t::state_->get();
|
||||
}
|
||||
|
||||
inline
|
||||
std::exception_ptr get_exception_ptr() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->get_exception_ptr();
|
||||
}
|
||||
|
||||
inline
|
||||
void wait() const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
state_->wait();
|
||||
}
|
||||
using base_t::valid;
|
||||
using base_t::get_exception_ptr;
|
||||
using base_t::wait;
|
||||
|
||||
template< class Rep, class Period >
|
||||
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_for( timeout_duration);
|
||||
return base_t::wait_for( timeout_duration);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return state_->wait_until( timeout_time);
|
||||
return base_t::wait_until( timeout_time);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -577,28 +467,28 @@ public:
|
||||
template< typename R >
|
||||
shared_future< R >
|
||||
future< R >::share() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
if ( ! base_t::valid() ) {
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
return shared_future< R >( std::move( * this) );
|
||||
return shared_future< R >{ std::move( * this) };
|
||||
}
|
||||
|
||||
template< typename R >
|
||||
shared_future< R & >
|
||||
future< R & >::share() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
if ( ! base_t::valid() ) {
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
return shared_future< R & >( std::move( * this) );
|
||||
return shared_future< R & >{ std::move( * this) };
|
||||
}
|
||||
|
||||
inline
|
||||
shared_future< void >
|
||||
future< void >::share() {
|
||||
if ( ! valid() ) {
|
||||
throw future_uninitialized();
|
||||
if ( ! base_t::valid() ) {
|
||||
throw future_uninitialized{};
|
||||
}
|
||||
return shared_future< void >( std::move( * this) );
|
||||
return shared_future< void >{ std::move( * this) };
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -29,25 +29,20 @@ class packaged_task< R( Args ... ) > {
|
||||
private:
|
||||
typedef typename detail::task_base< R, Args ... >::ptr_t ptr_t;
|
||||
|
||||
bool obtained_;
|
||||
ptr_t task_;
|
||||
bool obtained_{ false };
|
||||
ptr_t task_{};
|
||||
|
||||
public:
|
||||
packaged_task() noexcept :
|
||||
obtained_( false),
|
||||
task_() {
|
||||
}
|
||||
constexpr packaged_task() noexcept = default;
|
||||
|
||||
~packaged_task() {
|
||||
~packaged_task() noexcept {
|
||||
if ( task_) {
|
||||
task_->owner_destroyed();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
explicit packaged_task( Fn && fn) :
|
||||
obtained_( false),
|
||||
task_() {
|
||||
explicit packaged_task( Fn && fn) {
|
||||
typedef detail::task_object<
|
||||
Fn,
|
||||
std::allocator< packaged_task< R() > >,
|
||||
@@ -55,42 +50,38 @@ public:
|
||||
Args ...
|
||||
> object_t;
|
||||
std::allocator< packaged_task< R() > > alloc;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
task_ = ptr_t(
|
||||
typename object_t::allocator_t a{ alloc };
|
||||
task_ = ptr_t{
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( a, std::forward< Fn >( fn) ) );
|
||||
::new( a.allocate( 1) ) object_t{ a, std::forward< Fn >( fn) } };
|
||||
}
|
||||
|
||||
template< typename Fn, typename Allocator >
|
||||
explicit packaged_task( std::allocator_arg_t, Allocator const& alloc, Fn && fn) :
|
||||
obtained_( false),
|
||||
task_() {
|
||||
explicit packaged_task( std::allocator_arg_t, Allocator const& alloc, Fn && fn) {
|
||||
typedef detail::task_object<
|
||||
Fn,
|
||||
Allocator,
|
||||
R
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
task_ = ptr_t(
|
||||
typename object_t::allocator_t a{ alloc };
|
||||
task_ = ptr_t{
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( a, std::forward< Fn >( fn) ) );
|
||||
::new( a.allocate( 1) ) object_t{ a, std::forward< Fn >( fn) } };
|
||||
}
|
||||
|
||||
packaged_task( packaged_task const&) = delete;
|
||||
packaged_task & operator=( packaged_task const&) = delete;
|
||||
|
||||
packaged_task( packaged_task && other) noexcept :
|
||||
obtained_( other.obtained_),
|
||||
task_( std::move( other.task_) ) {
|
||||
obtained_{ other.obtained_ },
|
||||
task_{ std::move( other.task_) } {
|
||||
other.obtained_ = false;
|
||||
}
|
||||
|
||||
packaged_task & operator=( packaged_task && other) noexcept {
|
||||
if ( this != & other) {
|
||||
obtained_ = other.obtained_;
|
||||
other.obtained_ = false;
|
||||
task_ = std::move( other.task_);
|
||||
}
|
||||
if ( this == & other) return * this;
|
||||
packaged_task tmp{ std::move( other) };
|
||||
swap( tmp);
|
||||
return * this;
|
||||
}
|
||||
|
||||
@@ -105,26 +96,26 @@ public:
|
||||
|
||||
future< R > get_future() {
|
||||
if ( obtained_) {
|
||||
throw future_already_retrieved();
|
||||
throw future_already_retrieved{};
|
||||
}
|
||||
if ( ! valid() ) {
|
||||
throw packaged_task_uninitialized();
|
||||
throw packaged_task_uninitialized{};
|
||||
}
|
||||
obtained_ = true;
|
||||
return future< R >(
|
||||
boost::static_pointer_cast< detail::shared_state< R > >( task_) );
|
||||
return future< R >{
|
||||
boost::static_pointer_cast< detail::shared_state< R > >( task_) };
|
||||
}
|
||||
|
||||
void operator()( Args && ... args) {
|
||||
if ( ! valid() ) {
|
||||
throw packaged_task_uninitialized();
|
||||
throw packaged_task_uninitialized{};
|
||||
}
|
||||
task_->run( std::forward< Args >( args) ... );
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if ( ! valid() ) {
|
||||
throw packaged_task_uninitialized();
|
||||
throw packaged_task_uninitialized{};
|
||||
}
|
||||
obtained_ = false;
|
||||
task_->reset();
|
||||
|
||||
@@ -26,35 +26,31 @@ class promise {
|
||||
private:
|
||||
typedef typename detail::shared_state< R >::ptr_t ptr_t;
|
||||
|
||||
bool obtained_;
|
||||
ptr_t future_;
|
||||
bool obtained_{ false };
|
||||
ptr_t future_{};
|
||||
|
||||
public:
|
||||
promise() :
|
||||
obtained_( false),
|
||||
future_() {
|
||||
promise() {
|
||||
typedef detail::shared_state_object<
|
||||
R, std::allocator< promise< R > >
|
||||
> object_t;
|
||||
std::allocator< promise< R > > alloc;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
future_ = ptr_t(
|
||||
typename object_t::allocator_t a{ alloc };
|
||||
future_ = ptr_t{
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( a) );
|
||||
::new( a.allocate( 1) ) object_t{ a } };
|
||||
}
|
||||
|
||||
template< typename Allocator >
|
||||
promise( std::allocator_arg_t, Allocator alloc) :
|
||||
obtained_( false),
|
||||
future_() {
|
||||
promise( std::allocator_arg_t, Allocator alloc) {
|
||||
typedef detail::shared_state_object< R, Allocator > object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
future_ = ptr_t(
|
||||
typename object_t::allocator_t a{ alloc };
|
||||
future_ = ptr_t{
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( a) );
|
||||
::new( a.allocate( 1) ) object_t{ a } };
|
||||
}
|
||||
|
||||
~promise() {
|
||||
~promise() noexcept {
|
||||
if ( future_) {
|
||||
future_->owner_destroyed();
|
||||
}
|
||||
@@ -64,17 +60,15 @@ public:
|
||||
promise & operator=( promise const&) = delete;
|
||||
|
||||
promise( promise && other) noexcept :
|
||||
obtained_( other.obtained_),
|
||||
future_( std::move( other.future_) ) {
|
||||
obtained_{ other.obtained_ },
|
||||
future_{ std::move( other.future_) } {
|
||||
other.obtained_ = false;
|
||||
}
|
||||
|
||||
promise & operator=( promise && other) noexcept {
|
||||
if ( this != & other) {
|
||||
obtained_ = other.obtained_;
|
||||
other.obtained_ = false;
|
||||
future_ = std::move( other.future_);
|
||||
}
|
||||
if ( this == & other) return * this;
|
||||
promise tmp{ std::move( other) };
|
||||
swap( tmp);
|
||||
return * this;
|
||||
}
|
||||
|
||||
@@ -85,32 +79,32 @@ public:
|
||||
|
||||
future< R > get_future() {
|
||||
if ( obtained_) {
|
||||
throw future_already_retrieved();
|
||||
throw future_already_retrieved{};
|
||||
}
|
||||
if ( ! future_) {
|
||||
throw promise_uninitialized();
|
||||
throw promise_uninitialized{};
|
||||
}
|
||||
obtained_ = true;
|
||||
return future< R >( future_);
|
||||
return future< R >{ future_ };
|
||||
}
|
||||
|
||||
void set_value( R const& value) {
|
||||
if ( ! future_) {
|
||||
throw promise_uninitialized();
|
||||
throw promise_uninitialized{};
|
||||
}
|
||||
future_->set_value( value);
|
||||
}
|
||||
|
||||
void set_value( R && value) {
|
||||
if ( ! future_) {
|
||||
throw promise_uninitialized();
|
||||
throw promise_uninitialized{};
|
||||
}
|
||||
future_->set_value( std::move( value) );
|
||||
}
|
||||
|
||||
void set_exception( std::exception_ptr p) {
|
||||
if ( ! future_) {
|
||||
throw promise_uninitialized();
|
||||
throw promise_uninitialized{};
|
||||
}
|
||||
future_->set_exception( p);
|
||||
}
|
||||
@@ -121,35 +115,31 @@ class promise< R & > {
|
||||
private:
|
||||
typedef typename detail::shared_state< R & >::ptr_t ptr_t;
|
||||
|
||||
bool obtained_;
|
||||
ptr_t future_;
|
||||
bool obtained_{ false };
|
||||
ptr_t future_{};
|
||||
|
||||
public:
|
||||
promise() :
|
||||
obtained_( false),
|
||||
future_() {
|
||||
promise() {
|
||||
typedef detail::shared_state_object<
|
||||
R &, std::allocator< promise< R & > >
|
||||
> object_t;
|
||||
std::allocator< promise< R > > alloc;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
future_ = ptr_t(
|
||||
std::allocator< promise< R > > alloc{};
|
||||
typename object_t::allocator_t a{ alloc };
|
||||
future_ = ptr_t{
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( a) );
|
||||
::new( a.allocate( 1) ) object_t{ a } };
|
||||
}
|
||||
|
||||
template< typename Allocator >
|
||||
promise( std::allocator_arg_t, Allocator alloc) :
|
||||
obtained_( false),
|
||||
future_() {
|
||||
promise( std::allocator_arg_t, Allocator alloc) {
|
||||
typedef detail::shared_state_object< R &, Allocator > object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
future_ = ptr_t(
|
||||
typename object_t::allocator_t a{ alloc };
|
||||
future_ = ptr_t{
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( a) );
|
||||
::new( a.allocate( 1) ) object_t{ a } };
|
||||
}
|
||||
|
||||
~promise() {
|
||||
~promise() noexcept {
|
||||
if ( future_) {
|
||||
future_->owner_destroyed();
|
||||
}
|
||||
@@ -159,17 +149,15 @@ public:
|
||||
promise & operator=( promise const&) = delete;
|
||||
|
||||
promise( promise && other) noexcept :
|
||||
obtained_( other.obtained_),
|
||||
future_( std::move( other.future_) ) {
|
||||
obtained_{ other.obtained_ },
|
||||
future_{ std::move( other.future_) } {
|
||||
other.obtained_ = false;
|
||||
}
|
||||
|
||||
promise & operator=( promise && other) noexcept {
|
||||
if ( this != & other) {
|
||||
obtained_ = other.obtained_;
|
||||
other.obtained_ = false;
|
||||
future_ = std::move( other.future_);
|
||||
}
|
||||
if ( this == & other) return * this;
|
||||
promise tmp{ std::move( other) };
|
||||
swap( tmp);
|
||||
return * this;
|
||||
}
|
||||
|
||||
@@ -180,25 +168,25 @@ public:
|
||||
|
||||
future< R & > get_future() {
|
||||
if ( obtained_) {
|
||||
throw future_already_retrieved();
|
||||
throw future_already_retrieved{};
|
||||
}
|
||||
if ( ! future_) {
|
||||
throw promise_uninitialized();
|
||||
throw promise_uninitialized{};
|
||||
}
|
||||
obtained_ = true;
|
||||
return future< R & >( future_);
|
||||
return future< R & >{ future_ };
|
||||
}
|
||||
|
||||
void set_value( R & value) {
|
||||
if ( ! future_) {
|
||||
throw promise_uninitialized();
|
||||
throw promise_uninitialized{};
|
||||
}
|
||||
future_->set_value( value);
|
||||
}
|
||||
|
||||
void set_exception( std::exception_ptr p) {
|
||||
if ( ! future_) {
|
||||
throw promise_uninitialized();
|
||||
throw promise_uninitialized{};
|
||||
}
|
||||
future_->set_exception( p);
|
||||
}
|
||||
@@ -209,35 +197,31 @@ class promise< void > {
|
||||
private:
|
||||
typedef detail::shared_state< void >::ptr_t ptr_t;
|
||||
|
||||
bool obtained_;
|
||||
ptr_t future_;
|
||||
bool obtained_{ false };
|
||||
ptr_t future_{};
|
||||
|
||||
public:
|
||||
promise() :
|
||||
obtained_( false),
|
||||
future_() {
|
||||
promise() {
|
||||
typedef detail::shared_state_object<
|
||||
void, std::allocator< promise< void > >
|
||||
> object_t;
|
||||
std::allocator< promise< void > > alloc;
|
||||
object_t::allocator_t a( alloc);
|
||||
future_ = ptr_t(
|
||||
std::allocator< promise< void > > alloc{};
|
||||
object_t::allocator_t a{ alloc };
|
||||
future_ = ptr_t{
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( a) );
|
||||
::new( a.allocate( 1) ) object_t{ a } };
|
||||
}
|
||||
|
||||
template< typename Allocator >
|
||||
promise( std::allocator_arg_t, Allocator alloc) :
|
||||
obtained_( false),
|
||||
future_() {
|
||||
promise( std::allocator_arg_t, Allocator alloc) {
|
||||
typedef detail::shared_state_object< void, Allocator > object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
future_ = ptr_t(
|
||||
future_ = ptr_t{
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( a) );
|
||||
::new( a.allocate( 1) ) object_t{ a } };
|
||||
}
|
||||
|
||||
~promise() {
|
||||
~promise() noexcept {
|
||||
if ( future_) {
|
||||
future_->owner_destroyed();
|
||||
}
|
||||
@@ -248,18 +232,16 @@ public:
|
||||
|
||||
inline
|
||||
promise( promise && other) noexcept :
|
||||
obtained_( other.obtained_),
|
||||
future_( std::move( other.future_) ) {
|
||||
obtained_{ other.obtained_ },
|
||||
future_{ std::move( other.future_) } {
|
||||
other.obtained_ = false;
|
||||
}
|
||||
|
||||
inline
|
||||
promise & operator=( promise && other) noexcept {
|
||||
if ( this != & other) {
|
||||
obtained_ = other.obtained_;
|
||||
other.obtained_ = false;
|
||||
future_ = std::move( other.future_);
|
||||
}
|
||||
if ( this == & other) return * this;
|
||||
promise tmp{ std::move( other) };
|
||||
swap( tmp);
|
||||
return * this;
|
||||
}
|
||||
|
||||
@@ -272,19 +254,19 @@ public:
|
||||
inline
|
||||
future< void > get_future() {
|
||||
if ( obtained_) {
|
||||
throw future_already_retrieved();
|
||||
throw future_already_retrieved{};
|
||||
}
|
||||
if ( ! future_) {
|
||||
throw promise_uninitialized();
|
||||
throw promise_uninitialized{};
|
||||
}
|
||||
obtained_ = true;
|
||||
return future< void >( future_);
|
||||
return future< void >{ future_ };
|
||||
}
|
||||
|
||||
inline
|
||||
void set_value() {
|
||||
if ( ! future_) {
|
||||
throw promise_uninitialized();
|
||||
throw promise_uninitialized{};
|
||||
}
|
||||
future_->set_value();
|
||||
}
|
||||
@@ -292,7 +274,7 @@ public:
|
||||
inline
|
||||
void set_exception( std::exception_ptr p) {
|
||||
if ( ! future_) {
|
||||
throw promise_uninitialized();
|
||||
throw promise_uninitialized{};
|
||||
}
|
||||
future_->set_exception( p);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ static auto make_dispatcher_context( scheduler * sched) {
|
||||
thread_local static std::size_t counter;
|
||||
|
||||
// schwarz counter
|
||||
context_initializer::context_initializer() noexcept {
|
||||
context_initializer::context_initializer() {
|
||||
if ( 0 == counter++) {
|
||||
# if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
||||
// allocate memory for main context and scheduler
|
||||
|
||||
Reference in New Issue
Block a user