Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:38:19

0001 //
0002 // Copyright (c) 2023-2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
0003 //
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
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         // get_associated_immediate_executor will require asio::execution::blocking.never
0067         // on the default executor.
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 } // end boost::mqtt5::detail
0097 
0098 #endif // !BOOST_MQTT5_CANCELLABLE_HANDLER_HPP