Files

124 lines
3.7 KiB
C++
Raw Permalink Normal View History

2024-05-27 10:35:06 +02:00
//
2025-02-14 13:42:23 +01:00
// Copyright (c) 2023-2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
2024-05-27 10:35:06 +02:00
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
2025-01-13 16:11:41 +01:00
#ifndef BOOST_MQTT5_TEST_DELAYED_OP_HPP
#define BOOST_MQTT5_TEST_DELAYED_OP_HPP
#include <boost/asio/append.hpp>
#include <boost/asio/bind_cancellation_slot.hpp>
2023-10-06 11:51:04 +02:00
#include <boost/asio/cancellation_signal.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/asio/prepend.hpp>
#include <boost/asio/recycling_allocator.hpp>
#include <boost/asio/steady_timer.hpp>
2023-12-07 15:41:31 +01:00
#include <boost/type_traits/remove_cv_ref.hpp>
2025-01-13 16:11:41 +01:00
#include <chrono>
namespace boost::mqtt5::test {
namespace asio = boost::asio;
using error_code = boost::system::error_code;
using time_stamp = std::chrono::time_point<std::chrono::steady_clock>;
using duration = time_stamp::duration;
template <typename ...BoundArgs>
class delayed_op {
2025-01-13 16:11:41 +01:00
struct on_timer {};
2025-01-13 16:11:41 +01:00
std::unique_ptr<asio::steady_timer> _timer;
time_stamp::duration _delay;
asio::cancellation_slot _cancel_slot;
2025-01-13 16:11:41 +01:00
std::tuple<BoundArgs...> _args;
public:
2025-01-13 16:11:41 +01:00
template <typename Executor, typename ...Args>
delayed_op(
const Executor& ex, time_stamp::duration delay, Args&& ...args
) :
_timer(new asio::steady_timer(ex)), _delay(delay),
_args(std::move(args)...)
{}
2025-01-13 16:11:41 +01:00
delayed_op(delayed_op&&) = default;
delayed_op(const delayed_op&) = delete;
2025-01-13 16:11:41 +01:00
delayed_op& operator=(delayed_op&&) = default;
delayed_op& operator=(const delayed_op&) = delete;
2025-01-13 16:11:41 +01:00
using allocator_type = asio::recycling_allocator<void>;
allocator_type get_allocator() const noexcept {
return allocator_type {};
}
2025-01-13 16:11:41 +01:00
using cancellation_slot_type = asio::cancellation_slot;
asio::cancellation_slot get_cancellation_slot() const noexcept {
return _cancel_slot;
}
2025-01-13 16:11:41 +01:00
using executor_type = asio::steady_timer::executor_type;
executor_type get_executor() const noexcept {
return _timer->get_executor();
}
2024-08-08 09:55:45 +02:00
2025-01-13 16:11:41 +01:00
template <typename CompletionHandler>
void perform(CompletionHandler&& handler) {
_cancel_slot = asio::get_associated_cancellation_slot(handler);
2025-01-13 16:11:41 +01:00
_timer->expires_after(_delay);
_timer->async_wait(
asio::prepend(std::move(*this), on_timer {}, std::move(handler))
);
}
2025-01-13 16:11:41 +01:00
template <typename CompletionHandler>
void operator()(on_timer, CompletionHandler&& h, error_code ec) {
// The timer places a handler into the cancellation slot
// and does not clear it. Therefore, we need to clear it explicitly
// to properly remove the corresponding cancellation signal
// in the test_broker.
get_cancellation_slot().clear();
2025-01-13 16:11:41 +01:00
auto bh = std::apply(
[h = std::move(h)](auto&&... args) mutable {
return asio::append(std::move(h), std::move(args)...);
},
_args
);
2025-01-13 16:11:41 +01:00
asio::dispatch(asio::prepend(std::move(bh), ec));
}
};
template <typename CompletionToken, typename ...BoundArgs>
decltype(auto) async_delay(
2025-01-13 16:11:41 +01:00
asio::cancellation_slot cancel_slot,
delayed_op<BoundArgs...>&& op,
CompletionToken&& token
) {
2025-01-13 16:11:41 +01:00
using Signature = void (error_code, boost::remove_cv_ref_t<BoundArgs>...);
2025-01-13 16:11:41 +01:00
auto initiation = [](
auto handler, asio::cancellation_slot cancel_slot,
delayed_op<BoundArgs...> op
) {
op.perform(
asio::bind_cancellation_slot(cancel_slot, std::move(handler))
);
};
2025-01-13 16:11:41 +01:00
return asio::async_initiate<CompletionToken, Signature>(
std::move(initiation), token, cancel_slot, std::move(op)
);
}
2025-01-13 16:11:41 +01:00
} // end namespace boost::mqtt5::test
2025-01-13 16:11:41 +01:00
#endif // BOOST_MQTT5_TEST_DELAYED_OP_HPP