Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/asio/detail/timed_cancel_op.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //
0002 // detail/timed_cancel_op.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DETAIL_TIMED_CANCEL_OP_HPP
0012 #define BOOST_ASIO_DETAIL_TIMED_CANCEL_OP_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <boost/asio/associated_cancellation_slot.hpp>
0020 #include <boost/asio/associator.hpp>
0021 #include <boost/asio/basic_waitable_timer.hpp>
0022 #include <boost/asio/cancellation_signal.hpp>
0023 #include <boost/asio/detail/atomic_count.hpp>
0024 #include <boost/asio/detail/completion_payload.hpp>
0025 #include <boost/asio/detail/completion_payload_handler.hpp>
0026 #include <boost/asio/detail/handler_alloc_helpers.hpp>
0027 #include <boost/asio/detail/type_traits.hpp>
0028 
0029 #include <boost/asio/detail/push_options.hpp>
0030 
0031 namespace boost {
0032 namespace asio {
0033 namespace detail {
0034 
0035 template <typename Op, typename... Signatures>
0036 class timed_cancel_op_handler;
0037 
0038 template <typename Op>
0039 class timed_cancel_timer_handler;
0040 
0041 template <typename Handler, typename Timer, typename... Signatures>
0042 class timed_cancel_op
0043 {
0044 public:
0045   using handler_type = Handler;
0046 
0047   BOOST_ASIO_DEFINE_TAGGED_HANDLER_PTR(
0048       thread_info_base::timed_cancel_tag, timed_cancel_op);
0049 
0050   timed_cancel_op(Handler& handler, Timer timer,
0051       cancellation_type_t cancel_type)
0052     : ref_count_(2),
0053       handler_(static_cast<Handler&&>(handler)),
0054       timer_(static_cast<Timer&&>(timer)),
0055       cancellation_type_(cancel_type),
0056       cancel_proxy_(nullptr),
0057       has_payload_(false),
0058       has_pending_timer_wait_(true)
0059   {
0060   }
0061 
0062   ~timed_cancel_op()
0063   {
0064     if (has_payload_)
0065       payload_storage_.payload_.~payload_type();
0066   }
0067 
0068   cancellation_slot get_cancellation_slot() noexcept
0069   {
0070     return cancellation_signal_.slot();
0071   }
0072 
0073   template <typename Initiation, typename... Args>
0074   void start(Initiation&& initiation, Args&&... args)
0075   {
0076     using op_handler_type =
0077       timed_cancel_op_handler<timed_cancel_op, Signatures...>;
0078     op_handler_type op_handler(this);
0079 
0080     using timer_handler_type =
0081       timed_cancel_timer_handler<timed_cancel_op>;
0082     timer_handler_type timer_handler(this);
0083 
0084     associated_cancellation_slot_t<Handler> slot
0085       = (get_associated_cancellation_slot)(handler_);
0086     if (slot.is_connected())
0087       cancel_proxy_ = &slot.template emplace<cancel_proxy>(this);
0088 
0089     timer_.async_wait(static_cast<timer_handler_type&&>(timer_handler));
0090     async_initiate<op_handler_type, Signatures...>(
0091         static_cast<Initiation&&>(initiation),
0092         static_cast<op_handler_type&>(op_handler),
0093         static_cast<Args&&>(args)...);
0094   }
0095 
0096   template <typename Message>
0097   void handle_op(Message&& message)
0098   {
0099     if (cancel_proxy_)
0100       cancel_proxy_->op_ = nullptr;
0101 
0102     new (&payload_storage_.payload_) payload_type(
0103         static_cast<Message&&>(message));
0104     has_payload_ = true;
0105 
0106     if (has_pending_timer_wait_)
0107     {
0108       timer_.cancel();
0109       release();
0110     }
0111     else
0112     {
0113       complete();
0114     }
0115   }
0116 
0117   void handle_timer()
0118   {
0119     has_pending_timer_wait_ = false;
0120 
0121     if (has_payload_)
0122     {
0123       complete();
0124     }
0125     else
0126     {
0127       cancellation_signal_.emit(cancellation_type_);
0128       release();
0129     }
0130   }
0131 
0132   void release()
0133   {
0134     if (--ref_count_ == 0)
0135     {
0136       ptr p = { boost::asio::detail::addressof(handler_), this, this };
0137       Handler handler(static_cast<Handler&&>(handler_));
0138       p.h = boost::asio::detail::addressof(handler);
0139       p.reset();
0140     }
0141   }
0142 
0143   void complete()
0144   {
0145     if (--ref_count_ == 0)
0146     {
0147       ptr p = { boost::asio::detail::addressof(handler_), this, this };
0148       completion_payload_handler<payload_type, Handler> handler(
0149           static_cast<payload_type&&>(payload_storage_.payload_), handler_);
0150       p.h = boost::asio::detail::addressof(handler.handler());
0151       p.reset();
0152       handler();
0153     }
0154   }
0155 
0156 //private:
0157   typedef completion_payload<Signatures...> payload_type;
0158 
0159   struct cancel_proxy
0160   {
0161     cancel_proxy(timed_cancel_op* op)
0162       : op_(op)
0163     {
0164     }
0165 
0166     void operator()(cancellation_type_t type)
0167     {
0168       if (op_)
0169         op_->cancellation_signal_.emit(type);
0170     }
0171 
0172     timed_cancel_op* op_;
0173   };
0174 
0175   // The number of handlers that share a reference to the state.
0176   atomic_count ref_count_;
0177 
0178   // The handler to be called when the operation completes.
0179   Handler handler_;
0180 
0181   // The timer used to determine when to cancel the pending operation.
0182   Timer timer_;
0183 
0184   // The cancellation signal and type used to cancel the pending operation.
0185   cancellation_signal cancellation_signal_;
0186   cancellation_type_t cancellation_type_;
0187 
0188   // A proxy cancel handler used to allow cancellation of the timed operation.
0189   cancel_proxy* cancel_proxy_;
0190 
0191   // Arguments to be passed to the completion handler.
0192   union payload_storage
0193   {
0194     payload_storage() {}
0195     ~payload_storage() {}
0196 
0197     char dummy_;
0198     payload_type payload_;
0199   } payload_storage_;
0200 
0201   // Whether the payload storage contains a valid payload.
0202   bool has_payload_;
0203 
0204   // Whether the asynchronous wait on the timer is still pending
0205   bool has_pending_timer_wait_;
0206 };
0207 
0208 template <typename Op, typename R, typename... Args>
0209 class timed_cancel_op_handler<Op, R(Args...)>
0210 {
0211 public:
0212   using cancellation_slot_type = cancellation_slot;
0213 
0214   explicit timed_cancel_op_handler(Op* op)
0215     : op_(op)
0216   {
0217   }
0218 
0219   timed_cancel_op_handler(timed_cancel_op_handler&& other) noexcept
0220     : op_(other.op_)
0221   {
0222     other.op_ = nullptr;
0223   }
0224 
0225   ~timed_cancel_op_handler()
0226   {
0227     if (op_)
0228       op_->release();
0229   }
0230 
0231   cancellation_slot_type get_cancellation_slot() const noexcept
0232   {
0233     return op_->get_cancellation_slot();
0234   }
0235 
0236   template <typename... Args2>
0237   enable_if_t<
0238     is_constructible<completion_message<R(Args...)>, int, Args2...>::value
0239   > operator()(Args2&&... args)
0240   {
0241     Op* op = op_;
0242     op_ = nullptr;
0243     typedef completion_message<R(Args...)> message_type;
0244     op->handle_op(message_type(0, static_cast<Args2&&>(args)...));
0245   }
0246 
0247 //protected:
0248   Op* op_;
0249 };
0250 
0251 template <typename Op, typename R, typename... Args, typename... Signatures>
0252 class timed_cancel_op_handler<Op, R(Args...), Signatures...> :
0253   public timed_cancel_op_handler<Op, Signatures...>
0254 {
0255 public:
0256   using timed_cancel_op_handler<Op, Signatures...>::timed_cancel_op_handler;
0257   using timed_cancel_op_handler<Op, Signatures...>::operator();
0258 
0259   template <typename... Args2>
0260   enable_if_t<
0261     is_constructible<completion_message<R(Args...)>, int, Args2...>::value
0262   > operator()(Args2&&... args)
0263   {
0264     Op* op = this->op_;
0265     this->op_ = nullptr;
0266     typedef completion_message<R(Args...)> message_type;
0267     op->handle_op(message_type(0, static_cast<Args2&&>(args)...));
0268   }
0269 };
0270 
0271 template <typename Op>
0272 class timed_cancel_timer_handler
0273 {
0274 public:
0275   using cancellation_slot_type = cancellation_slot;
0276 
0277   explicit timed_cancel_timer_handler(Op* op)
0278     : op_(op)
0279   {
0280   }
0281 
0282   timed_cancel_timer_handler(timed_cancel_timer_handler&& other) noexcept
0283     : op_(other.op_)
0284   {
0285     other.op_ = nullptr;
0286   }
0287 
0288   ~timed_cancel_timer_handler()
0289   {
0290     if (op_)
0291       op_->release();
0292   }
0293 
0294   cancellation_slot_type get_cancellation_slot() const noexcept
0295   {
0296     return cancellation_slot_type();
0297   }
0298 
0299   void operator()(const boost::system::error_code&)
0300   {
0301     Op* op = op_;
0302     op_ = nullptr;
0303     op->handle_timer();
0304   }
0305 
0306 //private:
0307   Op* op_;
0308 };
0309 
0310 } // namespace detail
0311 
0312 template <template <typename, typename> class Associator,
0313     typename Op, typename... Signatures, typename DefaultCandidate>
0314 struct associator<Associator,
0315     detail::timed_cancel_op_handler<Op, Signatures...>, DefaultCandidate>
0316   : Associator<typename Op::handler_type, DefaultCandidate>
0317 {
0318   static typename Associator<typename Op::handler_type, DefaultCandidate>::type
0319   get(const detail::timed_cancel_op_handler<Op, Signatures...>& h) noexcept
0320   {
0321     return Associator<typename Op::handler_type, DefaultCandidate>::get(
0322         h.op_->handler_);
0323   }
0324 
0325   static auto get(const detail::timed_cancel_op_handler<Op, Signatures...>& h,
0326       const DefaultCandidate& c) noexcept
0327     -> decltype(Associator<typename Op::handler_type, DefaultCandidate>::get(
0328         h.op_->handler_, c))
0329   {
0330     return Associator<typename Op::handler_type, DefaultCandidate>::get(
0331         h.op_->handler_, c);
0332   }
0333 };
0334 
0335 template <template <typename, typename> class Associator,
0336     typename Op, typename DefaultCandidate>
0337 struct associator<Associator,
0338     detail::timed_cancel_timer_handler<Op>, DefaultCandidate>
0339   : Associator<typename Op::handler_type, DefaultCandidate>
0340 {
0341   static typename Associator<typename Op::handler_type, DefaultCandidate>::type
0342   get(const detail::timed_cancel_timer_handler<Op>& h) noexcept
0343   {
0344     return Associator<typename Op::handler_type, DefaultCandidate>::get(
0345         h.op_->handler_);
0346   }
0347 
0348   static auto get(const detail::timed_cancel_timer_handler<Op>& h,
0349       const DefaultCandidate& c) noexcept
0350     -> decltype(Associator<typename Op::handler_type, DefaultCandidate>::get(
0351         h.op_->handler_, c))
0352   {
0353     return Associator<typename Op::handler_type, DefaultCandidate>::get(
0354         h.op_->handler_, c);
0355   }
0356 };
0357 
0358 } // namespace asio
0359 } // namespace boost
0360 
0361 #include <boost/asio/detail/pop_options.hpp>
0362 
0363 #endif // BOOST_ASIO_DETAIL_TIMED_CANCEL_OP_HPP