File indexing completed on 2025-09-17 08:38:19
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MQTT5_CANCELLABLE_HANDLER_HPP
0009 #define BOOST_MQTT5_CANCELLABLE_HANDLER_HPP
0010
0011 #include <boost/mqtt5/detail/async_traits.hpp>
0012
0013 #include <boost/asio/associated_allocator.hpp>
0014 #include <boost/asio/associated_cancellation_slot.hpp>
0015 #include <boost/asio/associated_executor.hpp>
0016 #include <boost/asio/associated_immediate_executor.hpp>
0017 #include <boost/asio/cancellation_state.hpp>
0018 #include <boost/asio/dispatch.hpp>
0019 #include <boost/asio/prepend.hpp>
0020
0021 namespace boost::mqtt5::detail {
0022
0023 template <typename Handler, typename Executor>
0024 class cancellable_handler {
0025 Executor _executor;
0026 Handler _handler;
0027 tracking_type<Handler, Executor> _handler_ex;
0028 asio::cancellation_state _cancellation_state;
0029
0030 public:
0031 cancellable_handler(Handler&& handler, const Executor& ex) :
0032 _executor(ex),
0033 _handler(std::move(handler)),
0034 _handler_ex(tracking_executor(_handler, ex)),
0035 _cancellation_state(
0036 asio::get_associated_cancellation_slot(_handler),
0037 asio::enable_total_cancellation {},
0038 asio::enable_terminal_cancellation {}
0039 )
0040 {}
0041
0042 cancellable_handler(cancellable_handler&&) = default;
0043 cancellable_handler(const cancellable_handler&) = delete;
0044
0045 cancellable_handler& operator=(cancellable_handler&&) = default;
0046 cancellable_handler& operator=(const cancellable_handler&) = delete;
0047
0048 using allocator_type = asio::associated_allocator_t<Handler>;
0049 allocator_type get_allocator() const noexcept {
0050 return asio::get_associated_allocator(_handler);
0051 }
0052
0053 using cancellation_slot_type = asio::associated_cancellation_slot_t<Handler>;
0054 cancellation_slot_type get_cancellation_slot() const noexcept {
0055 return _cancellation_state.slot();
0056 }
0057
0058 using executor_type = tracking_type<Handler, Executor>;
0059 executor_type get_executor() const noexcept {
0060 return _handler_ex;
0061 }
0062
0063 using immediate_executor_type =
0064 asio::associated_immediate_executor_t<Handler, Executor>;
0065 immediate_executor_type get_immediate_executor() const noexcept {
0066
0067
0068 return asio::get_associated_immediate_executor(_handler, _executor);
0069 }
0070
0071 asio::cancellation_type_t cancelled() const {
0072 return _cancellation_state.cancelled();
0073 }
0074
0075 template <typename... Args>
0076 void complete(Args&&... args) {
0077 asio::get_associated_cancellation_slot(_handler).clear();
0078 asio::dispatch(
0079 _handler_ex,
0080 asio::prepend(std::move(_handler), std::forward<Args>(args)...)
0081 );
0082 }
0083
0084 template <typename... Args>
0085 void complete_immediate(Args&&... args) {
0086 asio::get_associated_cancellation_slot(_handler).clear();
0087 auto ex = get_immediate_executor();
0088 asio::dispatch(
0089 ex,
0090 asio::prepend(std::move(_handler), std::forward<Args>(args)...)
0091 );
0092 }
0093
0094 };
0095
0096 }
0097
0098 #endif