You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
937 lines
24 KiB
937 lines
24 KiB
// |
|
// impl/use_future.hpp |
|
// ~~~~~~~~~~~~~~~~~~~ |
|
// |
|
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
|
// |
|
// 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 ASIO_IMPL_USE_FUTURE_HPP |
|
#define ASIO_IMPL_USE_FUTURE_HPP |
|
|
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200) |
|
# pragma once |
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
|
|
|
#include "asio/detail/config.hpp" |
|
#include <tuple> |
|
#include "asio/async_result.hpp" |
|
#include "asio/detail/memory.hpp" |
|
#include "asio/error_code.hpp" |
|
#include "asio/packaged_task.hpp" |
|
#include "asio/system_error.hpp" |
|
#include "asio/system_executor.hpp" |
|
|
|
#include "asio/detail/push_options.hpp" |
|
|
|
namespace asio { |
|
namespace detail { |
|
|
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
template <typename T, typename F, typename... Args> |
|
inline void promise_invoke_and_set(std::promise<T>& p, |
|
F& f, ASIO_MOVE_ARG(Args)... args) |
|
{ |
|
#if !defined(ASIO_NO_EXCEPTIONS) |
|
try |
|
#endif // !defined(ASIO_NO_EXCEPTIONS) |
|
{ |
|
p.set_value(f(ASIO_MOVE_CAST(Args)(args)...)); |
|
} |
|
#if !defined(ASIO_NO_EXCEPTIONS) |
|
catch (...) |
|
{ |
|
p.set_exception(std::current_exception()); |
|
} |
|
#endif // !defined(ASIO_NO_EXCEPTIONS) |
|
} |
|
|
|
template <typename F, typename... Args> |
|
inline void promise_invoke_and_set(std::promise<void>& p, |
|
F& f, ASIO_MOVE_ARG(Args)... args) |
|
{ |
|
#if !defined(ASIO_NO_EXCEPTIONS) |
|
try |
|
#endif // !defined(ASIO_NO_EXCEPTIONS) |
|
{ |
|
f(ASIO_MOVE_CAST(Args)(args)...); |
|
p.set_value(); |
|
} |
|
#if !defined(ASIO_NO_EXCEPTIONS) |
|
catch (...) |
|
{ |
|
p.set_exception(std::current_exception()); |
|
} |
|
#endif // !defined(ASIO_NO_EXCEPTIONS) |
|
} |
|
|
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
template <typename T, typename F> |
|
inline void promise_invoke_and_set(std::promise<T>& p, F& f) |
|
{ |
|
#if !defined(ASIO_NO_EXCEPTIONS) |
|
try |
|
#endif // !defined(ASIO_NO_EXCEPTIONS) |
|
{ |
|
p.set_value(f()); |
|
} |
|
#if !defined(ASIO_NO_EXCEPTIONS) |
|
catch (...) |
|
{ |
|
p.set_exception(std::current_exception()); |
|
} |
|
#endif // !defined(ASIO_NO_EXCEPTIONS) |
|
} |
|
|
|
template <typename F, typename Args> |
|
inline void promise_invoke_and_set(std::promise<void>& p, F& f) |
|
{ |
|
#if !defined(ASIO_NO_EXCEPTIONS) |
|
try |
|
#endif // !defined(ASIO_NO_EXCEPTIONS) |
|
{ |
|
f(); |
|
p.set_value(); |
|
#if !defined(ASIO_NO_EXCEPTIONS) |
|
} |
|
catch (...) |
|
{ |
|
p.set_exception(std::current_exception()); |
|
} |
|
#endif // !defined(ASIO_NO_EXCEPTIONS) |
|
} |
|
|
|
#if defined(ASIO_NO_EXCEPTIONS) |
|
|
|
#define ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \ |
|
template <typename T, typename F, ASIO_VARIADIC_TPARAMS(n)> \ |
|
inline void promise_invoke_and_set(std::promise<T>& p, \ |
|
F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ |
|
{ \ |
|
p.set_value(f(ASIO_VARIADIC_MOVE_ARGS(n))); \ |
|
} \ |
|
\ |
|
template <typename F, ASIO_VARIADIC_TPARAMS(n)> \ |
|
inline void promise_invoke_and_set(std::promise<void>& p, \ |
|
F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ |
|
{ \ |
|
f(ASIO_VARIADIC_MOVE_ARGS(n)); \ |
|
p.set_value(); \ |
|
} \ |
|
/**/ |
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_INVOKE_DEF) |
|
#undef ASIO_PRIVATE_PROMISE_INVOKE_DEF |
|
|
|
#else // defined(ASIO_NO_EXCEPTIONS) |
|
|
|
#define ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \ |
|
template <typename T, typename F, ASIO_VARIADIC_TPARAMS(n)> \ |
|
inline void promise_invoke_and_set(std::promise<T>& p, \ |
|
F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ |
|
{ \ |
|
try \ |
|
{ \ |
|
p.set_value(f(ASIO_VARIADIC_MOVE_ARGS(n))); \ |
|
} \ |
|
catch (...) \ |
|
{ \ |
|
p.set_exception(std::current_exception()); \ |
|
} \ |
|
} \ |
|
\ |
|
template <typename F, ASIO_VARIADIC_TPARAMS(n)> \ |
|
inline void promise_invoke_and_set(std::promise<void>& p, \ |
|
F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ |
|
{ \ |
|
try \ |
|
{ \ |
|
f(ASIO_VARIADIC_MOVE_ARGS(n)); \ |
|
p.set_value(); \ |
|
} \ |
|
catch (...) \ |
|
{ \ |
|
p.set_exception(std::current_exception()); \ |
|
} \ |
|
} \ |
|
/**/ |
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_INVOKE_DEF) |
|
#undef ASIO_PRIVATE_PROMISE_INVOKE_DEF |
|
|
|
#endif // defined(ASIO_NO_EXCEPTIONS) |
|
|
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
// A function object adapter to invoke a nullary function object and capture |
|
// any exception thrown into a promise. |
|
template <typename T, typename F> |
|
class promise_invoker |
|
{ |
|
public: |
|
promise_invoker(const shared_ptr<std::promise<T> >& p, |
|
ASIO_MOVE_ARG(F) f) |
|
: p_(p), f_(ASIO_MOVE_CAST(F)(f)) |
|
{ |
|
} |
|
|
|
void operator()() |
|
{ |
|
#if !defined(ASIO_NO_EXCEPTIONS) |
|
try |
|
#endif // !defined(ASIO_NO_EXCEPTIONS) |
|
{ |
|
f_(); |
|
} |
|
#if !defined(ASIO_NO_EXCEPTIONS) |
|
catch (...) |
|
{ |
|
p_->set_exception(std::current_exception()); |
|
} |
|
#endif // !defined(ASIO_NO_EXCEPTIONS) |
|
} |
|
|
|
private: |
|
shared_ptr<std::promise<T> > p_; |
|
typename decay<F>::type f_; |
|
}; |
|
|
|
// An executor that adapts the system_executor to capture any exeption thrown |
|
// by a submitted function object and save it into a promise. |
|
template <typename T> |
|
class promise_executor |
|
{ |
|
public: |
|
explicit promise_executor(const shared_ptr<std::promise<T> >& p) |
|
: p_(p) |
|
{ |
|
} |
|
|
|
execution_context& context() const ASIO_NOEXCEPT |
|
{ |
|
return system_executor().context(); |
|
} |
|
|
|
void on_work_started() const ASIO_NOEXCEPT {} |
|
void on_work_finished() const ASIO_NOEXCEPT {} |
|
|
|
template <typename F, typename A> |
|
void dispatch(ASIO_MOVE_ARG(F) f, const A&) const |
|
{ |
|
promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f))(); |
|
} |
|
|
|
template <typename F, typename A> |
|
void post(ASIO_MOVE_ARG(F) f, const A& a) const |
|
{ |
|
system_executor().post( |
|
promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)), a); |
|
} |
|
|
|
template <typename F, typename A> |
|
void defer(ASIO_MOVE_ARG(F) f, const A& a) const |
|
{ |
|
system_executor().defer( |
|
promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)), a); |
|
} |
|
|
|
friend bool operator==(const promise_executor& a, |
|
const promise_executor& b) ASIO_NOEXCEPT |
|
{ |
|
return a.p_ == b.p_; |
|
} |
|
|
|
friend bool operator!=(const promise_executor& a, |
|
const promise_executor& b) ASIO_NOEXCEPT |
|
{ |
|
return a.p_ != b.p_; |
|
} |
|
|
|
private: |
|
shared_ptr<std::promise<T> > p_; |
|
}; |
|
|
|
// The base class for all completion handlers that create promises. |
|
template <typename T> |
|
class promise_creator |
|
{ |
|
public: |
|
typedef promise_executor<T> executor_type; |
|
|
|
executor_type get_executor() const ASIO_NOEXCEPT |
|
{ |
|
return executor_type(p_); |
|
} |
|
|
|
typedef std::future<T> future_type; |
|
|
|
future_type get_future() |
|
{ |
|
return p_->get_future(); |
|
} |
|
|
|
protected: |
|
template <typename Allocator> |
|
void create_promise(const Allocator& a) |
|
{ |
|
ASIO_REBIND_ALLOC(Allocator, char) b(a); |
|
p_ = std::allocate_shared<std::promise<T>>(b, std::allocator_arg, b); |
|
} |
|
|
|
shared_ptr<std::promise<T> > p_; |
|
}; |
|
|
|
// For completion signature void(). |
|
class promise_handler_0 |
|
: public promise_creator<void> |
|
{ |
|
public: |
|
void operator()() |
|
{ |
|
this->p_->set_value(); |
|
} |
|
}; |
|
|
|
// For completion signature void(error_code). |
|
class promise_handler_ec_0 |
|
: public promise_creator<void> |
|
{ |
|
public: |
|
void operator()(const asio::error_code& ec) |
|
{ |
|
if (ec) |
|
{ |
|
this->p_->set_exception( |
|
std::make_exception_ptr( |
|
asio::system_error(ec))); |
|
} |
|
else |
|
{ |
|
this->p_->set_value(); |
|
} |
|
} |
|
}; |
|
|
|
// For completion signature void(exception_ptr). |
|
class promise_handler_ex_0 |
|
: public promise_creator<void> |
|
{ |
|
public: |
|
void operator()(const std::exception_ptr& ex) |
|
{ |
|
if (ex) |
|
{ |
|
this->p_->set_exception(ex); |
|
} |
|
else |
|
{ |
|
this->p_->set_value(); |
|
} |
|
} |
|
}; |
|
|
|
// For completion signature void(T). |
|
template <typename T> |
|
class promise_handler_1 |
|
: public promise_creator<T> |
|
{ |
|
public: |
|
template <typename Arg> |
|
void operator()(ASIO_MOVE_ARG(Arg) arg) |
|
{ |
|
this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg)); |
|
} |
|
}; |
|
|
|
// For completion signature void(error_code, T). |
|
template <typename T> |
|
class promise_handler_ec_1 |
|
: public promise_creator<T> |
|
{ |
|
public: |
|
template <typename Arg> |
|
void operator()(const asio::error_code& ec, |
|
ASIO_MOVE_ARG(Arg) arg) |
|
{ |
|
if (ec) |
|
{ |
|
this->p_->set_exception( |
|
std::make_exception_ptr( |
|
asio::system_error(ec))); |
|
} |
|
else |
|
this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg)); |
|
} |
|
}; |
|
|
|
// For completion signature void(exception_ptr, T). |
|
template <typename T> |
|
class promise_handler_ex_1 |
|
: public promise_creator<T> |
|
{ |
|
public: |
|
template <typename Arg> |
|
void operator()(const std::exception_ptr& ex, |
|
ASIO_MOVE_ARG(Arg) arg) |
|
{ |
|
if (ex) |
|
this->p_->set_exception(ex); |
|
else |
|
this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg)); |
|
} |
|
}; |
|
|
|
// For completion signature void(T1, ..., Tn); |
|
template <typename T> |
|
class promise_handler_n |
|
: public promise_creator<T> |
|
{ |
|
public: |
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
template <typename... Args> |
|
void operator()(ASIO_MOVE_ARG(Args)... args) |
|
{ |
|
this->p_->set_value( |
|
std::forward_as_tuple( |
|
ASIO_MOVE_CAST(Args)(args)...)); |
|
} |
|
|
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
#define ASIO_PRIVATE_CALL_OP_DEF(n) \ |
|
template <ASIO_VARIADIC_TPARAMS(n)> \ |
|
void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \ |
|
{\ |
|
this->p_->set_value( \ |
|
std::forward_as_tuple( \ |
|
ASIO_VARIADIC_MOVE_ARGS(n))); \ |
|
} \ |
|
/**/ |
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) |
|
#undef ASIO_PRIVATE_CALL_OP_DEF |
|
|
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
}; |
|
|
|
// For completion signature void(error_code, T1, ..., Tn); |
|
template <typename T> |
|
class promise_handler_ec_n |
|
: public promise_creator<T> |
|
{ |
|
public: |
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
template <typename... Args> |
|
void operator()(const asio::error_code& ec, |
|
ASIO_MOVE_ARG(Args)... args) |
|
{ |
|
if (ec) |
|
{ |
|
this->p_->set_exception( |
|
std::make_exception_ptr( |
|
asio::system_error(ec))); |
|
} |
|
else |
|
{ |
|
this->p_->set_value( |
|
std::forward_as_tuple( |
|
ASIO_MOVE_CAST(Args)(args)...)); |
|
} |
|
} |
|
|
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
#define ASIO_PRIVATE_CALL_OP_DEF(n) \ |
|
template <ASIO_VARIADIC_TPARAMS(n)> \ |
|
void operator()(const asio::error_code& ec, \ |
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \ |
|
{\ |
|
if (ec) \ |
|
{ \ |
|
this->p_->set_exception( \ |
|
std::make_exception_ptr( \ |
|
asio::system_error(ec))); \ |
|
} \ |
|
else \ |
|
{ \ |
|
this->p_->set_value( \ |
|
std::forward_as_tuple( \ |
|
ASIO_VARIADIC_MOVE_ARGS(n))); \ |
|
} \ |
|
} \ |
|
/**/ |
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) |
|
#undef ASIO_PRIVATE_CALL_OP_DEF |
|
|
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
}; |
|
|
|
// For completion signature void(exception_ptr, T1, ..., Tn); |
|
template <typename T> |
|
class promise_handler_ex_n |
|
: public promise_creator<T> |
|
{ |
|
public: |
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
template <typename... Args> |
|
void operator()(const std::exception_ptr& ex, |
|
ASIO_MOVE_ARG(Args)... args) |
|
{ |
|
if (ex) |
|
this->p_->set_exception(ex); |
|
else |
|
{ |
|
this->p_->set_value( |
|
std::forward_as_tuple( |
|
ASIO_MOVE_CAST(Args)(args)...)); |
|
} |
|
} |
|
|
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
#define ASIO_PRIVATE_CALL_OP_DEF(n) \ |
|
template <ASIO_VARIADIC_TPARAMS(n)> \ |
|
void operator()(const std::exception_ptr& ex, \ |
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \ |
|
{\ |
|
if (ex) \ |
|
this->p_->set_exception(ex); \ |
|
else \ |
|
{ \ |
|
this->p_->set_value( \ |
|
std::forward_as_tuple( \ |
|
ASIO_VARIADIC_MOVE_ARGS(n))); \ |
|
} \ |
|
} \ |
|
/**/ |
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) |
|
#undef ASIO_PRIVATE_CALL_OP_DEF |
|
|
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
}; |
|
|
|
// Helper template to choose the appropriate concrete promise handler |
|
// implementation based on the supplied completion signature. |
|
template <typename> class promise_handler_selector; |
|
|
|
template <> |
|
class promise_handler_selector<void()> |
|
: public promise_handler_0 {}; |
|
|
|
template <> |
|
class promise_handler_selector<void(asio::error_code)> |
|
: public promise_handler_ec_0 {}; |
|
|
|
template <> |
|
class promise_handler_selector<void(std::exception_ptr)> |
|
: public promise_handler_ex_0 {}; |
|
|
|
template <typename Arg> |
|
class promise_handler_selector<void(Arg)> |
|
: public promise_handler_1<Arg> {}; |
|
|
|
template <typename Arg> |
|
class promise_handler_selector<void(asio::error_code, Arg)> |
|
: public promise_handler_ec_1<Arg> {}; |
|
|
|
template <typename Arg> |
|
class promise_handler_selector<void(std::exception_ptr, Arg)> |
|
: public promise_handler_ex_1<Arg> {}; |
|
|
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
template <typename... Arg> |
|
class promise_handler_selector<void(Arg...)> |
|
: public promise_handler_n<std::tuple<Arg...> > {}; |
|
|
|
template <typename... Arg> |
|
class promise_handler_selector<void(asio::error_code, Arg...)> |
|
: public promise_handler_ec_n<std::tuple<Arg...> > {}; |
|
|
|
template <typename... Arg> |
|
class promise_handler_selector<void(std::exception_ptr, Arg...)> |
|
: public promise_handler_ex_n<std::tuple<Arg...> > {}; |
|
|
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
#define ASIO_PRIVATE_PROMISE_SELECTOR_DEF(n) \ |
|
template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \ |
|
class promise_handler_selector< \ |
|
void(Arg, ASIO_VARIADIC_TARGS(n))> \ |
|
: public promise_handler_n< \ |
|
std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \ |
|
\ |
|
template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \ |
|
class promise_handler_selector< \ |
|
void(asio::error_code, Arg, ASIO_VARIADIC_TARGS(n))> \ |
|
: public promise_handler_ec_n< \ |
|
std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \ |
|
\ |
|
template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \ |
|
class promise_handler_selector< \ |
|
void(std::exception_ptr, Arg, ASIO_VARIADIC_TARGS(n))> \ |
|
: public promise_handler_ex_n< \ |
|
std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \ |
|
/**/ |
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_SELECTOR_DEF) |
|
#undef ASIO_PRIVATE_PROMISE_SELECTOR_DEF |
|
|
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
// Completion handlers produced from the use_future completion token, when not |
|
// using use_future::operator(). |
|
template <typename Signature, typename Allocator> |
|
class promise_handler |
|
: public promise_handler_selector<Signature> |
|
{ |
|
public: |
|
typedef Allocator allocator_type; |
|
typedef void result_type; |
|
|
|
promise_handler(use_future_t<Allocator> u) |
|
: allocator_(u.get_allocator()) |
|
{ |
|
this->create_promise(allocator_); |
|
} |
|
|
|
allocator_type get_allocator() const ASIO_NOEXCEPT |
|
{ |
|
return allocator_; |
|
} |
|
|
|
private: |
|
Allocator allocator_; |
|
}; |
|
|
|
template <typename Function, typename Signature, typename Allocator> |
|
inline void asio_handler_invoke(Function& f, |
|
promise_handler<Signature, Allocator>* h) |
|
{ |
|
typename promise_handler<Signature, Allocator>::executor_type |
|
ex(h->get_executor()); |
|
ex.dispatch(ASIO_MOVE_CAST(Function)(f), std::allocator<void>()); |
|
} |
|
|
|
template <typename Function, typename Signature, typename Allocator> |
|
inline void asio_handler_invoke(const Function& f, |
|
promise_handler<Signature, Allocator>* h) |
|
{ |
|
typename promise_handler<Signature, Allocator>::executor_type |
|
ex(h->get_executor()); |
|
ex.dispatch(f, std::allocator<void>()); |
|
} |
|
|
|
// Helper base class for async_result specialisation. |
|
template <typename Signature, typename Allocator> |
|
class promise_async_result |
|
{ |
|
public: |
|
typedef promise_handler<Signature, Allocator> completion_handler_type; |
|
typedef typename completion_handler_type::future_type return_type; |
|
|
|
explicit promise_async_result(completion_handler_type& h) |
|
: future_(h.get_future()) |
|
{ |
|
} |
|
|
|
return_type get() |
|
{ |
|
return ASIO_MOVE_CAST(return_type)(future_); |
|
} |
|
|
|
private: |
|
return_type future_; |
|
}; |
|
|
|
// Return value from use_future::operator(). |
|
template <typename Function, typename Allocator> |
|
class packaged_token |
|
{ |
|
public: |
|
packaged_token(Function f, const Allocator& a) |
|
: function_(ASIO_MOVE_CAST(Function)(f)), |
|
allocator_(a) |
|
{ |
|
} |
|
|
|
//private: |
|
Function function_; |
|
Allocator allocator_; |
|
}; |
|
|
|
// Completion handlers produced from the use_future completion token, when |
|
// using use_future::operator(). |
|
template <typename Function, typename Allocator, typename Result> |
|
class packaged_handler |
|
: public promise_creator<Result> |
|
{ |
|
public: |
|
typedef Allocator allocator_type; |
|
typedef void result_type; |
|
|
|
packaged_handler(packaged_token<Function, Allocator> t) |
|
: function_(ASIO_MOVE_CAST(Function)(t.function_)), |
|
allocator_(t.allocator_) |
|
{ |
|
this->create_promise(allocator_); |
|
} |
|
|
|
allocator_type get_allocator() const ASIO_NOEXCEPT |
|
{ |
|
return allocator_; |
|
} |
|
|
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
template <typename... Args> |
|
void operator()(ASIO_MOVE_ARG(Args)... args) |
|
{ |
|
(promise_invoke_and_set)(*this->p_, |
|
function_, ASIO_MOVE_CAST(Args)(args)...); |
|
} |
|
|
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
void operator()() |
|
{ |
|
(promise_invoke_and_set)(*this->p_, function_); |
|
} |
|
|
|
#define ASIO_PRIVATE_CALL_OP_DEF(n) \ |
|
template <ASIO_VARIADIC_TPARAMS(n)> \ |
|
void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \ |
|
{\ |
|
(promise_invoke_and_set)(*this->p_, \ |
|
function_, ASIO_VARIADIC_MOVE_ARGS(n)); \ |
|
} \ |
|
/**/ |
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) |
|
#undef ASIO_PRIVATE_CALL_OP_DEF |
|
|
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
private: |
|
Function function_; |
|
Allocator allocator_; |
|
}; |
|
|
|
template <typename Function, |
|
typename Function1, typename Allocator, typename Result> |
|
inline void asio_handler_invoke(Function& f, |
|
packaged_handler<Function1, Allocator, Result>* h) |
|
{ |
|
typename packaged_handler<Function1, Allocator, Result>::executor_type |
|
ex(h->get_executor()); |
|
ex.dispatch(ASIO_MOVE_CAST(Function)(f), std::allocator<void>()); |
|
} |
|
|
|
template <typename Function, |
|
typename Function1, typename Allocator, typename Result> |
|
inline void asio_handler_invoke(const Function& f, |
|
packaged_handler<Function1, Allocator, Result>* h) |
|
{ |
|
typename packaged_handler<Function1, Allocator, Result>::executor_type |
|
ex(h->get_executor()); |
|
ex.dispatch(f, std::allocator<void>()); |
|
} |
|
|
|
// Helper base class for async_result specialisation. |
|
template <typename Function, typename Allocator, typename Result> |
|
class packaged_async_result |
|
{ |
|
public: |
|
typedef packaged_handler<Function, Allocator, Result> completion_handler_type; |
|
typedef typename completion_handler_type::future_type return_type; |
|
|
|
explicit packaged_async_result(completion_handler_type& h) |
|
: future_(h.get_future()) |
|
{ |
|
} |
|
|
|
return_type get() |
|
{ |
|
return ASIO_MOVE_CAST(return_type)(future_); |
|
} |
|
|
|
private: |
|
return_type future_; |
|
}; |
|
|
|
} // namespace detail |
|
|
|
template <typename Allocator> template <typename Function> |
|
inline detail::packaged_token<typename decay<Function>::type, Allocator> |
|
use_future_t<Allocator>::operator()(ASIO_MOVE_ARG(Function) f) const |
|
{ |
|
return detail::packaged_token<typename decay<Function>::type, Allocator>( |
|
ASIO_MOVE_CAST(Function)(f), allocator_); |
|
} |
|
|
|
#if !defined(GENERATING_DOCUMENTATION) |
|
|
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
template <typename Allocator, typename Result, typename... Args> |
|
class async_result<use_future_t<Allocator>, Result(Args...)> |
|
: public detail::promise_async_result< |
|
void(typename decay<Args>::type...), Allocator> |
|
{ |
|
public: |
|
explicit async_result( |
|
typename detail::promise_async_result<void(typename decay<Args>::type...), |
|
Allocator>::completion_handler_type& h) |
|
: detail::promise_async_result< |
|
void(typename decay<Args>::type...), Allocator>(h) |
|
{ |
|
} |
|
}; |
|
|
|
template <typename Function, typename Allocator, |
|
typename Result, typename... Args> |
|
class async_result<detail::packaged_token<Function, Allocator>, Result(Args...)> |
|
: public detail::packaged_async_result<Function, Allocator, |
|
typename result_of<Function(Args...)>::type> |
|
{ |
|
public: |
|
explicit async_result( |
|
typename detail::packaged_async_result<Function, Allocator, |
|
typename result_of<Function(Args...)>::type>::completion_handler_type& h) |
|
: detail::packaged_async_result<Function, Allocator, |
|
typename result_of<Function(Args...)>::type>(h) |
|
{ |
|
} |
|
}; |
|
|
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
template <typename Allocator, typename Result> |
|
class async_result<use_future_t<Allocator>, Result()> |
|
: public detail::promise_async_result<void(), Allocator> |
|
{ |
|
public: |
|
explicit async_result( |
|
typename detail::promise_async_result< |
|
void(), Allocator>::completion_handler_type& h) |
|
: detail::promise_async_result<void(), Allocator>(h) |
|
{ |
|
} |
|
}; |
|
|
|
template <typename Function, typename Allocator, typename Result> |
|
class async_result<detail::packaged_token<Function, Allocator>, Result()> |
|
: public detail::packaged_async_result<Function, Allocator, |
|
typename result_of<Function()>::type> |
|
{ |
|
public: |
|
explicit async_result( |
|
typename detail::packaged_async_result<Function, Allocator, |
|
typename result_of<Function()>::type>::completion_handler_type& h) |
|
: detail::packaged_async_result<Function, Allocator, |
|
typename result_of<Function()>::type>(h) |
|
{ |
|
} |
|
}; |
|
|
|
#define ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \ |
|
template <typename Allocator, \ |
|
typename Result, ASIO_VARIADIC_TPARAMS(n)> \ |
|
class async_result<use_future_t<Allocator>, \ |
|
Result(ASIO_VARIADIC_TARGS(n))> \ |
|
: public detail::promise_async_result< \ |
|
void(ASIO_VARIADIC_DECAY(n)), Allocator> \ |
|
{ \ |
|
public: \ |
|
explicit async_result( \ |
|
typename detail::promise_async_result< \ |
|
void(ASIO_VARIADIC_DECAY(n)), \ |
|
Allocator>::completion_handler_type& h) \ |
|
: detail::promise_async_result< \ |
|
void(ASIO_VARIADIC_DECAY(n)), Allocator>(h) \ |
|
{ \ |
|
} \ |
|
}; \ |
|
\ |
|
template <typename Function, typename Allocator, \ |
|
typename Result, ASIO_VARIADIC_TPARAMS(n)> \ |
|
class async_result<detail::packaged_token<Function, Allocator>, \ |
|
Result(ASIO_VARIADIC_TARGS(n))> \ |
|
: public detail::packaged_async_result<Function, Allocator, \ |
|
typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type> \ |
|
{ \ |
|
public: \ |
|
explicit async_result( \ |
|
typename detail::packaged_async_result<Function, Allocator, \ |
|
typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type \ |
|
>::completion_handler_type& h) \ |
|
: detail::packaged_async_result<Function, Allocator, \ |
|
typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type>(h) \ |
|
{ \ |
|
} \ |
|
}; \ |
|
/**/ |
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_RESULT_DEF) |
|
#undef ASIO_PRIVATE_ASYNC_RESULT_DEF |
|
|
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
|
|
|
#if !defined(ASIO_NO_DEPRECATED) |
|
|
|
template <typename Allocator, typename Signature> |
|
struct handler_type<use_future_t<Allocator>, Signature> |
|
{ |
|
typedef typename async_result<use_future_t<Allocator>, |
|
Signature>::completion_handler_type type; |
|
}; |
|
|
|
template <typename Signature, typename Allocator> |
|
class async_result<detail::promise_handler<Signature, Allocator> > |
|
: public detail::promise_async_result<Signature, Allocator> |
|
{ |
|
public: |
|
typedef typename detail::promise_async_result< |
|
Signature, Allocator>::return_type type; |
|
|
|
explicit async_result( |
|
typename detail::promise_async_result< |
|
Signature, Allocator>::completion_handler_type& h) |
|
: detail::promise_async_result<Signature, Allocator>(h) |
|
{ |
|
} |
|
}; |
|
|
|
template <typename Function, typename Allocator, typename Signature> |
|
struct handler_type<detail::packaged_token<Function, Allocator>, Signature> |
|
{ |
|
typedef typename async_result<detail::packaged_token<Function, Allocator>, |
|
Signature>::completion_handler_type type; |
|
}; |
|
|
|
template <typename Function, typename Allocator, typename Result> |
|
class async_result<detail::packaged_handler<Function, Allocator, Result> > |
|
: public detail::packaged_async_result<Function, Allocator, Result> |
|
{ |
|
public: |
|
typedef typename detail::packaged_async_result< |
|
Function, Allocator, Result>::return_type type; |
|
|
|
explicit async_result( |
|
typename detail::packaged_async_result< |
|
Function, Allocator, Result>::completion_handler_type& h) |
|
: detail::packaged_async_result<Function, Allocator, Result>(h) |
|
{ |
|
} |
|
}; |
|
|
|
#endif // !defined(ASIO_NO_DEPRECATED) |
|
|
|
#endif // !defined(GENERATING_DOCUMENTATION) |
|
|
|
} // namespace asio |
|
|
|
#include "asio/detail/pop_options.hpp" |
|
|
|
#endif // ASIO_IMPL_USE_FUTURE_HPP
|
|
|