File indexing completed on 2025-01-18 09:28:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
0012 #define BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019
0020 #if defined(BOOST_ASIO_HAS_IOCP)
0021
0022 #include <cstring>
0023 #include <boost/asio/error.hpp>
0024 #include <boost/asio/execution_context.hpp>
0025 #include <boost/asio/socket_base.hpp>
0026 #include <boost/asio/detail/bind_handler.hpp>
0027 #include <boost/asio/detail/buffer_sequence_adapter.hpp>
0028 #include <boost/asio/detail/fenced_block.hpp>
0029 #include <boost/asio/detail/handler_alloc_helpers.hpp>
0030 #include <boost/asio/detail/memory.hpp>
0031 #include <boost/asio/detail/mutex.hpp>
0032 #include <boost/asio/detail/operation.hpp>
0033 #include <boost/asio/detail/reactor_op.hpp>
0034 #include <boost/asio/detail/select_reactor.hpp>
0035 #include <boost/asio/detail/socket_holder.hpp>
0036 #include <boost/asio/detail/socket_ops.hpp>
0037 #include <boost/asio/detail/socket_types.hpp>
0038 #include <boost/asio/detail/win_iocp_io_context.hpp>
0039 #include <boost/asio/detail/win_iocp_null_buffers_op.hpp>
0040 #include <boost/asio/detail/win_iocp_socket_accept_op.hpp>
0041 #include <boost/asio/detail/win_iocp_socket_connect_op.hpp>
0042 #include <boost/asio/detail/win_iocp_socket_recvfrom_op.hpp>
0043 #include <boost/asio/detail/win_iocp_socket_send_op.hpp>
0044 #include <boost/asio/detail/win_iocp_socket_service_base.hpp>
0045
0046 #include <boost/asio/detail/push_options.hpp>
0047
0048 namespace boost {
0049 namespace asio {
0050 namespace detail {
0051
0052 template <typename Protocol>
0053 class win_iocp_socket_service :
0054 public execution_context_service_base<win_iocp_socket_service<Protocol>>,
0055 public win_iocp_socket_service_base
0056 {
0057 public:
0058
0059 typedef Protocol protocol_type;
0060
0061
0062 typedef typename Protocol::endpoint endpoint_type;
0063
0064
0065 class native_handle_type
0066 {
0067 public:
0068 native_handle_type(socket_type s)
0069 : socket_(s),
0070 have_remote_endpoint_(false)
0071 {
0072 }
0073
0074 native_handle_type(socket_type s, const endpoint_type& ep)
0075 : socket_(s),
0076 have_remote_endpoint_(true),
0077 remote_endpoint_(ep)
0078 {
0079 }
0080
0081 void operator=(socket_type s)
0082 {
0083 socket_ = s;
0084 have_remote_endpoint_ = false;
0085 remote_endpoint_ = endpoint_type();
0086 }
0087
0088 operator socket_type() const
0089 {
0090 return socket_;
0091 }
0092
0093 bool have_remote_endpoint() const
0094 {
0095 return have_remote_endpoint_;
0096 }
0097
0098 endpoint_type remote_endpoint() const
0099 {
0100 return remote_endpoint_;
0101 }
0102
0103 private:
0104 socket_type socket_;
0105 bool have_remote_endpoint_;
0106 endpoint_type remote_endpoint_;
0107 };
0108
0109
0110 struct implementation_type :
0111 win_iocp_socket_service_base::base_implementation_type
0112 {
0113
0114 implementation_type()
0115 : protocol_(endpoint_type().protocol()),
0116 have_remote_endpoint_(false),
0117 remote_endpoint_()
0118 {
0119 }
0120
0121
0122 protocol_type protocol_;
0123
0124
0125 bool have_remote_endpoint_;
0126
0127
0128 endpoint_type remote_endpoint_;
0129 };
0130
0131
0132 win_iocp_socket_service(execution_context& context)
0133 : execution_context_service_base<
0134 win_iocp_socket_service<Protocol>>(context),
0135 win_iocp_socket_service_base(context)
0136 {
0137 }
0138
0139
0140 void shutdown()
0141 {
0142 this->base_shutdown();
0143 }
0144
0145
0146 void move_construct(implementation_type& impl,
0147 implementation_type& other_impl) noexcept
0148 {
0149 this->base_move_construct(impl, other_impl);
0150
0151 impl.protocol_ = other_impl.protocol_;
0152 other_impl.protocol_ = endpoint_type().protocol();
0153
0154 impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;
0155 other_impl.have_remote_endpoint_ = false;
0156
0157 impl.remote_endpoint_ = other_impl.remote_endpoint_;
0158 other_impl.remote_endpoint_ = endpoint_type();
0159 }
0160
0161
0162 void move_assign(implementation_type& impl,
0163 win_iocp_socket_service_base& other_service,
0164 implementation_type& other_impl)
0165 {
0166 this->base_move_assign(impl, other_service, other_impl);
0167
0168 impl.protocol_ = other_impl.protocol_;
0169 other_impl.protocol_ = endpoint_type().protocol();
0170
0171 impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;
0172 other_impl.have_remote_endpoint_ = false;
0173
0174 impl.remote_endpoint_ = other_impl.remote_endpoint_;
0175 other_impl.remote_endpoint_ = endpoint_type();
0176 }
0177
0178
0179 template <typename Protocol1>
0180 void converting_move_construct(implementation_type& impl,
0181 win_iocp_socket_service<Protocol1>&,
0182 typename win_iocp_socket_service<
0183 Protocol1>::implementation_type& other_impl)
0184 {
0185 this->base_move_construct(impl, other_impl);
0186
0187 impl.protocol_ = protocol_type(other_impl.protocol_);
0188 other_impl.protocol_ = typename Protocol1::endpoint().protocol();
0189
0190 impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;
0191 other_impl.have_remote_endpoint_ = false;
0192
0193 impl.remote_endpoint_ = other_impl.remote_endpoint_;
0194 other_impl.remote_endpoint_ = typename Protocol1::endpoint();
0195 }
0196
0197
0198 boost::system::error_code open(implementation_type& impl,
0199 const protocol_type& protocol, boost::system::error_code& ec)
0200 {
0201 if (!do_open(impl, protocol.family(),
0202 protocol.type(), protocol.protocol(), ec))
0203 {
0204 impl.protocol_ = protocol;
0205 impl.have_remote_endpoint_ = false;
0206 impl.remote_endpoint_ = endpoint_type();
0207 }
0208
0209 BOOST_ASIO_ERROR_LOCATION(ec);
0210 return ec;
0211 }
0212
0213
0214 boost::system::error_code assign(implementation_type& impl,
0215 const protocol_type& protocol, const native_handle_type& native_socket,
0216 boost::system::error_code& ec)
0217 {
0218 if (!do_assign(impl, protocol.type(), native_socket, ec))
0219 {
0220 impl.protocol_ = protocol;
0221 impl.have_remote_endpoint_ = native_socket.have_remote_endpoint();
0222 impl.remote_endpoint_ = native_socket.remote_endpoint();
0223 }
0224
0225 BOOST_ASIO_ERROR_LOCATION(ec);
0226 return ec;
0227 }
0228
0229
0230 native_handle_type native_handle(implementation_type& impl)
0231 {
0232 if (impl.have_remote_endpoint_)
0233 return native_handle_type(impl.socket_, impl.remote_endpoint_);
0234 return native_handle_type(impl.socket_);
0235 }
0236
0237
0238 boost::system::error_code bind(implementation_type& impl,
0239 const endpoint_type& endpoint, boost::system::error_code& ec)
0240 {
0241 socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
0242
0243 BOOST_ASIO_ERROR_LOCATION(ec);
0244 return ec;
0245 }
0246
0247
0248 template <typename Option>
0249 boost::system::error_code set_option(implementation_type& impl,
0250 const Option& option, boost::system::error_code& ec)
0251 {
0252 socket_ops::setsockopt(impl.socket_, impl.state_,
0253 option.level(impl.protocol_), option.name(impl.protocol_),
0254 option.data(impl.protocol_), option.size(impl.protocol_), ec);
0255
0256 BOOST_ASIO_ERROR_LOCATION(ec);
0257 return ec;
0258 }
0259
0260
0261 template <typename Option>
0262 boost::system::error_code get_option(const implementation_type& impl,
0263 Option& option, boost::system::error_code& ec) const
0264 {
0265 std::size_t size = option.size(impl.protocol_);
0266 socket_ops::getsockopt(impl.socket_, impl.state_,
0267 option.level(impl.protocol_), option.name(impl.protocol_),
0268 option.data(impl.protocol_), &size, ec);
0269 if (!ec)
0270 option.resize(impl.protocol_, size);
0271
0272 BOOST_ASIO_ERROR_LOCATION(ec);
0273 return ec;
0274 }
0275
0276
0277 endpoint_type local_endpoint(const implementation_type& impl,
0278 boost::system::error_code& ec) const
0279 {
0280 endpoint_type endpoint;
0281 std::size_t addr_len = endpoint.capacity();
0282 if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
0283 {
0284 BOOST_ASIO_ERROR_LOCATION(ec);
0285 return endpoint_type();
0286 }
0287 endpoint.resize(addr_len);
0288 return endpoint;
0289 }
0290
0291
0292 endpoint_type remote_endpoint(const implementation_type& impl,
0293 boost::system::error_code& ec) const
0294 {
0295 endpoint_type endpoint = impl.remote_endpoint_;
0296 std::size_t addr_len = endpoint.capacity();
0297 if (socket_ops::getpeername(impl.socket_, endpoint.data(),
0298 &addr_len, impl.have_remote_endpoint_, ec))
0299 {
0300 BOOST_ASIO_ERROR_LOCATION(ec);
0301 return endpoint_type();
0302 }
0303 endpoint.resize(addr_len);
0304 return endpoint;
0305 }
0306
0307
0308 boost::system::error_code shutdown(base_implementation_type& impl,
0309 socket_base::shutdown_type what, boost::system::error_code& ec)
0310 {
0311 socket_ops::shutdown(impl.socket_, what, ec);
0312 return ec;
0313 }
0314
0315
0316
0317 template <typename ConstBufferSequence>
0318 size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
0319 const endpoint_type& destination, socket_base::message_flags flags,
0320 boost::system::error_code& ec)
0321 {
0322 buffer_sequence_adapter<boost::asio::const_buffer,
0323 ConstBufferSequence> bufs(buffers);
0324
0325 size_t n = socket_ops::sync_sendto(impl.socket_,
0326 impl.state_, bufs.buffers(), bufs.count(), flags,
0327 destination.data(), destination.size(), ec);
0328
0329 BOOST_ASIO_ERROR_LOCATION(ec);
0330 return n;
0331 }
0332
0333
0334 size_t send_to(implementation_type& impl, const null_buffers&,
0335 const endpoint_type&, socket_base::message_flags,
0336 boost::system::error_code& ec)
0337 {
0338
0339 socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
0340 BOOST_ASIO_ERROR_LOCATION(ec);
0341 return 0;
0342 }
0343
0344
0345
0346 template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
0347 void async_send_to(implementation_type& impl,
0348 const ConstBufferSequence& buffers, const endpoint_type& destination,
0349 socket_base::message_flags flags, Handler& handler,
0350 const IoExecutor& io_ex)
0351 {
0352 associated_cancellation_slot_t<Handler> slot
0353 = boost::asio::get_associated_cancellation_slot(handler);
0354
0355
0356 typedef win_iocp_socket_send_op<
0357 ConstBufferSequence, Handler, IoExecutor> op;
0358 typename op::ptr p = { boost::asio::detail::addressof(handler),
0359 op::ptr::allocate(handler), 0 };
0360 operation* o = p.p = new (p.v) op(
0361 impl.cancel_token_, buffers, handler, io_ex);
0362
0363 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0364 &impl, impl.socket_, "async_send_to"));
0365
0366 buffer_sequence_adapter<boost::asio::const_buffer,
0367 ConstBufferSequence> bufs(buffers);
0368
0369
0370 if (slot.is_connected())
0371 o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);
0372
0373 start_send_to_op(impl, bufs.buffers(), bufs.count(),
0374 destination.data(), static_cast<int>(destination.size()),
0375 flags, o);
0376 p.v = p.p = 0;
0377 }
0378
0379
0380 template <typename Handler, typename IoExecutor>
0381 void async_send_to(implementation_type& impl, const null_buffers&,
0382 const endpoint_type&, socket_base::message_flags, Handler& handler,
0383 const IoExecutor& io_ex)
0384 {
0385
0386 typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
0387 typename op::ptr p = { boost::asio::detail::addressof(handler),
0388 op::ptr::allocate(handler), 0 };
0389 reactor_op* o = p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
0390
0391 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0392 &impl, impl.socket_, "async_send_to(null_buffers)"));
0393
0394 start_reactor_op(impl, select_reactor::write_op, o);
0395 p.v = p.p = 0;
0396 }
0397
0398
0399
0400 template <typename MutableBufferSequence>
0401 size_t receive_from(implementation_type& impl,
0402 const MutableBufferSequence& buffers,
0403 endpoint_type& sender_endpoint, socket_base::message_flags flags,
0404 boost::system::error_code& ec)
0405 {
0406 buffer_sequence_adapter<boost::asio::mutable_buffer,
0407 MutableBufferSequence> bufs(buffers);
0408
0409 std::size_t addr_len = sender_endpoint.capacity();
0410 std::size_t n = socket_ops::sync_recvfrom(impl.socket_,
0411 impl.state_, bufs.buffers(), bufs.count(), flags,
0412 sender_endpoint.data(), &addr_len, ec);
0413
0414 if (!ec)
0415 sender_endpoint.resize(addr_len);
0416
0417 BOOST_ASIO_ERROR_LOCATION(ec);
0418 return n;
0419 }
0420
0421
0422 size_t receive_from(implementation_type& impl,
0423 const null_buffers&, endpoint_type& sender_endpoint,
0424 socket_base::message_flags, boost::system::error_code& ec)
0425 {
0426
0427 socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
0428
0429
0430 sender_endpoint = endpoint_type();
0431
0432 BOOST_ASIO_ERROR_LOCATION(ec);
0433 return 0;
0434 }
0435
0436
0437
0438
0439 template <typename MutableBufferSequence,
0440 typename Handler, typename IoExecutor>
0441 void async_receive_from(implementation_type& impl,
0442 const MutableBufferSequence& buffers, endpoint_type& sender_endp,
0443 socket_base::message_flags flags, Handler& handler,
0444 const IoExecutor& io_ex)
0445 {
0446 associated_cancellation_slot_t<Handler> slot
0447 = boost::asio::get_associated_cancellation_slot(handler);
0448
0449
0450 typedef win_iocp_socket_recvfrom_op<MutableBufferSequence,
0451 endpoint_type, Handler, IoExecutor> op;
0452 typename op::ptr p = { boost::asio::detail::addressof(handler),
0453 op::ptr::allocate(handler), 0 };
0454 operation* o = p.p = new (p.v) op(sender_endp,
0455 impl.cancel_token_, buffers, handler, io_ex);
0456
0457 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0458 &impl, impl.socket_, "async_receive_from"));
0459
0460 buffer_sequence_adapter<boost::asio::mutable_buffer,
0461 MutableBufferSequence> bufs(buffers);
0462
0463
0464 if (slot.is_connected())
0465 o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);
0466
0467 start_receive_from_op(impl, bufs.buffers(), bufs.count(),
0468 sender_endp.data(), flags, &p.p->endpoint_size(), o);
0469 p.v = p.p = 0;
0470 }
0471
0472
0473 template <typename Handler, typename IoExecutor>
0474 void async_receive_from(implementation_type& impl, const null_buffers&,
0475 endpoint_type& sender_endpoint, socket_base::message_flags flags,
0476 Handler& handler, const IoExecutor& io_ex)
0477 {
0478 associated_cancellation_slot_t<Handler> slot
0479 = boost::asio::get_associated_cancellation_slot(handler);
0480
0481
0482 typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
0483 typename op::ptr p = { boost::asio::detail::addressof(handler),
0484 op::ptr::allocate(handler), 0 };
0485 p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
0486
0487 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0488 &impl, impl.socket_, "async_receive_from(null_buffers)"));
0489
0490
0491 sender_endpoint = endpoint_type();
0492
0493
0494 operation* iocp_op = p.p;
0495 if (slot.is_connected())
0496 {
0497 p.p->cancellation_key_ = iocp_op =
0498 &slot.template emplace<reactor_op_cancellation>(
0499 impl.socket_, iocp_op);
0500 }
0501
0502 int op_type = start_null_buffers_receive_op(impl, flags, p.p, iocp_op);
0503 p.v = p.p = 0;
0504
0505
0506 if (slot.is_connected() && op_type != -1)
0507 {
0508 static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(
0509 &get_reactor(), &impl.reactor_data_, op_type);
0510 }
0511 }
0512
0513
0514 template <typename Socket>
0515 boost::system::error_code accept(implementation_type& impl, Socket& peer,
0516 endpoint_type* peer_endpoint, boost::system::error_code& ec)
0517 {
0518
0519 if (peer.is_open())
0520 {
0521 ec = boost::asio::error::already_open;
0522 BOOST_ASIO_ERROR_LOCATION(ec);
0523 return ec;
0524 }
0525
0526 std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
0527 socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
0528 impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
0529 peer_endpoint ? &addr_len : 0, ec));
0530
0531
0532 if (new_socket.get() != invalid_socket)
0533 {
0534 if (peer_endpoint)
0535 peer_endpoint->resize(addr_len);
0536 peer.assign(impl.protocol_, new_socket.get(), ec);
0537 if (!ec)
0538 new_socket.release();
0539 }
0540
0541 BOOST_ASIO_ERROR_LOCATION(ec);
0542 return ec;
0543 }
0544
0545
0546
0547 template <typename Socket, typename Handler, typename IoExecutor>
0548 void async_accept(implementation_type& impl, Socket& peer,
0549 endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex)
0550 {
0551 associated_cancellation_slot_t<Handler> slot
0552 = boost::asio::get_associated_cancellation_slot(handler);
0553
0554
0555 typedef win_iocp_socket_accept_op<Socket,
0556 protocol_type, Handler, IoExecutor> op;
0557 typename op::ptr p = { boost::asio::detail::addressof(handler),
0558 op::ptr::allocate(handler), 0 };
0559 bool enable_connection_aborted =
0560 (impl.state_ & socket_ops::enable_connection_aborted) != 0;
0561 operation* o = p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_,
0562 peer_endpoint, enable_connection_aborted, handler, io_ex);
0563
0564 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0565 &impl, impl.socket_, "async_accept"));
0566
0567
0568 if (slot.is_connected())
0569 {
0570 accept_op_cancellation* c =
0571 &slot.template emplace<accept_op_cancellation>(impl.socket_, o);
0572 p.p->enable_cancellation(c->get_cancel_requested(), c);
0573 o = c;
0574 }
0575
0576 start_accept_op(impl, peer.is_open(), p.p->new_socket(),
0577 impl.protocol_.family(), impl.protocol_.type(),
0578 impl.protocol_.protocol(), p.p->output_buffer(),
0579 p.p->address_length(), o);
0580 p.v = p.p = 0;
0581 }
0582
0583
0584
0585 template <typename PeerIoExecutor, typename Handler, typename IoExecutor>
0586 void async_move_accept(implementation_type& impl,
0587 const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint,
0588 Handler& handler, const IoExecutor& io_ex)
0589 {
0590 associated_cancellation_slot_t<Handler> slot
0591 = boost::asio::get_associated_cancellation_slot(handler);
0592
0593
0594 typedef win_iocp_socket_move_accept_op<
0595 protocol_type, PeerIoExecutor, Handler, IoExecutor> op;
0596 typename op::ptr p = { boost::asio::detail::addressof(handler),
0597 op::ptr::allocate(handler), 0 };
0598 bool enable_connection_aborted =
0599 (impl.state_ & socket_ops::enable_connection_aborted) != 0;
0600 operation* o = p.p = new (p.v) op(*this, impl.socket_, impl.protocol_,
0601 peer_io_ex, peer_endpoint, enable_connection_aborted,
0602 handler, io_ex);
0603
0604 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0605 &impl, impl.socket_, "async_accept"));
0606
0607
0608 if (slot.is_connected())
0609 {
0610 accept_op_cancellation* c =
0611 &slot.template emplace<accept_op_cancellation>(impl.socket_, o);
0612 p.p->enable_cancellation(c->get_cancel_requested(), c);
0613 o = c;
0614 }
0615
0616 start_accept_op(impl, false, p.p->new_socket(),
0617 impl.protocol_.family(), impl.protocol_.type(),
0618 impl.protocol_.protocol(), p.p->output_buffer(),
0619 p.p->address_length(), o);
0620 p.v = p.p = 0;
0621 }
0622
0623
0624 boost::system::error_code connect(implementation_type& impl,
0625 const endpoint_type& peer_endpoint, boost::system::error_code& ec)
0626 {
0627 socket_ops::sync_connect(impl.socket_,
0628 peer_endpoint.data(), peer_endpoint.size(), ec);
0629 BOOST_ASIO_ERROR_LOCATION(ec);
0630 return ec;
0631 }
0632
0633
0634 template <typename Handler, typename IoExecutor>
0635 void async_connect(implementation_type& impl,
0636 const endpoint_type& peer_endpoint, Handler& handler,
0637 const IoExecutor& io_ex)
0638 {
0639 associated_cancellation_slot_t<Handler> slot
0640 = boost::asio::get_associated_cancellation_slot(handler);
0641
0642
0643 typedef win_iocp_socket_connect_op<Handler, IoExecutor> op;
0644 typename op::ptr p = { boost::asio::detail::addressof(handler),
0645 op::ptr::allocate(handler), 0 };
0646 p.p = new (p.v) op(impl.socket_, handler, io_ex);
0647
0648 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0649 &impl, impl.socket_, "async_connect"));
0650
0651
0652 operation* iocp_op = p.p;
0653 if (slot.is_connected())
0654 {
0655 p.p->cancellation_key_ = iocp_op =
0656 &slot.template emplace<reactor_op_cancellation>(
0657 impl.socket_, iocp_op);
0658 }
0659
0660 int op_type = start_connect_op(impl, impl.protocol_.family(),
0661 impl.protocol_.type(), peer_endpoint.data(),
0662 static_cast<int>(peer_endpoint.size()), p.p, iocp_op);
0663 p.v = p.p = 0;
0664
0665
0666 if (slot.is_connected() && op_type != -1)
0667 {
0668 static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(
0669 &get_reactor(), &impl.reactor_data_, op_type);
0670 }
0671 }
0672 };
0673
0674 }
0675 }
0676 }
0677
0678 #include <boost/asio/detail/pop_options.hpp>
0679
0680 #endif
0681
0682 #endif