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
* Add experimental test/handler.hpp
* 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__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__handler">test::handler</link>&nbsp;<emphasis role="green">&#128946;</emphasis></member>
<member><link linkend="beast.ref.boost__beast__test__stream">test::stream</link></member>
</simplelist>
</entry>
@ -364,6 +365,9 @@
<bridgehead renderas="sect3">Functions</bridgehead>
<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__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>
</entry>
<entry valign="top">

View File

@ -19,8 +19,17 @@ namespace boost {
namespace beast {
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
{
boost::optional<error_code> ec_;
@ -61,6 +70,14 @@ public:
pass_ = true;
}
void
operator()()
{
BEAST_EXPECT(! pass_); // can't call twice
BEAST_EXPECT(! ec_);
pass_ = true;
}
template<class Arg0, class... Args,
class = typename std::enable_if<
! std::is_convertible<Arg0, error_code>::value>::type>
@ -73,8 +90,6 @@ public:
}
};
} // detail
/** Return a test CompletionHandler which requires success.
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.
*/
inline
#if BOOST_BEAST_DOXYGEN
__implementation_defined__
#else
detail::handler
#endif
handler
success_handler() noexcept
{
return detail::handler(error_code{});
return handler(error_code{});
}
/** Return a test CompletionHandler which requires invocation.
@ -104,14 +115,10 @@ success_handler() noexcept
@li The handler is destroyed without being invoked.
*/
inline
#if BOOST_BEAST_DOXYGEN
__implementation_defined__
#else
detail::handler
#endif
handler
any_handler() noexcept
{
return detail::handler(boost::none);
return handler(boost::none);
}
/** Return a test CompletionHandler which requires a specific error code.
@ -127,14 +134,10 @@ any_handler() noexcept
@param ec The error code to specify.
*/
inline
#if BOOST_BEAST_DOXYGEN
__implementation_defined__
#else
detail::handler
#endif
handler
fail_handler(error_code ec) noexcept
{
return detail::handler(ec);
return handler(ec);
}
} // test

View File

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

View File

@ -11,14 +11,17 @@
#define BOOST_BEAST_CORE_ASYNC_OP_BASE_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/async_op_base.hpp>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/handler_alloc_hook.hpp>
#include <boost/asio/handler_continuation_hook.hpp>
#include <boost/asio/handler_invoke_hook.hpp>
#include <boost/asio/post.hpp>
#include <boost/core/exchange.hpp>
#include <boost/core/empty_value.hpp>
#include <utility>
@ -314,15 +317,54 @@ public:
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
arguments forwarded. It is undefined to call this member
function more than once.
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 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>
void

View File

@ -110,7 +110,7 @@ public:
@par Example
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
template <class SyncReadStream>
std::size_t read_line (SyncReadStream& stream, flat_buffer& buffer)

View File

@ -38,10 +38,10 @@ namespace http {
fields.
The parser is optimized for the case where the input buffer
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
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.
Alternatively, the caller may use custom techniques to ensure that
the structured portion of the HTTP message (header or chunk header)

View File

@ -13,6 +13,7 @@
#include "test_handler.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/core/error.hpp>
#include <boost/asio/async_result.hpp>
@ -419,13 +420,28 @@ public:
// invocation
{
bool invoked = false;
net::io_context ioc;
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(
final_handler{invoked}, {});
op.invoke();
BEAST_EXPECT(invoked);
test::any_handler(), {});
op.invoke_now();
}
// legacy hooks
@ -478,13 +494,28 @@ public:
// invocation
{
bool invoked = false;
net::io_context ioc;
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(
final_handler{invoked}, {});
op.invoke();
BEAST_EXPECT(invoked);
test::any_handler(), {});
op.invoke_now();
}
// legacy hooks

View File

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