mirror of
https://github.com/boostorg/mqtt5.git
synced 2026-01-19 04:22:11 +00:00
Summary: related to T15996 - docs are now buildable with b2 (in a very simplified way) like mysql docs - change Async.MQTT5 -> Boost.MQTT5, async_mqtt5 namespace to boost::mqtt5 namespace - once changes are approved, Ill update all tabs to 4 spaces in .qbk files Reviewers: ivica Reviewed By: ivica Subscribers: iljazovic, miljen Differential Revision: https://repo.mireo.local/D33373
96 lines
5.8 KiB
Plaintext
96 lines
5.8 KiB
Plaintext
[/
|
|
Copyright (c) 2023-2024 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
|
Distributed under the Boost Software License, Version 1.0.
|
|
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
]
|
|
|
|
[section:per_op_cancellation Per-Operation Cancellation]
|
|
[nochunk]
|
|
|
|
In __Asio__, various objects such as sockets and timers offer the ability to terminate all ongoing asynchronous operations
|
|
globally through their `close` or `cancel` member functions.
|
|
Beyond this global cancellation capability, __Asio__ also provides mechanisms for cancelling specific asynchronous
|
|
operations on an individual basis.
|
|
This individual per-operation cancellation is enabled by specifying that a completion handler has an associated cancellation slot.
|
|
If the asynchronous operation supports cancellation, then it will install a cancellation handler into the associated slot.
|
|
The cancellation handler will be invoked when the user emits a cancellation signal into the cancellation slot.
|
|
See __ASIO_PER_OP_CANCELLATION__ for more information.
|
|
|
|
The utility of per-operation cancellation becomes particularly evident when using `boost::asio::experimental::parallel_group` to launch
|
|
work performed in parallel and wait for one or all of the operations to complete.
|
|
For instance, in a parallel group awaiting the completion of any one operation among several,
|
|
completing one operation will trigger individual cancellation of all the remaining operations.
|
|
The same concept applies to the `awaitable operator ||`, which runs two awaitables in parallel,
|
|
waiting for one to complete and subsequently cancelling the remaining one.
|
|
See __ASIO_PARALLEL_GROUP__ for more information.
|
|
|
|
Within the __Client__, every asynchronous function is designed to support individual per-operation cancellation.
|
|
This allows for associating of a cancellation slot with any `async_xxx` function call, enabling the emission of a cancellation signal as needed.
|
|
The impact of emitting a cancellation signal varies depending on the signal type (terminal, total, partial) and the operation being cancelled.
|
|
Detailed descriptions of how cancellation signals affect each `async_xxx` function
|
|
are provided in the ['Per-Operation Cancellation] paragraph in their respective sections of the __Client__ reference documentation.
|
|
|
|
[heading Example: associating a cancellation slot with an asynchronous operation]
|
|
|
|
This example illustrates associating a cancellation slot with a [refmem mqtt_client async_publish] operation
|
|
and emitting a terminal cancellation signal.
|
|
Executing this sequence effectively results in the immediate cancellation of the entire client operation,
|
|
mirroring the outcome of invoking [refmem mqtt_client cancel] directly.
|
|
|
|
If a total or partial cancellation signal were issued instead of a terminal one, the implications would be less severe.
|
|
In such cases, the cancellation would specifically target resending the __PUBLISH__ packet,
|
|
preventing it from being retransmitted should the client reconnect during the ongoing operation.
|
|
|
|
```
|
|
boost::mqtt5::mqtt_client<boost::asio::ip::tcp::socket> client(ioc);
|
|
|
|
client.brokers("<your-mqtt-broker>", 1883)
|
|
.async_run(boost::asio::detached);
|
|
|
|
boost::asio::cancellation_signal signal;
|
|
|
|
client.async_publish<boost::mqtt5::qos_e::at_least_once>(
|
|
"<topic>", "Hello world!",
|
|
boost::mqtt5::retain_e::no, boost::mqtt5::publish_props {},
|
|
boost::asio::bind_cancellation_slot(
|
|
signal.slot(),
|
|
[&client](boost::mqtt5::error_code ec, boost::mqtt5::reason_code rc, boost::mqtt5::puback_props props ) {
|
|
std::cout << ec.message() << std::endl;
|
|
}
|
|
)
|
|
);
|
|
|
|
signal.emit(boost::asio::cancellation_type_t::terminal);
|
|
```
|
|
|
|
[section:parallel_group parallel_group/operator || and asynchronous functions in the mqtt_client]
|
|
As a result of supporting per-operation cancellation,
|
|
all the asynchronous functions with the __Client__ can be used in `parallel_group` or with `awaitable operator ||`.
|
|
This feature is especially beneficial for executing operations that require a timeout mechanism.
|
|
|
|
Below are two examples illustrating how to implement a timeout:
|
|
|
|
* [link mqtt5.timeout_with_parallel_group timeout_with_parallel_group.cpp]
|
|
* [link mqtt5.timeout_with_awaitable_operators timeout_with_awaitable_operators.cpp]
|
|
|
|
[endsect] [/parallel_group]
|
|
|
|
[section:protocol_level_cancellation About protocol-level cancellation]
|
|
In the context of __Client__, the handling of cancellation signals varies across different asynchronous operations.
|
|
Except for [refmem mqtt_client async_receive], all other `async_xxx` operations respond to a terminal cancellation signal by invoking [refmem mqtt_client cancel].
|
|
These operations will halt the resending of certain packets for total and partial cancellation signals.
|
|
|
|
It is worth noting that cancelling an `async_xxx` operation during an ongoing protocol exchange is not implemented because of a design decision
|
|
to prevent protocol breaches.
|
|
For example, if [refmem mqtt_client async_publish] with QoS 2 is in the middle of a communication with the Broker
|
|
[footnote Publishing with QoS 2 involves sending a __PUBLISH__ packet, receiving a __PUBREC__ acknowledgement from the Broker, transmitting a __PUBREL__ packet, and finally receiving a __PUBCOMP__ packet.]
|
|
and an attempt to cancel it is made, it could lead to a protocol violation.
|
|
For instance, if the operation is cancelled after a __PUBREC__ packet has been received from the Broker but before sending the __PUBREL__ packet,
|
|
that would breach the MQTT protocol by failing to send a necessary packet and leave the connection with the Broker in an invalid state.
|
|
|
|
Therefore, the design of __Client__'s cancellation strategy carefully avoids these pitfalls to ensure continuous protocol compliance.
|
|
|
|
[endsect] [/protocol_level_cancellation]
|
|
|
|
[endsect] [/per_op_cancellation]
|