%PDF- %PDF-
Direktori : /backups/router/usr/local/include/boost/asio/detail/ |
Current File : //backups/router/usr/local/include/boost/asio/detail/timed_cancel_op.hpp |
// // detail/timed_cancel_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_ASIO_DETAIL_TIMED_CANCEL_OP_HPP #define BOOST_ASIO_DETAIL_TIMED_CANCEL_OP_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <boost/asio/detail/config.hpp> #include <boost/asio/associated_cancellation_slot.hpp> #include <boost/asio/associator.hpp> #include <boost/asio/basic_waitable_timer.hpp> #include <boost/asio/cancellation_signal.hpp> #include <boost/asio/detail/atomic_count.hpp> #include <boost/asio/detail/completion_payload.hpp> #include <boost/asio/detail/completion_payload_handler.hpp> #include <boost/asio/detail/handler_alloc_helpers.hpp> #include <boost/asio/detail/type_traits.hpp> #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { namespace detail { template <typename Op, typename... Signatures> class timed_cancel_op_handler; template <typename Op> class timed_cancel_timer_handler; template <typename Handler, typename Timer, typename... Signatures> class timed_cancel_op { public: using handler_type = Handler; BOOST_ASIO_DEFINE_TAGGED_HANDLER_PTR( thread_info_base::timed_cancel_tag, timed_cancel_op); timed_cancel_op(Handler& handler, Timer timer, cancellation_type_t cancel_type) : ref_count_(2), handler_(static_cast<Handler&&>(handler)), timer_(static_cast<Timer&&>(timer)), cancellation_type_(cancel_type), cancel_proxy_(nullptr), has_payload_(false), has_pending_timer_wait_(true) { } ~timed_cancel_op() { if (has_payload_) payload_storage_.payload_.~payload_type(); } cancellation_slot get_cancellation_slot() noexcept { return cancellation_signal_.slot(); } template <typename Initiation, typename... Args> void start(Initiation&& initiation, Args&&... args) { using op_handler_type = timed_cancel_op_handler<timed_cancel_op, Signatures...>; op_handler_type op_handler(this); using timer_handler_type = timed_cancel_timer_handler<timed_cancel_op>; timer_handler_type timer_handler(this); associated_cancellation_slot_t<Handler> slot = (get_associated_cancellation_slot)(handler_); if (slot.is_connected()) cancel_proxy_ = &slot.template emplace<cancel_proxy>(this); timer_.async_wait(static_cast<timer_handler_type&&>(timer_handler)); async_initiate<op_handler_type, Signatures...>( static_cast<Initiation&&>(initiation), static_cast<op_handler_type&>(op_handler), static_cast<Args&&>(args)...); } template <typename Message> void handle_op(Message&& message) { if (cancel_proxy_) cancel_proxy_->op_ = nullptr; new (&payload_storage_.payload_) payload_type( static_cast<Message&&>(message)); has_payload_ = true; if (has_pending_timer_wait_) { timer_.cancel(); release(); } else { complete(); } } void handle_timer() { has_pending_timer_wait_ = false; if (has_payload_) { complete(); } else { cancellation_signal_.emit(cancellation_type_); release(); } } void release() { if (--ref_count_ == 0) { ptr p = { boost::asio::detail::addressof(handler_), this, this }; Handler handler(static_cast<Handler&&>(handler_)); p.h = boost::asio::detail::addressof(handler); p.reset(); } } void complete() { if (--ref_count_ == 0) { ptr p = { boost::asio::detail::addressof(handler_), this, this }; completion_payload_handler<payload_type, Handler> handler( static_cast<payload_type&&>(payload_storage_.payload_), handler_); p.h = boost::asio::detail::addressof(handler.handler()); p.reset(); handler(); } } //private: typedef completion_payload<Signatures...> payload_type; struct cancel_proxy { cancel_proxy(timed_cancel_op* op) : op_(op) { } void operator()(cancellation_type_t type) { if (op_) op_->cancellation_signal_.emit(type); } timed_cancel_op* op_; }; // The number of handlers that share a reference to the state. atomic_count ref_count_; // The handler to be called when the operation completes. Handler handler_; // The timer used to determine when to cancel the pending operation. Timer timer_; // The cancellation signal and type used to cancel the pending operation. cancellation_signal cancellation_signal_; cancellation_type_t cancellation_type_; // A proxy cancel handler used to allow cancellation of the timed operation. cancel_proxy* cancel_proxy_; // Arguments to be passed to the completion handler. union payload_storage { payload_storage() {} ~payload_storage() {} char dummy_; payload_type payload_; } payload_storage_; // Whether the payload storage contains a valid payload. bool has_payload_; // Whether the asynchronous wait on the timer is still pending bool has_pending_timer_wait_; }; template <typename Op, typename R, typename... Args> class timed_cancel_op_handler<Op, R(Args...)> { public: using cancellation_slot_type = cancellation_slot; explicit timed_cancel_op_handler(Op* op) : op_(op) { } timed_cancel_op_handler(timed_cancel_op_handler&& other) noexcept : op_(other.op_) { other.op_ = nullptr; } ~timed_cancel_op_handler() { if (op_) op_->release(); } cancellation_slot_type get_cancellation_slot() const noexcept { return op_->get_cancellation_slot(); } template <typename... Args2> enable_if_t< is_constructible<completion_message<R(Args...)>, int, Args2...>::value > operator()(Args2&&... args) { Op* op = op_; op_ = nullptr; typedef completion_message<R(Args...)> message_type; op->handle_op(message_type(0, static_cast<Args2&&>(args)...)); } //protected: Op* op_; }; template <typename Op, typename R, typename... Args, typename... Signatures> class timed_cancel_op_handler<Op, R(Args...), Signatures...> : public timed_cancel_op_handler<Op, Signatures...> { public: using timed_cancel_op_handler<Op, Signatures...>::timed_cancel_op_handler; using timed_cancel_op_handler<Op, Signatures...>::operator(); template <typename... Args2> enable_if_t< is_constructible<completion_message<R(Args...)>, int, Args2...>::value > operator()(Args2&&... args) { Op* op = this->op_; this->op_ = nullptr; typedef completion_message<R(Args...)> message_type; op->handle_op(message_type(0, static_cast<Args2&&>(args)...)); } }; template <typename Op> class timed_cancel_timer_handler { public: using cancellation_slot_type = cancellation_slot; explicit timed_cancel_timer_handler(Op* op) : op_(op) { } timed_cancel_timer_handler(timed_cancel_timer_handler&& other) noexcept : op_(other.op_) { other.op_ = nullptr; } ~timed_cancel_timer_handler() { if (op_) op_->release(); } cancellation_slot_type get_cancellation_slot() const noexcept { return cancellation_slot_type(); } void operator()(const boost::system::error_code&) { Op* op = op_; op_ = nullptr; op->handle_timer(); } //private: Op* op_; }; } // namespace detail template <template <typename, typename> class Associator, typename Op, typename... Signatures, typename DefaultCandidate> struct associator<Associator, detail::timed_cancel_op_handler<Op, Signatures...>, DefaultCandidate> : Associator<typename Op::handler_type, DefaultCandidate> { static typename Associator<typename Op::handler_type, DefaultCandidate>::type get(const detail::timed_cancel_op_handler<Op, Signatures...>& h) noexcept { return Associator<typename Op::handler_type, DefaultCandidate>::get( h.op_->handler_); } static auto get(const detail::timed_cancel_op_handler<Op, Signatures...>& h, const DefaultCandidate& c) noexcept -> decltype(Associator<typename Op::handler_type, DefaultCandidate>::get( h.op_->handler_, c)) { return Associator<typename Op::handler_type, DefaultCandidate>::get( h.op_->handler_, c); } }; template <template <typename, typename> class Associator, typename Op, typename DefaultCandidate> struct associator<Associator, detail::timed_cancel_timer_handler<Op>, DefaultCandidate> : Associator<typename Op::handler_type, DefaultCandidate> { static typename Associator<typename Op::handler_type, DefaultCandidate>::type get(const detail::timed_cancel_timer_handler<Op>& h) noexcept { return Associator<typename Op::handler_type, DefaultCandidate>::get( h.op_->handler_); } static auto get(const detail::timed_cancel_timer_handler<Op>& h, const DefaultCandidate& c) noexcept -> decltype(Associator<typename Op::handler_type, DefaultCandidate>::get( h.op_->handler_, c)) { return Associator<typename Op::handler_type, DefaultCandidate>::get( h.op_->handler_, c); } }; } // namespace asio } // namespace boost #include <boost/asio/detail/pop_options.hpp> #endif // BOOST_ASIO_DETAIL_TIMED_CANCEL_OP_HPP