Rename basic_stackless_context to stackless_context and make the use of the template parameters explicit.
diff --git a/asio/include/asio/go.hpp b/asio/include/asio/go.hpp index 1346964..c9d5fb5 100644 --- a/asio/include/asio/go.hpp +++ b/asio/include/asio/go.hpp
@@ -18,7 +18,6 @@ #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" @@ -49,12 +48,12 @@ /// Context object the represents the currently executing coroutine. /** - * The basic_stackless_context class is used to represent the currently - * executing stackless coroutine. A basic_stackless_context may be passed as a - * handler to an asynchronous operation. For example: + * The stackless_context class is used to represent the currently executing + * stackless coroutine. A stackless_context may be passed as a handler to an + * asynchronous operation. For example: * * @code template <typename Handler> - * void my_coroutine(basic_stackless_context<Handler> ctx) + * void my_coroutine(stackless_context<Handler> ctx) * { * reenter (ctx) * { @@ -68,8 +67,8 @@ * the current coroutine. The coroutine is resumed when the asynchronous * operation completes. */ -template <typename Handler, typename Signature = void ()> -class basic_stackless_context +template <typename Handler = void, typename Signature = void ()> +class stackless_context { public: /// Return a coroutine context that sets the specified error_code. @@ -80,7 +79,7 @@ * set with the asynchronous operation's result. For example: * * @code template <typename Handler> - * void my_coroutine(basic_stackless_context<Handler> ctx) + * void my_coroutine(stackless_context<Handler> ctx) * { * reenter (ctx) * { @@ -94,9 +93,9 @@ * } * } @endcode */ - basic_stackless_context operator[](asio::error_code& ec) const + stackless_context operator[](asio::error_code& ec) const { - basic_stackless_context tmp(*this); + stackless_context tmp(*this); tmp.ec_ = &ec; return tmp; } @@ -106,10 +105,6 @@ * 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) @@ -129,16 +124,6 @@ asio::error_code* ec_; }; -#if defined(GENERATING_DOCUMENTATION) -/// Context object that represents the currently executing coroutine. -typedef basic_stackless_context<unspecified> stackless_context; -#else // defined(GENERATING_DOCUMENTATION) -typedef basic_stackless_context< - detail::wrapped_handler< - io_service::strand, void (*)(), - detail::is_continuation_if_running> > stackless_context; -#endif // defined(GENERATING_DOCUMENTATION) - /** * @defgroup go asio::go * @@ -181,19 +166,28 @@ */ /*@{*/ +/// Start a new stackless coroutine. +/** + * This function is used to launch a new coroutine. + * + * @param function The coroutine function. The function must have the signature: + * @code void function(stackless_context<void> c); @endcode + */ +template <typename Function> +void go(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, but will be - * invoked automatically after coroutine termination if not called first. More + * explicitly called via the context's @c complete() function. 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> c); @endcode + * @code void function(stackless_context<Handler> c); @endcode */ template <typename Handler, typename Function> ASIO_INITFN_RESULT_TYPE(Handler, void ()) @@ -210,7 +204,7 @@ * for the coroutine. * * @param function The coroutine function. The function must have the signature: - * @code void function(basic_stackless_context<Handler, Signature> c); @endcode + * @code void function(stackless_context<Handler, Signature> c); @endcode */ template <typename Signature, typename Handler, typename Function> ASIO_INITFN_RESULT_TYPE(Handler, Signature) @@ -228,10 +222,10 @@ * same strand. * * @param function The coroutine function. The function must have the signature: - * @code void function(basic_stackless_context<Handler> yield); @endcode + * @code void function(stackless_context<Handler> yield); @endcode */ template <typename Handler, typename Function> -void go(basic_stackless_context<Handler> ctx, +void go(stackless_context<Handler> ctx, ASIO_MOVE_ARG(Function) function); /// Start a new stackless coroutine that executes in the context of a strand. @@ -243,7 +237,7 @@ * execute simultaneously. * * @param function The coroutine function. The function must have the signature: - * @code void function(stackless_context yield); @endcode + * @code void function(stackless_context<io_service::strand> yield); @endcode */ template <typename Function> void go(asio::io_service::strand strand, @@ -253,11 +247,10 @@ /** * This function is used to launch a new coroutine. * - * @param io_service Identifies the io_service that will run the coroutine. The - * new coroutine is implicitly given its own strand within this io_service. + * @param io_service Identifies the io_service that will run the coroutine. * * @param function The coroutine function. The function must have the signature: - * @code void function(stackless_context yield); @endcode + * @code void function(stackless_context<io_service> yield); @endcode */ template <typename Function> void go(asio::io_service& io_service,
diff --git a/asio/include/asio/impl/go.hpp b/asio/include/asio/impl/go.hpp index 824922e..ea84f63 100644 --- a/asio/include/asio/impl/go.hpp +++ b/asio/include/asio/impl/go.hpp
@@ -22,6 +22,7 @@ #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/type_traits.hpp" +#include "asio/detail/wrapped_handler.hpp" #include "asio/handler_type.hpp" #include "asio/detail/push_options.hpp" @@ -30,12 +31,37 @@ namespace detail { template <typename Handler, typename Signature> + struct stackless_handler_type + { + typedef typename handler_type<Handler, Signature>::type type; + }; + + template <> + struct stackless_handler_type<void, void()> + { + typedef void (*type)(); + }; + + template <> + struct stackless_handler_type<asio::io_service, void()> + { + typedef wrapped_handler<asio::io_service&, void(*)()> type; + }; + + template <> + struct stackless_handler_type<asio::io_service::strand, void()> + { + typedef wrapped_handler<asio::io_service::strand, + void(*)(), is_continuation_if_running> type; + }; + + 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, Signature>&), + void (*resume_fn)(const stackless_context<Handler, Signature>&), void (*destroy_fn)(stackless_impl_base*)) : handler_(ASIO_MOVE_CAST(Handler1)(handler)), ref_count_(1), @@ -54,13 +80,13 @@ static void resume(stackless_impl_base*& impl); //private: - typename handler_type<Handler, Signature>::type handler_; + typename stackless_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, Signature>&); + void (*resume_)(const stackless_context<Handler, Signature>&); void (*destroy_)(stackless_impl_base*); bool completed_; }; @@ -96,34 +122,13 @@ } } - 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; - basic_stackless_context<Handler, Signature> ctx - = { &impl, &impl->throw_ec_ }; + stackless_context<Handler, Signature> ctx = { &impl, &impl->throw_ec_ }; impl->resume_(ctx); - - if (impl && impl->coroutine_.is_complete() && !impl->completed_) - { - impl->completed_ = true; - call_completed_handler<Signature>::call(impl->handler_); - } } template <typename Handler, typename Signature, typename Function> @@ -143,8 +148,7 @@ } private: - static void do_resume( - const basic_stackless_context<Handler, Signature>& ctx) + static void do_resume(const stackless_context<Handler, Signature>& ctx) { stackless_impl_base<Handler, Signature>* base = *ctx.impl_; static_cast<stackless_impl*>(base)->function_(ctx); @@ -162,7 +166,7 @@ class stackless_handler { public: - stackless_handler(const basic_stackless_context<Handler, Signature>& ctx) + stackless_handler(const stackless_context<Handler, Signature>& ctx) : impl_(stackless_impl_base<Handler, Signature>::move_ref(*ctx.impl_)) { impl_->result_ec_ = ctx.ec_; @@ -212,7 +216,7 @@ class stackless_handler<Handler, Signature, void> { public: - stackless_handler(const basic_stackless_context<Handler, Signature>& ctx) + stackless_handler(const stackless_context<Handler, Signature>& ctx) : impl_(stackless_impl_base<Handler, Signature>::move_ref(*ctx.impl_)) { impl_->result_ec_ = ctx.ec_; @@ -340,21 +344,20 @@ #if !defined(GENERATING_DOCUMENTATION) template <typename Handler, typename Signature, typename ReturnType> -struct handler_type<basic_stackless_context<Handler, Signature>, ReturnType()> +struct handler_type<stackless_context<Handler, Signature>, ReturnType()> { typedef detail::stackless_handler<Handler, Signature, void> type; }; template <typename Handler, typename Signature, typename ReturnType, typename Arg1> -struct handler_type<basic_stackless_context<Handler, Signature>, - ReturnType(Arg1)> +struct handler_type<stackless_context<Handler, Signature>, ReturnType(Arg1)> { typedef detail::stackless_handler<Handler, Signature, Arg1> type; }; template <typename Handler, typename Signature, typename ReturnType> -struct handler_type<basic_stackless_context<Handler, Signature>, +struct handler_type<stackless_context<Handler, Signature>, ReturnType(asio::error_code)> { typedef detail::stackless_handler<Handler, Signature, void> type; @@ -362,7 +365,7 @@ template <typename Handler, typename Signature, typename ReturnType, typename Arg2> -struct handler_type<basic_stackless_context<Handler, Signature>, +struct handler_type<stackless_context<Handler, Signature>, ReturnType(asio::error_code, Arg2)> { typedef detail::stackless_handler<Handler, Signature, Arg2> type; @@ -385,43 +388,41 @@ }; template <typename Handler, typename Signature> -inline coroutine& get_coroutine( - basic_stackless_context<Handler, Signature>& c) +inline coroutine& get_coroutine(stackless_context<Handler, Signature>& c) { return (*c.impl_)->coroutine_; } template <typename Handler, typename Signature> -inline coroutine& get_coroutine( - basic_stackless_context<Handler, Signature>* c) +inline coroutine& get_coroutine(stackless_context<Handler, Signature>* c) { return (*c->impl_)->coroutine_; } template <typename Handler, typename Signature> inline const asio::error_code* get_coroutine_error( - basic_stackless_context<Handler, Signature>& c) + stackless_context<Handler, Signature>& c) { return &(*c.impl_)->throw_ec_; } template <typename Handler, typename Signature> inline const asio::error_code* get_coroutine_error( - basic_stackless_context<Handler, Signature>* c) + stackless_context<Handler, Signature>* c) { return &(*c->impl_)->throw_ec_; } template <typename Handler, typename Signature> inline void** get_coroutine_async_result( - basic_stackless_context<Handler, Signature>& c) + stackless_context<Handler, Signature>& c) { return &(*c.impl_)->result_value_; } template <typename Handler, typename Signature> inline void** get_coroutine_async_result( - basic_stackless_context<Handler, Signature>* c) + stackless_context<Handler, Signature>* c) { return &(*c->impl_)->result_value_; } @@ -430,7 +431,7 @@ template <typename Handler, typename Signature> template <typename... T> -void basic_stackless_context<Handler, Signature>::complete(T&&... args) +void stackless_context<Handler, Signature>::complete(T&&... args) { if (!(*impl_)->completed_) { @@ -442,7 +443,7 @@ #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename Handler, typename Signature> -void basic_stackless_context<Handler, Signature>::complete() +void stackless_context<Handler, Signature>::complete() { if (!(*impl_)->completed_) { @@ -454,7 +455,7 @@ // A macro that should expand to: // template <typename Handler, typename Signature> // template <typename T1, ..., typename Tn> -// void basic_stackless_context<Handler, Signature>::complete( +// void stackless_context<Handler, Signature>::complete( // const T1& x1, ..., const Tn& xn) // { // if (!(*impl_)->completed_) @@ -468,7 +469,7 @@ # define ASIO_PRIVATE_COMPLETE_DEF(n) \ template <typename Handler, typename Signature> \ template <ASIO_VARIADIC_TPARAMS(n)> \ - void basic_stackless_context<Handler, Signature>::complete( \ + void stackless_context<Handler, Signature>::complete( \ ASIO_VARIADIC_CONSTREF_PARAMS(n)) \ { \ if (!(*impl_)->completed_) \ @@ -485,6 +486,18 @@ #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) +template <typename Function> +void go(ASIO_MOVE_ARG(Function) function) +{ + typedef typename remove_const< + typename remove_reference<Function>::type>::type + function_type; + + detail::go_helper<void, void(), function_type>( + &detail::default_go_handler, + ASIO_MOVE_CAST(Function)(function))(); +} + template <typename Handler, typename Function> ASIO_INITFN_RESULT_TYPE(Handler, void ()) go(ASIO_MOVE_ARG(Handler) handler, @@ -542,7 +555,7 @@ } template <typename Handler, typename Function> -void go(basic_stackless_context<Handler> ctx, +void go(stackless_context<Handler> ctx, ASIO_MOVE_ARG(Function) function) { Handler handler(ctx.handler_); @@ -554,16 +567,26 @@ void go(asio::io_service::strand strand, ASIO_MOVE_ARG(Function) function) { - asio::go(strand.wrap(&detail::default_go_handler), - ASIO_MOVE_CAST(Function)(function)); + typedef typename remove_const< + typename remove_reference<Function>::type>::type + function_type; + + detail::go_helper<asio::io_service::strand, void(), function_type>( + strand.wrap(&detail::default_go_handler), + ASIO_MOVE_CAST(Function)(function))(); } template <typename Function> void go(asio::io_service& io_service, ASIO_MOVE_ARG(Function) function) { - asio::go(asio::io_service::strand(io_service), - ASIO_MOVE_CAST(Function)(function)); + typedef typename remove_const< + typename remove_reference<Function>::type>::type + function_type; + + detail::go_helper<asio::io_service, void(), function_type>( + io_service.wrap(&detail::default_go_handler), + ASIO_MOVE_CAST(Function)(function))(); } #endif // !defined(GENERATING_DOCUMENTATION)
diff --git a/asio/src/examples/cpp11/go/echo_server.cpp b/asio/src/examples/cpp11/go/echo_server.cpp index d628aa3..2724683 100644 --- a/asio/src/examples/cpp11/go/echo_server.cpp +++ b/asio/src/examples/cpp11/go/echo_server.cpp
@@ -26,8 +26,7 @@ public: explicit session(tcp::socket socket) : socket_(std::move(socket)), - timer_(socket_.get_io_service()), - strand_(socket_.get_io_service()) + timer_(socket_.get_io_service()) { } @@ -38,8 +37,9 @@ std::size_t n = 0; std::array<char, 128> data; - asio::go(strand_, - [this, self, n, data](asio::stackless_context ctx) mutable + asio::go( + [this, self, n, data] + (asio::stackless_context<void> ctx) mutable { try { @@ -62,8 +62,9 @@ asio::error_code ignored_ec; - asio::go(strand_, - [this, self, ignored_ec](asio::stackless_context ctx) mutable + asio::go( + [this, self, ignored_ec] + (asio::stackless_context<void> ctx) mutable { reenter (ctx) { @@ -80,7 +81,6 @@ private: tcp::socket socket_; asio::steady_timer timer_; - asio::io_service::strand strand_; }; int main(int argc, char* argv[]) @@ -99,8 +99,8 @@ tcp::socket socket(io_service); asio::error_code ec; - asio::go(io_service, - [&](asio::stackless_context ctx) + asio::go( + [&](asio::stackless_context<void> ctx) { reenter (ctx) {