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>