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
0003
0004
0005
0006
0007
0008
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
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
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
0176 atomic_count ref_count_;
0177
0178
0179 Handler handler_;
0180
0181
0182 Timer timer_;
0183
0184
0185 cancellation_signal cancellation_signal_;
0186 cancellation_type_t cancellation_type_;
0187
0188
0189 cancel_proxy* cancel_proxy_;
0190
0191
0192 union payload_storage
0193 {
0194 payload_storage() {}
0195 ~payload_storage() {}
0196
0197 char dummy_;
0198 payload_type payload_;
0199 } payload_storage_;
0200
0201
0202 bool has_payload_;
0203
0204
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
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
0307 Op* op_;
0308 };
0309
0310 }
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 }
0359 }
0360
0361 #include <boost/asio/detail/pop_options.hpp>
0362
0363 #endif