forked from boostorg/mqtt5
use associated executors for intermediate handlers
Summary: * per-operation cancellation changed: total/partial signals only prevent further resending, terminal signal cancels the whole client Reviewers: ivica Reviewed By: ivica Subscribers: korina Differential Revision: https://repo.mireo.local/D27246
This commit is contained in:
1 parent
1996251253
commit
d78fdd3208
21 files changed
+311
-414
No files matched your search
@@ -39,8 +39,7 @@ public:
|
||||
CompletionToken&& token
|
||||
) {
|
||||
auto initiation = [this](auto handler) {
|
||||
auto ex = asio::get_associated_executor(handler, _ex);
|
||||
asio::post(ex,
|
||||
asio::post(_ex,
|
||||
asio::prepend(std::move(handler), error_code {})
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,7 +15,8 @@ namespace async_mqtt5::test {
|
||||
|
||||
enum cancel_type {
|
||||
ioc_stop = 1,
|
||||
client_cancel
|
||||
client_cancel,
|
||||
signal_emit
|
||||
};
|
||||
|
||||
} // end namespace async_mqtt5::test
|
||||
@@ -34,27 +35,42 @@ void cancel_async_receive() {
|
||||
using client_type = mqtt_client<stream_type>;
|
||||
client_type c(ioc, "");
|
||||
|
||||
c.brokers("mqtt.mireo.local", 1883)
|
||||
c.brokers("127.0.0.1", 1883)
|
||||
.credentials("test-cli", "", "")
|
||||
.run();
|
||||
|
||||
auto handler = [&handlers_called](
|
||||
error_code ec, std::string, std::string, publish_props
|
||||
) {
|
||||
BOOST_CHECK_EQUAL(ec, asio::error::operation_aborted);
|
||||
handlers_called++;
|
||||
};
|
||||
|
||||
std::vector<asio::cancellation_signal> signals(3);
|
||||
|
||||
for (auto i = 0; i < num_handlers; ++i)
|
||||
c.async_receive([&handlers_called](
|
||||
error_code ec, std::string, std::string, publish_props
|
||||
) {
|
||||
BOOST_CHECK_EQUAL(ec, asio::error::operation_aborted);
|
||||
handlers_called++;
|
||||
});
|
||||
c.async_receive(asio::bind_cancellation_slot(
|
||||
signals[i].slot(),
|
||||
std::move(handler)
|
||||
));
|
||||
|
||||
asio::steady_timer timer(c.get_executor());
|
||||
timer.expires_after(std::chrono::seconds(1));
|
||||
timer.expires_after(std::chrono::milliseconds(10));
|
||||
timer.async_wait([&](auto) {
|
||||
if constexpr (type == ioc_stop)
|
||||
ioc.stop();
|
||||
else
|
||||
else if constexpr (type == client_cancel)
|
||||
c.cancel();
|
||||
else if constexpr (type == signal_emit)
|
||||
std::for_each(
|
||||
signals.begin(), signals.end(),
|
||||
[](auto& signal) {
|
||||
signal.emit(asio::cancellation_type_t::terminal);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
ioc.run();
|
||||
ioc.run_for(std::chrono::milliseconds(20));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
}
|
||||
|
||||
@@ -71,87 +87,68 @@ void cancel_async_publish() {
|
||||
using client_type = mqtt_client<stream_type>;
|
||||
client_type c(ioc, "");
|
||||
|
||||
c.brokers("mqtt.mireo.local", 1883)
|
||||
c.brokers("127.0.0.1", 1883)
|
||||
.credentials("test-cli", "", "")
|
||||
.run();
|
||||
|
||||
std::vector<asio::cancellation_signal> signals(3);
|
||||
|
||||
c.async_publish<qos_e::at_most_once>(
|
||||
"topic", "payload", retain_e::yes, {},
|
||||
[&handlers_called](error_code ec) {
|
||||
BOOST_CHECK_EQUAL(ec, asio::error::operation_aborted);
|
||||
handlers_called++;
|
||||
}
|
||||
asio::bind_cancellation_slot(
|
||||
signals[0].slot(),
|
||||
[&handlers_called](error_code ec) {
|
||||
BOOST_CHECK_EQUAL(ec, asio::error::operation_aborted);
|
||||
handlers_called++;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
c.async_publish<qos_e::at_least_once>(
|
||||
"topic", "payload", retain_e::yes, {},
|
||||
[&handlers_called](error_code ec, reason_code rc, puback_props) {
|
||||
BOOST_CHECK_EQUAL(ec, asio::error::operation_aborted);
|
||||
BOOST_CHECK_EQUAL(rc, reason_codes::empty);
|
||||
handlers_called++;
|
||||
}
|
||||
asio::bind_cancellation_slot(
|
||||
signals[1].slot(),
|
||||
[&handlers_called](error_code ec, reason_code rc, puback_props) {
|
||||
BOOST_CHECK_EQUAL(ec, asio::error::operation_aborted);
|
||||
BOOST_CHECK_EQUAL(rc, reason_codes::empty);
|
||||
handlers_called++;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
c.async_publish<qos_e::exactly_once>(
|
||||
"topic", "payload", retain_e::yes, {},
|
||||
[&handlers_called](error_code ec, reason_code rc, pubcomp_props) {
|
||||
BOOST_CHECK_EQUAL(ec, asio::error::operation_aborted);
|
||||
BOOST_CHECK_EQUAL(rc, reason_codes::empty);
|
||||
handlers_called++;
|
||||
}
|
||||
asio::bind_cancellation_slot(
|
||||
signals[2].slot(),
|
||||
[&handlers_called](error_code ec, reason_code rc, pubcomp_props) {
|
||||
BOOST_CHECK_EQUAL(ec, asio::error::operation_aborted);
|
||||
BOOST_CHECK_EQUAL(rc, reason_codes::empty);
|
||||
handlers_called++;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
asio::steady_timer timer(c.get_executor());
|
||||
timer.expires_after(std::chrono::seconds(1));
|
||||
timer.expires_after(std::chrono::milliseconds(10));
|
||||
timer.async_wait([&](auto) {
|
||||
if constexpr (type == ioc_stop)
|
||||
ioc.stop();
|
||||
else
|
||||
else if constexpr (type == client_cancel)
|
||||
c.cancel();
|
||||
else if constexpr (type == signal_emit)
|
||||
std::for_each(
|
||||
signals.begin(), signals.end(),
|
||||
[](auto& signal) {
|
||||
signal.emit(asio::cancellation_type_t::terminal);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
ioc.run();
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
}
|
||||
|
||||
template <test::cancel_type type>
|
||||
void cancel_during_connecting() {
|
||||
using namespace test;
|
||||
|
||||
constexpr int expected_handlers_called = type == ioc_stop ? 0 : 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
asio::io_context ioc;
|
||||
|
||||
using stream_type = asio::ip::tcp::socket;
|
||||
using client_type = mqtt_client<stream_type>;
|
||||
client_type c(ioc, "");
|
||||
|
||||
c.brokers("127.0.0.1", 1883)
|
||||
.run();
|
||||
|
||||
c.async_publish<qos_e::at_most_once>(
|
||||
"topic", "payload", retain_e::yes, {},
|
||||
[&handlers_called](error_code ec) {
|
||||
BOOST_CHECK_EQUAL(ec, asio::error::operation_aborted);
|
||||
handlers_called++;
|
||||
}
|
||||
);
|
||||
|
||||
asio::steady_timer timer(c.get_executor());
|
||||
timer.expires_after(std::chrono::seconds(2));
|
||||
timer.async_wait([&](auto) {
|
||||
if constexpr (type == ioc_stop)
|
||||
ioc.stop();
|
||||
else
|
||||
c.cancel();
|
||||
});
|
||||
|
||||
ioc.run();
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(cancellation/*, *boost::unit_test::disabled()*/)
|
||||
|
||||
|
||||
@@ -159,11 +156,14 @@ BOOST_AUTO_TEST_CASE(ioc_stop_async_receive) {
|
||||
cancel_async_receive<test::cancel_type::ioc_stop>();
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(client_cancel_async_receive) {
|
||||
cancel_async_receive<test::cancel_type::client_cancel>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(signal_emit_async_receive) {
|
||||
cancel_async_receive<test::cancel_type::signal_emit>();
|
||||
}
|
||||
|
||||
// passes on debian, hangs on windows in io_context destructor
|
||||
BOOST_AUTO_TEST_CASE(ioc_stop_async_publish, *boost::unit_test::disabled() ) {
|
||||
cancel_async_publish<test::cancel_type::ioc_stop>();
|
||||
@@ -173,13 +173,8 @@ BOOST_AUTO_TEST_CASE(client_cancel_async_publish) {
|
||||
cancel_async_publish<test::cancel_type::client_cancel>();
|
||||
}
|
||||
|
||||
// passes on debian, hangs on windows
|
||||
BOOST_AUTO_TEST_CASE(ioc_stop_cancel_during_connecting, *boost::unit_test::disabled() ) {
|
||||
cancel_during_connecting<test::cancel_type::ioc_stop>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(client_cancel_during_connecting) {
|
||||
cancel_during_connecting<test::cancel_type::client_cancel>();
|
||||
BOOST_AUTO_TEST_CASE(signal_emit_async_publish) {
|
||||
cancel_async_publish<test::cancel_type::signal_emit>();
|
||||
}
|
||||
|
||||
#ifdef BOOST_ASIO_HAS_CO_AWAIT
|
||||
|
||||
@@ -260,35 +260,6 @@ BOOST_AUTO_TEST_CASE(test_topic_alias_maximum) {
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_publish_immediate_cancellation) {
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
asio::io_context ioc;
|
||||
using client_service_type = test::test_service<asio::ip::tcp::socket>;
|
||||
auto svc_ptr = std::make_shared<client_service_type>(ioc.get_executor());
|
||||
asio::cancellation_signal cancel_signal;
|
||||
|
||||
auto h = [&handlers_called](error_code ec, reason_code rc, puback_props) {
|
||||
++handlers_called;
|
||||
BOOST_CHECK(ec == asio::error::operation_aborted);
|
||||
BOOST_CHECK_EQUAL(rc, reason_codes::empty);
|
||||
};
|
||||
|
||||
auto handler = asio::bind_cancellation_slot(cancel_signal.slot(), std::move(h));
|
||||
|
||||
detail::publish_send_op<
|
||||
client_service_type, decltype(handler), qos_e::at_least_once
|
||||
> { svc_ptr, std::move(handler) }
|
||||
.perform(
|
||||
"test", "payload", retain_e::no, {}
|
||||
);
|
||||
|
||||
cancel_signal.emit(asio::cancellation_type::terminal);
|
||||
ioc.run();
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_publish_cancellation) {
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
@@ -27,6 +27,7 @@ BOOST_AUTO_TEST_CASE(clear_waiting_on_pubrel) {
|
||||
asio::io_context ioc;
|
||||
using client_service_type = test::test_service<asio::ip::tcp::socket>;
|
||||
auto svc_ptr = std::make_shared<client_service_type>(ioc.get_executor());
|
||||
svc_ptr->open_stream();
|
||||
|
||||
decoders::publish_message pub_msg = std::make_tuple(
|
||||
"topic", int16_t(1), uint8_t(0b0100), publish_props {}, "payload"
|
||||
|
||||
Reference in new issue
Block a user