Add async_result support to go().
diff --git a/asio/include/asio/detail/variadic_templates.hpp b/asio/include/asio/detail/variadic_templates.hpp
index a8ac797..2c1f533 100644
--- a/asio/include/asio/detail/variadic_templates.hpp
+++ b/asio/include/asio/detail/variadic_templates.hpp
@@ -48,6 +48,20 @@
# define ASIO_VARIADIC_PARAMS_4 T1 x1, T2 x2, T3 x3, T4 x4
# define ASIO_VARIADIC_PARAMS_5 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5
+# define ASIO_VARIADIC_CONSTREF_PARAMS(n) \
+ ASIO_VARIADIC_CONSTREF_PARAMS_##n
+
+# define ASIO_VARIADIC_CONSTREF_PARAMS_1 \
+ const T1& x1
+# define ASIO_VARIADIC_CONSTREF_PARAMS_2 \
+ const T1& x1, const T2& x2
+# define ASIO_VARIADIC_CONSTREF_PARAMS_3 \
+ const T1& x1, const T2& x2, const T3& x3
+# define ASIO_VARIADIC_CONSTREF_PARAMS_4 \
+ const T1& x1, const T2& x2, const T3& x3, const T4& x4
+# define ASIO_VARIADIC_CONSTREF_PARAMS_5 \
+ const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5
+
# define ASIO_VARIADIC_ARGS(n) ASIO_VARIADIC_ARGS_##n
# define ASIO_VARIADIC_ARGS_1 x1
diff --git a/asio/include/asio/go.hpp b/asio/include/asio/go.hpp
index ce4a2f7..1346964 100644
--- a/asio/include/asio/go.hpp
+++ b/asio/include/asio/go.hpp
@@ -17,16 +17,33 @@
#include "asio/detail/config.hpp"
#include "asio/coroutine.hpp"
+#include "asio/detail/variadic_templates.hpp"
#include "asio/detail/wrapped_handler.hpp"
#include "asio/io_service.hpp"
#include "asio/strand.hpp"
+#if !defined(ASIO_HAS_VARIADIC_TEMPLATES)
+
+# include "asio/detail/variadic_templates.hpp"
+
+// A macro that should expand to:
+// template <typename T1, ..., typename Tn>
+// void complete(const T1& x1, ..., const Tn& xn);
+// This macro should only persist within this file.
+
+# define ASIO_PRIVATE_COMPLETE_DECL(n) \
+ template <ASIO_VARIADIC_TPARAMS(n)> \
+ void complete(ASIO_VARIADIC_CONSTREF_PARAMS(n)); \
+ /**/
+
+#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)
+
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
-template <typename Handler> class stackless_impl_base;
+template <typename Handler, typename Signature> class stackless_impl_base;
} // namespace detail
@@ -47,11 +64,11 @@
* }
* } @endcode
*
- * The initiating function (async_read_some in the above example) suspends the
- * current coroutine. The coroutine is resumed when the asynchronous operation
- * completes.
+ * The initiating function (@c async_read_some in the above example) suspends
+ * the current coroutine. The coroutine is resumed when the asynchronous
+ * operation completes.
*/
-template <typename Handler>
+template <typename Handler, typename Signature = void ()>
class basic_stackless_context
{
public:
@@ -84,10 +101,31 @@
return tmp;
}
+ /// Invoke the completion handler with the specified arguments.
+ /**
+ * This function is used to invoke the coroutine's associated completion
+ * handler. It should be called at most once, immediately prior to the
+ * termination of the coroutine. Additional calls will be ignored.
+ *
+ * For completion handlers with the signature <tt>void()</tt>, and if @c
+ * complete() is not explicitly called, the completion handler will be
+ * automatically invoked after coroutine termination.
+ */
+#if defined(GENERATING_DOCUMENTATION) \
+ || defined(ASIO_HAS_VARIADIC_TEMPLATES)
+ template <typename... T>
+ void complete(T&&... args);
+#else // defined(GENERATING_DOCUMENTATION)
+ // || defined(ASIO_HAS_VARIADIC_TEMPLATES)
+ void complete();
+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPLETE_DECL)
+#endif // defined(GENERATING_DOCUMENTATION)
+ // || defined(ASIO_HAS_VARIADIC_TEMPLATES)
+
#if defined(GENERATING_DOCUMENTATION)
private:
#endif // defined(GENERATING_DOCUMENTATION)
- detail::stackless_impl_base<Handler>** impl_;
+ detail::stackless_impl_base<Handler, Signature>** impl_;
asio::error_code* ec_;
};
@@ -97,7 +135,7 @@
#else // defined(GENERATING_DOCUMENTATION)
typedef basic_stackless_context<
detail::wrapped_handler<
- io_service::strand, void(*)(),
+ io_service::strand, void (*)(),
detail::is_continuation_if_running> > stackless_context;
#endif // defined(GENERATING_DOCUMENTATION)
@@ -143,21 +181,40 @@
*/
/*@{*/
-/// Start a new stackless coroutine, calling the specified handler when it
-/// completes.
+/// Start a new stackless coroutine with an associated completion handler.
/**
* This function is used to launch a new coroutine.
*
- * @param handler A handler to be called when the coroutine exits. More
+ * @param handler The handler associated with the coroutine. The handler may be
+ * explicitly called via the context's @c complete() function, but will be
+ * invoked automatically after coroutine termination if not called first. More
* importantly, the handler provides an execution context (via the the handler
* invocation hook) for the coroutine. The handler must have the signature:
* @code void handler(); @endcode
*
* @param function The coroutine function. The function must have the signature:
- * @code void function(basic_stackless_context<Handler> yield); @endcode
+ * @code void function(basic_stackless_context<Handler> c); @endcode
*/
template <typename Handler, typename Function>
-void go(ASIO_MOVE_ARG(Handler) handler,
+ASIO_INITFN_RESULT_TYPE(Handler, void ())
+go(ASIO_MOVE_ARG(Handler) handler,
+ ASIO_MOVE_ARG(Function) function);
+
+/// Start a new stackless coroutine with an associated completion handler.
+/**
+ * This function is used to launch a new coroutine.
+ *
+ * @param handler The handler associated with the coroutine. The handler may be
+ * explicitly called via the context's @c complete() function. Furthermore, the
+ * handler provides an execution context (via the the handler invocation hook)
+ * for the coroutine.
+ *
+ * @param function The coroutine function. The function must have the signature:
+ * @code void function(basic_stackless_context<Handler, Signature> c); @endcode
+ */
+template <typename Signature, typename Handler, typename Function>
+ASIO_INITFN_RESULT_TYPE(Handler, Signature)
+go(ASIO_MOVE_ARG(Handler) handler,
ASIO_MOVE_ARG(Function) function);
/// Start a new stackless coroutine, inheriting the execution context of another.
@@ -212,6 +269,10 @@
#include "asio/detail/pop_options.hpp"
+#if !defined(ASIO_HAS_VARIADIC_TEMPLATES)
+# undef ASIO_PRIVATE_COMPLETE_DECL
+#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)
+
#include "asio/impl/go.hpp"
#endif // ASIO_GO_HPP
diff --git a/asio/include/asio/impl/go.hpp b/asio/include/asio/impl/go.hpp
index 45ac9b9..824922e 100644
--- a/asio/include/asio/impl/go.hpp
+++ b/asio/include/asio/impl/go.hpp
@@ -29,20 +29,21 @@
namespace asio {
namespace detail {
- template <typename Handler>
+ template <typename Handler, typename Signature>
class stackless_impl_base
{
protected:
template <typename Handler1>
explicit stackless_impl_base(ASIO_MOVE_ARG(Handler1) handler,
- void (*resume_fn)(const basic_stackless_context<Handler>&),
+ void (*resume_fn)(const basic_stackless_context<Handler, Signature>&),
void (*destroy_fn)(stackless_impl_base*))
: handler_(ASIO_MOVE_CAST(Handler1)(handler)),
ref_count_(1),
result_ec_(&throw_ec_),
result_value_(0),
resume_(resume_fn),
- destroy_(destroy_fn)
+ destroy_(destroy_fn),
+ completed_(false)
{
}
@@ -53,37 +54,40 @@
static void resume(stackless_impl_base*& impl);
//private:
- Handler handler_;
+ typename handler_type<Handler, Signature>::type handler_;
asio::detail::atomic_count ref_count_;
asio::coroutine coroutine_;
asio::error_code throw_ec_;
asio::error_code* result_ec_;
void* result_value_;
- void (*resume_)(const basic_stackless_context<Handler>&);
+ void (*resume_)(const basic_stackless_context<Handler, Signature>&);
void (*destroy_)(stackless_impl_base*);
+ bool completed_;
};
- template <typename Handler>
- stackless_impl_base<Handler>* stackless_impl_base<Handler>::add_ref(
- stackless_impl_base<Handler>* impl)
+ template <typename Handler, typename Signature>
+ stackless_impl_base<Handler, Signature>*
+ stackless_impl_base<Handler, Signature>::add_ref(
+ stackless_impl_base<Handler, Signature>* impl)
{
if (impl)
++impl->ref_count_;
return impl;
}
- template <typename Handler>
- inline stackless_impl_base<Handler>* stackless_impl_base<Handler>::move_ref(
- stackless_impl_base<Handler>*& impl)
+ template <typename Handler, typename Signature>
+ inline stackless_impl_base<Handler, Signature>*
+ stackless_impl_base<Handler, Signature>::move_ref(
+ stackless_impl_base<Handler, Signature>*& impl)
{
stackless_impl_base* tmp = impl;
impl = 0;
return tmp;
}
- template <typename Handler>
- void stackless_impl_base<Handler>::release_ref(
- stackless_impl_base<Handler>* impl)
+ template <typename Handler, typename Signature>
+ void stackless_impl_base<Handler, Signature>::release_ref(
+ stackless_impl_base<Handler, Signature>* impl)
{
if (impl)
{
@@ -92,26 +96,45 @@
}
}
- template <typename Handler>
- void stackless_impl_base<Handler>::resume(
- stackless_impl_base<Handler>*& impl)
+ template <typename Signature>
+ struct call_completed_handler
+ {
+ template <typename Handler>
+ static void call(Handler&) {}
+ };
+
+ template <>
+ struct call_completed_handler<void ()>
+ {
+ template <typename Handler>
+ static void call(Handler& h) { h(); }
+ };
+
+ template <typename Handler, typename Signature>
+ void stackless_impl_base<Handler, Signature>::resume(
+ stackless_impl_base<Handler, Signature>*& impl)
{
impl->result_value_ = 0;
- const basic_stackless_context<Handler> ctx = { &impl, &impl->throw_ec_ };
+ basic_stackless_context<Handler, Signature> ctx
+ = { &impl, &impl->throw_ec_ };
impl->resume_(ctx);
- if (impl && impl->coroutine_.is_complete())
- impl->handler_();
+
+ if (impl && impl->coroutine_.is_complete() && !impl->completed_)
+ {
+ impl->completed_ = true;
+ call_completed_handler<Signature>::call(impl->handler_);
+ }
}
- template <typename Handler, typename Function>
+ template <typename Handler, typename Signature, typename Function>
class stackless_impl :
- public stackless_impl_base<Handler>
+ public stackless_impl_base<Handler, Signature>
{
public:
template <typename Handler1, typename Function1>
stackless_impl(ASIO_MOVE_ARG(Handler1) handler,
ASIO_MOVE_ARG(Function1) function)
- : stackless_impl_base<Handler>(
+ : stackless_impl_base<Handler, Signature>(
ASIO_MOVE_CAST(Handler1)(handler),
&stackless_impl::do_resume,
&stackless_impl::do_destroy),
@@ -120,13 +143,14 @@
}
private:
- static void do_resume(const basic_stackless_context<Handler>& ctx)
+ static void do_resume(
+ const basic_stackless_context<Handler, Signature>& ctx)
{
- stackless_impl_base<Handler>* base = *ctx.impl_;
+ stackless_impl_base<Handler, Signature>* base = *ctx.impl_;
static_cast<stackless_impl*>(base)->function_(ctx);
}
- static void do_destroy(stackless_impl_base<Handler>* impl)
+ static void do_destroy(stackless_impl_base<Handler, Signature>* impl)
{
delete static_cast<stackless_impl*>(impl);
}
@@ -134,31 +158,31 @@
Function function_;
};
- template <typename Handler, typename T>
+ template <typename Handler, typename Signature, typename T>
class stackless_handler
{
public:
- stackless_handler(const basic_stackless_context<Handler>& ctx)
- : impl_(stackless_impl_base<Handler>::move_ref(*ctx.impl_))
+ stackless_handler(const basic_stackless_context<Handler, Signature>& ctx)
+ : impl_(stackless_impl_base<Handler, Signature>::move_ref(*ctx.impl_))
{
impl_->result_ec_ = ctx.ec_;
}
stackless_handler(const stackless_handler& other)
- : impl_(stackless_impl_base<Handler>::add_ref(other.impl_))
+ : impl_(stackless_impl_base<Handler, Signature>::add_ref(other.impl_))
{
}
#if defined(ASIO_HAS_MOVE)
stackless_handler(stackless_handler&& other)
- : impl_(stackless_impl_base<Handler>::move_ref(other.impl_))
+ : impl_(stackless_impl_base<Handler, Signature>::move_ref(other.impl_))
{
}
#endif // defined(ASIO_HAS_MOVE)
~stackless_handler()
{
- stackless_impl_base<Handler>::release_ref(impl_);
+ stackless_impl_base<Handler, Signature>::release_ref(impl_);
}
void operator()(T value)
@@ -166,7 +190,7 @@
*impl_->result_ec_ = asio::error_code();
if (impl_->result_value_)
*static_cast<T*>(impl_->result_value_) = value;
- stackless_impl_base<Handler>::resume(impl_);
+ stackless_impl_base<Handler, Signature>::resume(impl_);
}
void operator()(asio::error_code ec, T value)
@@ -174,130 +198,139 @@
*impl_->result_ec_ = ec;
if (impl_->result_value_)
*static_cast<T*>(impl_->result_value_) = value;
- stackless_impl_base<Handler>::resume(impl_);
+ stackless_impl_base<Handler, Signature>::resume(impl_);
}
//private:
- stackless_impl_base<Handler>* impl_;
+ stackless_impl_base<Handler, Signature>* impl_;
+
+ private:
+ stackless_handler& operator=(const stackless_handler&);
};
- template <typename Handler>
- class stackless_handler<Handler, void>
+ template <typename Handler, typename Signature>
+ class stackless_handler<Handler, Signature, void>
{
public:
- stackless_handler(const basic_stackless_context<Handler>& ctx)
- : impl_(stackless_impl_base<Handler>::move_ref(*ctx.impl_))
+ stackless_handler(const basic_stackless_context<Handler, Signature>& ctx)
+ : impl_(stackless_impl_base<Handler, Signature>::move_ref(*ctx.impl_))
{
impl_->result_ec_ = ctx.ec_;
}
stackless_handler(const stackless_handler& other)
- : impl_(stackless_impl_base<Handler>::add_ref(other.impl_))
+ : impl_(stackless_impl_base<Handler, Signature>::add_ref(other.impl_))
{
}
#if defined(ASIO_HAS_MOVE)
stackless_handler(stackless_handler&& other)
- : impl_(stackless_impl_base<Handler>::move_ref(other.impl_))
+ : impl_(stackless_impl_base<Handler, Signature>::move_ref(other.impl_))
{
}
#endif // defined(ASIO_HAS_MOVE)
~stackless_handler()
{
- stackless_impl_base<Handler>::release_ref(impl_);
+ stackless_impl_base<Handler, Signature>::release_ref(impl_);
}
void operator()()
{
*impl_->result_ec_ = asio::error_code();
- stackless_impl_base<Handler>::resume(impl_);
+ stackless_impl_base<Handler, Signature>::resume(impl_);
}
void operator()(asio::error_code ec)
{
*impl_->result_ec_ = ec;
- stackless_impl_base<Handler>::resume(impl_);
+ stackless_impl_base<Handler, Signature>::resume(impl_);
}
//private:
- stackless_impl_base<Handler>* impl_;
+ stackless_impl_base<Handler, Signature>* impl_;
+
+ private:
+ stackless_handler& operator=(const stackless_handler&);
};
- template <typename Handler, typename T>
+ template <typename Handler, typename Signature, typename T>
inline void* asio_handler_allocate(std::size_t size,
- stackless_handler<Handler, T>* this_handler)
+ stackless_handler<Handler, Signature, T>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->impl_->handler_);
}
- template <typename Handler, typename T>
+ template <typename Handler, typename Signature, typename T>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- stackless_handler<Handler, T>* this_handler)
+ stackless_handler<Handler, Signature, T>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->impl_->handler_);
}
- template <typename Handler, typename T>
+ template <typename Handler, typename Signature, typename T>
inline bool asio_handler_is_continuation(
- stackless_handler<Handler, T>*)
+ stackless_handler<Handler, Signature, T>*)
{
return true;
}
- template <typename Function, typename Handler, typename T>
+ template <typename Function, typename Handler, typename Signature, typename T>
inline void asio_handler_invoke(Function& function,
- stackless_handler<Handler, T>* this_handler)
+ stackless_handler<Handler, Signature, T>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->impl_->handler_);
}
- template <typename Function, typename Handler, typename T>
+ template <typename Function, typename Handler, typename Signature, typename T>
inline void asio_handler_invoke(const Function& function,
- stackless_handler<Handler, T>* this_handler)
+ stackless_handler<Handler, Signature, T>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->impl_->handler_);
}
- template <typename Handler, typename Function>
+ template <typename Handler, typename Signature, typename Function>
struct go_helper
{
template <typename Handler1, typename Function1>
go_helper(ASIO_MOVE_ARG(Handler1) handler,
ASIO_MOVE_ARG(Function1) function)
- : impl_(new stackless_impl<Handler, Function>(
+ : impl_(new stackless_impl<Handler, Signature, Function>(
ASIO_MOVE_CAST(Handler1)(handler),
ASIO_MOVE_CAST(Function1)(function)))
{
}
go_helper(const go_helper& other)
- : impl_(stackless_impl_base<Handler>::add_ref(other.impl_))
+ : impl_(stackless_impl_base<Handler, Signature>::add_ref(other.impl_))
{
}
#if defined(ASIO_HAS_MOVE)
go_helper(go_helper&& other)
- : impl_(stackless_impl_base<Handler>::move_ref(other.impl_))
+ : impl_(stackless_impl_base<Handler, Signature>::move_ref(other.impl_))
{
}
#endif // defined(ASIO_HAS_MOVE)
~go_helper()
{
- stackless_impl_base<Handler>::release_ref(impl_);
+ stackless_impl_base<Handler, Signature>::release_ref(impl_);
}
void operator()()
{
- stackless_impl_base<Handler>::resume(impl_);
+ stackless_impl_base<Handler, Signature>::resume(impl_);
}
- stackless_impl_base<Handler>* impl_;
+ stackless_impl_base<Handler, Signature>* impl_;
+
+ private:
+ go_helper& operator=(const go_helper&);
};
inline void default_go_handler() {}
@@ -306,39 +339,42 @@
#if !defined(GENERATING_DOCUMENTATION)
-template <typename Handler, typename ReturnType>
-struct handler_type<basic_stackless_context<Handler>, ReturnType()>
+template <typename Handler, typename Signature, typename ReturnType>
+struct handler_type<basic_stackless_context<Handler, Signature>, ReturnType()>
{
- typedef detail::stackless_handler<Handler, void> type;
+ typedef detail::stackless_handler<Handler, Signature, void> type;
};
-template <typename Handler, typename ReturnType, typename Arg1>
-struct handler_type<basic_stackless_context<Handler>, ReturnType(Arg1)>
+template <typename Handler, typename Signature,
+ typename ReturnType, typename Arg1>
+struct handler_type<basic_stackless_context<Handler, Signature>,
+ ReturnType(Arg1)>
{
- typedef detail::stackless_handler<Handler, Arg1> type;
+ typedef detail::stackless_handler<Handler, Signature, Arg1> type;
};
-template <typename Handler, typename ReturnType>
-struct handler_type<basic_stackless_context<Handler>,
+template <typename Handler, typename Signature, typename ReturnType>
+struct handler_type<basic_stackless_context<Handler, Signature>,
ReturnType(asio::error_code)>
{
- typedef detail::stackless_handler<Handler, void> type;
+ typedef detail::stackless_handler<Handler, Signature, void> type;
};
-template <typename Handler, typename ReturnType, typename Arg2>
-struct handler_type<basic_stackless_context<Handler>,
+template <typename Handler, typename Signature,
+ typename ReturnType, typename Arg2>
+struct handler_type<basic_stackless_context<Handler, Signature>,
ReturnType(asio::error_code, Arg2)>
{
- typedef detail::stackless_handler<Handler, Arg2> type;
+ typedef detail::stackless_handler<Handler, Signature, Arg2> type;
};
-template <typename Handler, typename T>
-class async_result<detail::stackless_handler<Handler, T> >
+template <typename Handler, typename Signature, typename T>
+class async_result<detail::stackless_handler<Handler, Signature, T> >
{
public:
typedef awaitable<T> type;
- explicit async_result(detail::stackless_handler<Handler, T>&)
+ explicit async_result(detail::stackless_handler<Handler, Signature, T>&)
{
}
@@ -348,65 +384,161 @@
}
};
-template <typename Handler>
+template <typename Handler, typename Signature>
inline coroutine& get_coroutine(
- basic_stackless_context<Handler>& c)
+ basic_stackless_context<Handler, Signature>& c)
{
return (*c.impl_)->coroutine_;
}
-template <typename Handler>
+template <typename Handler, typename Signature>
inline coroutine& get_coroutine(
- basic_stackless_context<Handler>* c)
+ basic_stackless_context<Handler, Signature>* c)
{
return (*c->impl_)->coroutine_;
}
-template <typename Handler>
+template <typename Handler, typename Signature>
inline const asio::error_code* get_coroutine_error(
- basic_stackless_context<Handler>& c)
+ basic_stackless_context<Handler, Signature>& c)
{
return &(*c.impl_)->throw_ec_;
}
-template <typename Handler>
+template <typename Handler, typename Signature>
inline const asio::error_code* get_coroutine_error(
- basic_stackless_context<Handler>* c)
+ basic_stackless_context<Handler, Signature>* c)
{
return &(*c->impl_)->throw_ec_;
}
-template <typename Handler>
+template <typename Handler, typename Signature>
inline void** get_coroutine_async_result(
- basic_stackless_context<Handler>& c)
+ basic_stackless_context<Handler, Signature>& c)
{
return &(*c.impl_)->result_value_;
}
-template <typename Handler>
+template <typename Handler, typename Signature>
inline void** get_coroutine_async_result(
- basic_stackless_context<Handler>* c)
+ basic_stackless_context<Handler, Signature>* c)
{
return &(*c->impl_)->result_value_;
}
+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename Handler, typename Signature>
+template <typename... T>
+void basic_stackless_context<Handler, Signature>::complete(T&&... args)
+{
+ if (!(*impl_)->completed_)
+ {
+ (*impl_)->completed_ = true;
+ (*impl_)->handler_(static_cast<T&&>(args)...);
+ }
+}
+
+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename Handler, typename Signature>
+void basic_stackless_context<Handler, Signature>::complete()
+{
+ if (!(*impl_)->completed_)
+ {
+ (*impl_)->completed_ = true;
+ (*impl_)->handler_();
+ }
+}
+
+// A macro that should expand to:
+// template <typename Handler, typename Signature>
+// template <typename T1, ..., typename Tn>
+// void basic_stackless_context<Handler, Signature>::complete(
+// const T1& x1, ..., const Tn& xn)
+// {
+// if (!(*impl_)->completed_)
+// {
+// (*impl_)->completed_ = true;
+// (*impl_)->handler_(x1, ..., xn);
+// }
+// }
+// This macro should only persist within this file.
+
+# define ASIO_PRIVATE_COMPLETE_DEF(n) \
+ template <typename Handler, typename Signature> \
+ template <ASIO_VARIADIC_TPARAMS(n)> \
+ void basic_stackless_context<Handler, Signature>::complete( \
+ ASIO_VARIADIC_CONSTREF_PARAMS(n)) \
+ { \
+ if (!(*impl_)->completed_) \
+ { \
+ (*impl_)->completed_ = true; \
+ (*impl_)->handler_(ASIO_VARIADIC_ARGS(n)); \
+ } \
+ } \
+ /**/
+
+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPLETE_DEF)
+
+# undef ASIO_PRIVATE_COMPLETE_DEF
+
+#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
+
template <typename Handler, typename Function>
-void go(ASIO_MOVE_ARG(Handler) handler,
+ASIO_INITFN_RESULT_TYPE(Handler, void ())
+go(ASIO_MOVE_ARG(Handler) handler,
ASIO_MOVE_ARG(Function) function)
{
- typedef typename handler_type<Handler, void()>::type
- real_handler_type;
+ typedef typename remove_const<
+ typename remove_reference<Handler>::type>::type
+ passed_handler_type;
+
+ typedef typename handler_type<
+ Handler, void ()>::type real_handler_type;
typedef typename remove_const<
typename remove_reference<Function>::type>::type
function_type;
- detail::go_helper<real_handler_type, function_type> helper(
+ detail::go_helper<passed_handler_type, void (), function_type> helper(
ASIO_MOVE_CAST(Handler)(handler),
ASIO_MOVE_CAST(Function)(function));
+ async_result<real_handler_type> result(helper.impl_->handler_);
+
asio_handler_invoke_helpers::invoke(
helper, helper.impl_->handler_);
+
+ return result.get();
+}
+
+template <typename Signature, typename Handler, typename Function>
+ASIO_INITFN_RESULT_TYPE(Handler, Signature)
+go(ASIO_MOVE_ARG(Handler) handler,
+ ASIO_MOVE_ARG(Function) function)
+{
+ typedef typename remove_const<
+ typename remove_reference<Handler>::type>::type
+ passed_handler_type;
+
+ typedef typename handler_type<
+ Handler, Signature>::type real_handler_type;
+
+ typedef typename remove_const<
+ typename remove_reference<Function>::type>::type
+ function_type;
+
+ detail::go_helper<passed_handler_type, Signature, function_type> helper(
+ ASIO_MOVE_CAST(Handler)(handler),
+ ASIO_MOVE_CAST(Function)(function));
+
+ async_result<real_handler_type> result(helper.impl_->handler_);
+
+ asio_handler_invoke_helpers::invoke(
+ helper, helper.impl_->handler_);
+
+ return result.get();
}
template <typename Handler, typename Function>