Add async_op_base::invoke

This commit is contained in:
Vinnie Falco
2019-02-15 15:16:51 -08:00
parent fdaf2ea7e1
commit f41363c60c
9 changed files with 122 additions and 41 deletions

View File

@ -6,6 +6,7 @@ Version 215:
* Examples use bind_front_handler * Examples use bind_front_handler
* Add experimental test/handler.hpp * Add experimental test/handler.hpp
* Rename to async_op_base::invoke_now * Rename to async_op_base::invoke_now
* Add async_op_base::invoke
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@ -357,6 +357,7 @@
<member><link linkend="beast.ref.boost__beast__ssl_stream">ssl_stream</link></member> <member><link linkend="beast.ref.boost__beast__ssl_stream">ssl_stream</link></member>
<member><link linkend="beast.ref.boost__beast__http__icy_stream">http::icy_stream</link></member> <member><link linkend="beast.ref.boost__beast__http__icy_stream">http::icy_stream</link></member>
<member><link linkend="beast.ref.boost__beast__test__fail_count">test::fail_count</link></member> <member><link linkend="beast.ref.boost__beast__test__fail_count">test::fail_count</link></member>
<member><link linkend="beast.ref.boost__beast__test__handler">test::handler</link>&nbsp;<emphasis role="green">&#128946;</emphasis></member>
<member><link linkend="beast.ref.boost__beast__test__stream">test::stream</link></member> <member><link linkend="beast.ref.boost__beast__test__stream">test::stream</link></member>
</simplelist> </simplelist>
</entry> </entry>
@ -364,6 +365,9 @@
<bridgehead renderas="sect3">Functions</bridgehead> <bridgehead renderas="sect3">Functions</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="beast.ref.boost__beast__test__connect">test::connect</link></member> <member><link linkend="beast.ref.boost__beast__test__connect">test::connect</link></member>
<member><link linkend="beast.ref.boost__beast__test__any_handler">test::any_handler</link>&nbsp;<emphasis role="green">&#128946;</emphasis></member>
<member><link linkend="beast.ref.boost__beast__test__fail_handler">test::fail_handler</link>&nbsp;<emphasis role="green">&#128946;</emphasis></member>
<member><link linkend="beast.ref.boost__beast__test__success_handler">test::success_handler</link>&nbsp;<emphasis role="green">&#128946;</emphasis></member>
</simplelist> </simplelist>
</entry> </entry>
<entry valign="top"> <entry valign="top">

View File

@ -19,8 +19,17 @@ namespace boost {
namespace beast { namespace beast {
namespace test { namespace test {
namespace detail { /** A CompletionHandler used for testing.
This completion handler is used by tests to ensure correctness
of behavior. It is designed as a single type to reduce template
instantiations, with configurable settings through constructor
arguments. Typically this type will be used in type lists and
not instantiated directly; instances of this class are returned
by the helper functions listed below.
@see @ref success_handler, @ref fail_handler, @ref any_handler
*/
class handler class handler
{ {
boost::optional<error_code> ec_; boost::optional<error_code> ec_;
@ -61,6 +70,14 @@ public:
pass_ = true; pass_ = true;
} }
void
operator()()
{
BEAST_EXPECT(! pass_); // can't call twice
BEAST_EXPECT(! ec_);
pass_ = true;
}
template<class Arg0, class... Args, template<class Arg0, class... Args,
class = typename std::enable_if< class = typename std::enable_if<
! std::is_convertible<Arg0, error_code>::value>::type> ! std::is_convertible<Arg0, error_code>::value>::type>
@ -73,8 +90,6 @@ public:
} }
}; };
} // detail
/** Return a test CompletionHandler which requires success. /** Return a test CompletionHandler which requires success.
The returned handler can be invoked with any signature whose The returned handler can be invoked with any signature whose
@ -86,14 +101,10 @@ public:
@li The handler is invoked with a non-successful error code. @li The handler is invoked with a non-successful error code.
*/ */
inline inline
#if BOOST_BEAST_DOXYGEN handler
__implementation_defined__
#else
detail::handler
#endif
success_handler() noexcept success_handler() noexcept
{ {
return detail::handler(error_code{}); return handler(error_code{});
} }
/** Return a test CompletionHandler which requires invocation. /** Return a test CompletionHandler which requires invocation.
@ -104,14 +115,10 @@ success_handler() noexcept
@li The handler is destroyed without being invoked. @li The handler is destroyed without being invoked.
*/ */
inline inline
#if BOOST_BEAST_DOXYGEN handler
__implementation_defined__
#else
detail::handler
#endif
any_handler() noexcept any_handler() noexcept
{ {
return detail::handler(boost::none); return handler(boost::none);
} }
/** Return a test CompletionHandler which requires a specific error code. /** Return a test CompletionHandler which requires a specific error code.
@ -127,14 +134,10 @@ any_handler() noexcept
@param ec The error code to specify. @param ec The error code to specify.
*/ */
inline inline
#if BOOST_BEAST_DOXYGEN handler
__implementation_defined__
#else
detail::handler
#endif
fail_handler(error_code ec) noexcept fail_handler(error_code ec) noexcept
{ {
return detail::handler(ec); return handler(ec);
} }
} // test } // test

View File

@ -61,8 +61,8 @@ namespace test {
To facilitate testing, these streams support some additional To facilitate testing, these streams support some additional
features: features:
@li The input area, represented by a @ref flat_buffer, may @li The input area, represented by a @ref basic_flat_buffer,
be directly accessed by the caller to inspect the contents may be directly accessed by the caller to inspect the contents
before or after the remote endpoint writes data. This allows before or after the remote endpoint writes data. This allows
a unit test to verify that the received data matches. a unit test to verify that the received data matches.

View File

@ -11,14 +11,17 @@
#define BOOST_BEAST_CORE_ASYNC_OP_BASE_HPP #define BOOST_BEAST_CORE_ASYNC_OP_BASE_HPP
#include <boost/beast/core/detail/config.hpp> #include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/detail/allocator.hpp> #include <boost/beast/core/detail/allocator.hpp>
#include <boost/beast/core/detail/async_op_base.hpp> #include <boost/beast/core/detail/async_op_base.hpp>
#include <boost/asio/associated_allocator.hpp> #include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp> #include <boost/asio/associated_executor.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/executor_work_guard.hpp> #include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/handler_alloc_hook.hpp> #include <boost/asio/handler_alloc_hook.hpp>
#include <boost/asio/handler_continuation_hook.hpp> #include <boost/asio/handler_continuation_hook.hpp>
#include <boost/asio/handler_invoke_hook.hpp> #include <boost/asio/handler_invoke_hook.hpp>
#include <boost/asio/post.hpp>
#include <boost/core/exchange.hpp> #include <boost/core/exchange.hpp>
#include <boost/core/empty_value.hpp> #include <boost/core/empty_value.hpp>
#include <utility> #include <utility>
@ -314,15 +317,54 @@ public:
return std::move(h_); return std::move(h_);
} }
/** Invoke the final completion handler. /** Invoke the final completion handler, maybe using post.
This invokes the final completion handler with the specified This invokes the final completion handler with the specified
arguments forwarded. It is undefined to call this member arguments forwarded. It is undefined to call either of
function more than once. @ref invoke or @ref invoke_now more than once.
Any temporary objects allocated with @ref allocate_stable will Any temporary objects allocated with @ref allocate_stable will
be automatically destroyed before the final completion handler be automatically destroyed before the final completion handler
is invoked. is invoked.
@param is_continuation If this value is `false`, then the
handler will be submitted to the executor using `net::post`.
Otherwise the handler will be invoked as if by calling
@ref invoke_now.
@param args A list of optional parameters to invoke the handler
with. The completion handler must be invocable with the parameter
list, or else a compilation error will result.
*/
template<class... Args>
void
invoke(bool is_continuation, Args&&... args)
{
this->before_invoke_hook();
wg1_.reset();
if(! is_continuation)
net::post(net::bind_executor(
wg1_.get_executor(),
beast::bind_front_handler(
std::move(h_),
std::forward<Args>(args)...)));
else
h_(std::forward<Args>(args)...);
}
/** Invoke the final completion handler.
This invokes the final completion handler with the specified
arguments forwarded. It is undefined to call either of
@ref invoke or @ref invoke_now more than once.
Any temporary objects allocated with @ref allocate_stable will
be automatically destroyed before the final completion handler
is invoked.
@param args A list of optional parameters to invoke the handler
with. The completion handler must be invocable with the parameter
list, or else a compilation error will result.
*/ */
template<class... Args> template<class... Args>
void void

View File

@ -110,7 +110,7 @@ public:
@par Example @par Example
This function reads a line of text from a stream into a This function reads a line of text from a stream into a
@ref flat_buffer, using the net function `async_read_until`. The @ref basic_flat_buffer, using the net function `async_read_until`.
@code @code
template <class SyncReadStream> template <class SyncReadStream>
std::size_t read_line (SyncReadStream& stream, flat_buffer& buffer) std::size_t read_line (SyncReadStream& stream, flat_buffer& buffer)

View File

@ -38,10 +38,10 @@ namespace http {
fields. fields.
The parser is optimized for the case where the input buffer The parser is optimized for the case where the input buffer
sequence consists of a single contiguous buffer. The sequence consists of a single contiguous buffer. The
@ref flat_buffer class is provided, which guarantees @ref basic_flat_buffer class is provided, which guarantees
that the input sequence of the stream buffer will be represented that the input sequence of the stream buffer will be represented
by exactly one contiguous buffer. To ensure the optimum performance by exactly one contiguous buffer. To ensure the optimum performance
of the parser, use @ref flat_buffer with HTTP algorithms of the parser, use @ref basic_flat_buffer with HTTP algorithms
such as @ref read, @ref read_some, @ref async_read, and @ref async_read_some. such as @ref read, @ref read_some, @ref async_read, and @ref async_read_some.
Alternatively, the caller may use custom techniques to ensure that Alternatively, the caller may use custom techniques to ensure that
the structured portion of the HTTP message (header or chunk header) the structured portion of the HTTP message (header or chunk header)

View File

@ -13,6 +13,7 @@
#include "test_handler.hpp" #include "test_handler.hpp"
#include <boost/beast/_experimental/unit_test/suite.hpp> #include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/beast/_experimental/test/handler.hpp>
#include <boost/beast/_experimental/test/stream.hpp> #include <boost/beast/_experimental/test/stream.hpp>
#include <boost/beast/core/error.hpp> #include <boost/beast/core/error.hpp>
#include <boost/asio/async_result.hpp> #include <boost/asio/async_result.hpp>
@ -419,13 +420,28 @@ public:
// invocation // invocation
{ {
bool invoked = false; net::io_context ioc;
async_op_base< async_op_base<
final_handler, test::handler,
net::io_context::executor_type> op(
test::any_handler(), ioc.get_executor());
op.invoke(true);
}
{
net::io_context ioc;
async_op_base<
test::handler,
net::io_context::executor_type> op(
test::any_handler(), ioc.get_executor());
op.invoke(false);
ioc.run();
}
{
async_op_base<
test::handler,
simple_executor> op( simple_executor> op(
final_handler{invoked}, {}); test::any_handler(), {});
op.invoke(); op.invoke_now();
BEAST_EXPECT(invoked);
} }
// legacy hooks // legacy hooks
@ -478,13 +494,28 @@ public:
// invocation // invocation
{ {
bool invoked = false; net::io_context ioc;
stable_async_op_base< stable_async_op_base<
final_handler, test::handler,
net::io_context::executor_type> op(
test::any_handler(), ioc.get_executor());
op.invoke(true);
}
{
net::io_context ioc;
stable_async_op_base<
test::handler,
net::io_context::executor_type> op(
test::any_handler(), ioc.get_executor());
op.invoke(false);
ioc.run();
}
{
stable_async_op_base<
test::handler,
simple_executor> op( simple_executor> op(
final_handler{invoked}, {}); test::any_handler(), {});
op.invoke(); op.invoke_now();
BEAST_EXPECT(invoked);
} }
// legacy hooks // legacy hooks

View File

@ -7,8 +7,8 @@
// Official repository: https://github.com/boostorg/beast // Official repository: https://github.com/boostorg/beast
// //
#ifndef BOOST_BEAST_TEST_HANDLER_HPP #ifndef BOOST_BEAST_TEST_HANDLER_XXX_HPP
#define BOOST_BEAST_TEST_HANDLER_HPP #define BOOST_BEAST_TEST_HANDLER_XXX_HPP
#include <boost/beast/core/detail/config.hpp> #include <boost/beast/core/detail/config.hpp>
#include <boost/beast/_experimental/unit_test/suite.hpp> #include <boost/beast/_experimental/unit_test/suite.hpp>