File indexing completed on 2025-01-18 09:28:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_HPP
0012 #define BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_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 <boost/asio/associated_cancellation_slot.hpp>
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_connect_op.hpp>
0041 #include <boost/asio/detail/win_iocp_socket_send_op.hpp>
0042 #include <boost/asio/detail/win_iocp_socket_recv_op.hpp>
0043 #include <boost/asio/detail/win_iocp_socket_recvmsg_op.hpp>
0044 #include <boost/asio/detail/win_iocp_wait_op.hpp>
0045
0046 #include <boost/asio/detail/push_options.hpp>
0047
0048 namespace boost {
0049 namespace asio {
0050 namespace detail {
0051
0052 class win_iocp_socket_service_base
0053 {
0054 public:
0055
0056 struct base_implementation_type
0057 {
0058
0059 socket_type socket_;
0060
0061
0062 socket_ops::state_type state_;
0063
0064
0065
0066
0067
0068
0069
0070 socket_ops::shared_cancel_token_type cancel_token_;
0071
0072
0073 select_reactor::per_descriptor_data reactor_data_;
0074
0075 #if defined(BOOST_ASIO_ENABLE_CANCELIO)
0076
0077
0078
0079
0080 DWORD safe_cancellation_thread_id_;
0081 #endif
0082
0083
0084 base_implementation_type* next_;
0085 base_implementation_type* prev_;
0086 };
0087
0088
0089 BOOST_ASIO_DECL win_iocp_socket_service_base(execution_context& context);
0090
0091
0092 BOOST_ASIO_DECL void base_shutdown();
0093
0094
0095 BOOST_ASIO_DECL void construct(base_implementation_type& impl);
0096
0097
0098 BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl,
0099 base_implementation_type& other_impl) noexcept;
0100
0101
0102 BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl,
0103 win_iocp_socket_service_base& other_service,
0104 base_implementation_type& other_impl);
0105
0106
0107 BOOST_ASIO_DECL void destroy(base_implementation_type& impl);
0108
0109
0110 bool is_open(const base_implementation_type& impl) const
0111 {
0112 return impl.socket_ != invalid_socket;
0113 }
0114
0115
0116 BOOST_ASIO_DECL boost::system::error_code close(
0117 base_implementation_type& impl, boost::system::error_code& ec);
0118
0119
0120 BOOST_ASIO_DECL socket_type release(
0121 base_implementation_type& impl, boost::system::error_code& ec);
0122
0123
0124 BOOST_ASIO_DECL boost::system::error_code cancel(
0125 base_implementation_type& impl, boost::system::error_code& ec);
0126
0127
0128 bool at_mark(const base_implementation_type& impl,
0129 boost::system::error_code& ec) const
0130 {
0131 return socket_ops::sockatmark(impl.socket_, ec);
0132 }
0133
0134
0135 std::size_t available(const base_implementation_type& impl,
0136 boost::system::error_code& ec) const
0137 {
0138 return socket_ops::available(impl.socket_, ec);
0139 }
0140
0141
0142 boost::system::error_code listen(base_implementation_type& impl,
0143 int backlog, boost::system::error_code& ec)
0144 {
0145 socket_ops::listen(impl.socket_, backlog, ec);
0146 return ec;
0147 }
0148
0149
0150 template <typename IO_Control_Command>
0151 boost::system::error_code io_control(base_implementation_type& impl,
0152 IO_Control_Command& command, boost::system::error_code& ec)
0153 {
0154 socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
0155 static_cast<ioctl_arg_type*>(command.data()), ec);
0156 return ec;
0157 }
0158
0159
0160 bool non_blocking(const base_implementation_type& impl) const
0161 {
0162 return (impl.state_ & socket_ops::user_set_non_blocking) != 0;
0163 }
0164
0165
0166 boost::system::error_code non_blocking(base_implementation_type& impl,
0167 bool mode, boost::system::error_code& ec)
0168 {
0169 socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);
0170 return ec;
0171 }
0172
0173
0174 bool native_non_blocking(const base_implementation_type& impl) const
0175 {
0176 return (impl.state_ & socket_ops::internal_non_blocking) != 0;
0177 }
0178
0179
0180 boost::system::error_code native_non_blocking(base_implementation_type& impl,
0181 bool mode, boost::system::error_code& ec)
0182 {
0183 socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);
0184 return ec;
0185 }
0186
0187
0188
0189 boost::system::error_code wait(base_implementation_type& impl,
0190 socket_base::wait_type w, boost::system::error_code& ec)
0191 {
0192 switch (w)
0193 {
0194 case socket_base::wait_read:
0195 socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
0196 break;
0197 case socket_base::wait_write:
0198 socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
0199 break;
0200 case socket_base::wait_error:
0201 socket_ops::poll_error(impl.socket_, impl.state_, -1, ec);
0202 break;
0203 default:
0204 ec = boost::asio::error::invalid_argument;
0205 break;
0206 }
0207
0208 return ec;
0209 }
0210
0211
0212
0213 template <typename Handler, typename IoExecutor>
0214 void async_wait(base_implementation_type& impl,
0215 socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex)
0216 {
0217 associated_cancellation_slot_t<Handler> slot
0218 = boost::asio::get_associated_cancellation_slot(handler);
0219
0220 bool is_continuation =
0221 boost_asio_handler_cont_helpers::is_continuation(handler);
0222
0223
0224 typedef win_iocp_wait_op<Handler, IoExecutor> op;
0225 typename op::ptr p = { boost::asio::detail::addressof(handler),
0226 op::ptr::allocate(handler), 0 };
0227 p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
0228
0229 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0230 &impl, impl.socket_, "async_wait"));
0231
0232
0233 operation* iocp_op = p.p;
0234 if (slot.is_connected())
0235 {
0236 p.p->cancellation_key_ = iocp_op =
0237 &slot.template emplace<reactor_op_cancellation>(
0238 impl.socket_, iocp_op);
0239 }
0240
0241 int op_type = -1;
0242 switch (w)
0243 {
0244 case socket_base::wait_read:
0245 op_type = start_null_buffers_receive_op(impl, 0, p.p, iocp_op);
0246 break;
0247 case socket_base::wait_write:
0248 op_type = select_reactor::write_op;
0249 start_reactor_op(impl, select_reactor::write_op, p.p);
0250 break;
0251 case socket_base::wait_error:
0252 op_type = select_reactor::read_op;
0253 start_reactor_op(impl, select_reactor::except_op, p.p);
0254 break;
0255 default:
0256 p.p->ec_ = boost::asio::error::invalid_argument;
0257 iocp_service_.post_immediate_completion(p.p, is_continuation);
0258 break;
0259 }
0260
0261 p.v = p.p = 0;
0262
0263
0264 if (slot.is_connected() && op_type != -1)
0265 {
0266 static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(
0267 &get_reactor(), &impl.reactor_data_, op_type);
0268 }
0269 }
0270
0271
0272 template <typename ConstBufferSequence>
0273 size_t send(base_implementation_type& impl,
0274 const ConstBufferSequence& buffers,
0275 socket_base::message_flags flags, boost::system::error_code& ec)
0276 {
0277 buffer_sequence_adapter<boost::asio::const_buffer,
0278 ConstBufferSequence> bufs(buffers);
0279
0280 return socket_ops::sync_send(impl.socket_, impl.state_,
0281 bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
0282 }
0283
0284
0285 size_t send(base_implementation_type& impl, const null_buffers&,
0286 socket_base::message_flags, boost::system::error_code& ec)
0287 {
0288
0289 socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
0290
0291 return 0;
0292 }
0293
0294
0295
0296 template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
0297 void async_send(base_implementation_type& impl,
0298 const ConstBufferSequence& buffers, socket_base::message_flags flags,
0299 Handler& handler, const IoExecutor& io_ex)
0300 {
0301 associated_cancellation_slot_t<Handler> slot
0302 = boost::asio::get_associated_cancellation_slot(handler);
0303
0304
0305 typedef win_iocp_socket_send_op<
0306 ConstBufferSequence, Handler, IoExecutor> op;
0307 typename op::ptr p = { boost::asio::detail::addressof(handler),
0308 op::ptr::allocate(handler), 0 };
0309 operation* o = p.p = new (p.v) op(
0310 impl.cancel_token_, buffers, handler, io_ex);
0311
0312 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0313 &impl, impl.socket_, "async_send"));
0314
0315 buffer_sequence_adapter<boost::asio::const_buffer,
0316 ConstBufferSequence> bufs(buffers);
0317
0318
0319 if (slot.is_connected())
0320 o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);
0321
0322 start_send_op(impl, bufs.buffers(), bufs.count(), flags,
0323 (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),
0324 o);
0325 p.v = p.p = 0;
0326 }
0327
0328
0329 template <typename Handler, typename IoExecutor>
0330 void async_send(base_implementation_type& impl, const null_buffers&,
0331 socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
0332 {
0333
0334 typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
0335 typename op::ptr p = { boost::asio::detail::addressof(handler),
0336 op::ptr::allocate(handler), 0 };
0337 p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
0338
0339 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0340 &impl, impl.socket_, "async_send(null_buffers)"));
0341
0342 start_reactor_op(impl, select_reactor::write_op, p.p);
0343 p.v = p.p = 0;
0344 }
0345
0346
0347 template <typename MutableBufferSequence>
0348 size_t receive(base_implementation_type& impl,
0349 const MutableBufferSequence& buffers,
0350 socket_base::message_flags flags, boost::system::error_code& ec)
0351 {
0352 buffer_sequence_adapter<boost::asio::mutable_buffer,
0353 MutableBufferSequence> bufs(buffers);
0354
0355 return socket_ops::sync_recv(impl.socket_, impl.state_,
0356 bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
0357 }
0358
0359
0360 size_t receive(base_implementation_type& impl, const null_buffers&,
0361 socket_base::message_flags, boost::system::error_code& ec)
0362 {
0363
0364 socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
0365
0366 return 0;
0367 }
0368
0369
0370
0371 template <typename MutableBufferSequence,
0372 typename Handler, typename IoExecutor>
0373 void async_receive(base_implementation_type& impl,
0374 const MutableBufferSequence& buffers, socket_base::message_flags flags,
0375 Handler& handler, const IoExecutor& io_ex)
0376 {
0377 associated_cancellation_slot_t<Handler> slot
0378 = boost::asio::get_associated_cancellation_slot(handler);
0379
0380
0381 typedef win_iocp_socket_recv_op<
0382 MutableBufferSequence, Handler, IoExecutor> op;
0383 typename op::ptr p = { boost::asio::detail::addressof(handler),
0384 op::ptr::allocate(handler), 0 };
0385 operation* o = p.p = new (p.v) op(impl.state_,
0386 impl.cancel_token_, buffers, handler, io_ex);
0387
0388 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0389 &impl, impl.socket_, "async_receive"));
0390
0391 buffer_sequence_adapter<boost::asio::mutable_buffer,
0392 MutableBufferSequence> bufs(buffers);
0393
0394
0395 if (slot.is_connected())
0396 o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);
0397
0398 start_receive_op(impl, bufs.buffers(), bufs.count(), flags,
0399 (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),
0400 o);
0401 p.v = p.p = 0;
0402 }
0403
0404
0405 template <typename Handler, typename IoExecutor>
0406 void async_receive(base_implementation_type& impl,
0407 const null_buffers&, socket_base::message_flags flags,
0408 Handler& handler, const IoExecutor& io_ex)
0409 {
0410 associated_cancellation_slot_t<Handler> slot
0411 = boost::asio::get_associated_cancellation_slot(handler);
0412
0413
0414 typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
0415 typename op::ptr p = { boost::asio::detail::addressof(handler),
0416 op::ptr::allocate(handler), 0 };
0417 p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
0418
0419 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0420 &impl, impl.socket_, "async_receive(null_buffers)"));
0421
0422
0423 operation* iocp_op = p.p;
0424 if (slot.is_connected())
0425 {
0426 p.p->cancellation_key_ = iocp_op =
0427 &slot.template emplace<reactor_op_cancellation>(
0428 impl.socket_, iocp_op);
0429 }
0430
0431 int op_type = start_null_buffers_receive_op(impl, flags, p.p, iocp_op);
0432 p.v = p.p = 0;
0433
0434
0435 if (slot.is_connected() && op_type != -1)
0436 {
0437 static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(
0438 &get_reactor(), &impl.reactor_data_, op_type);
0439 }
0440 }
0441
0442
0443
0444 template <typename MutableBufferSequence>
0445 size_t receive_with_flags(base_implementation_type& impl,
0446 const MutableBufferSequence& buffers,
0447 socket_base::message_flags in_flags,
0448 socket_base::message_flags& out_flags, boost::system::error_code& ec)
0449 {
0450 buffer_sequence_adapter<boost::asio::mutable_buffer,
0451 MutableBufferSequence> bufs(buffers);
0452
0453 return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
0454 bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
0455 }
0456
0457
0458 size_t receive_with_flags(base_implementation_type& impl,
0459 const null_buffers&, socket_base::message_flags,
0460 socket_base::message_flags& out_flags, boost::system::error_code& ec)
0461 {
0462
0463 socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
0464
0465
0466
0467 out_flags = 0;
0468
0469 return 0;
0470 }
0471
0472
0473
0474 template <typename MutableBufferSequence,
0475 typename Handler, typename IoExecutor>
0476 void async_receive_with_flags(base_implementation_type& impl,
0477 const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
0478 socket_base::message_flags& out_flags, Handler& handler,
0479 const IoExecutor& io_ex)
0480 {
0481 associated_cancellation_slot_t<Handler> slot
0482 = boost::asio::get_associated_cancellation_slot(handler);
0483
0484
0485 typedef win_iocp_socket_recvmsg_op<
0486 MutableBufferSequence, Handler, IoExecutor> op;
0487 typename op::ptr p = { boost::asio::detail::addressof(handler),
0488 op::ptr::allocate(handler), 0 };
0489 operation* o = p.p = new (p.v) op(impl.cancel_token_,
0490 buffers, out_flags, handler, io_ex);
0491
0492 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0493 &impl, impl.socket_, "async_receive_with_flags"));
0494
0495 buffer_sequence_adapter<boost::asio::mutable_buffer,
0496 MutableBufferSequence> bufs(buffers);
0497
0498
0499 if (slot.is_connected())
0500 o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);
0501
0502 start_receive_op(impl, bufs.buffers(), bufs.count(), in_flags, false, o);
0503 p.v = p.p = 0;
0504 }
0505
0506
0507 template <typename Handler, typename IoExecutor>
0508 void async_receive_with_flags(base_implementation_type& impl,
0509 const null_buffers&, socket_base::message_flags in_flags,
0510 socket_base::message_flags& out_flags, Handler& handler,
0511 const IoExecutor& io_ex)
0512 {
0513 associated_cancellation_slot_t<Handler> slot
0514 = boost::asio::get_associated_cancellation_slot(handler);
0515
0516
0517 typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
0518 typename op::ptr p = { boost::asio::detail::addressof(handler),
0519 op::ptr::allocate(handler), 0 };
0520 p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
0521
0522 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0523 &impl, impl.socket_, "async_receive_with_flags(null_buffers)"));
0524
0525
0526 out_flags = 0;
0527
0528
0529 operation* iocp_op = p.p;
0530 if (slot.is_connected())
0531 {
0532 p.p->cancellation_key_ = iocp_op =
0533 &slot.template emplace<reactor_op_cancellation>(
0534 impl.socket_, iocp_op);
0535 }
0536
0537 int op_type = start_null_buffers_receive_op(impl, in_flags, p.p, iocp_op);
0538 p.v = p.p = 0;
0539
0540
0541 if (slot.is_connected() && op_type != -1)
0542 {
0543 static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(
0544 &get_reactor(), &impl.reactor_data_, op_type);
0545 }
0546 }
0547
0548
0549 BOOST_ASIO_DECL void restart_accept_op(socket_type s,
0550 socket_holder& new_socket, int family, int type,
0551 int protocol, void* output_buffer, DWORD address_length,
0552 long* cancel_requested, operation* op);
0553
0554 protected:
0555
0556 BOOST_ASIO_DECL boost::system::error_code do_open(
0557 base_implementation_type& impl, int family, int type,
0558 int protocol, boost::system::error_code& ec);
0559
0560
0561 BOOST_ASIO_DECL boost::system::error_code do_assign(
0562 base_implementation_type& impl, int type,
0563 socket_type native_socket, boost::system::error_code& ec);
0564
0565
0566 BOOST_ASIO_DECL void start_send_op(base_implementation_type& impl,
0567 WSABUF* buffers, std::size_t buffer_count,
0568 socket_base::message_flags flags, bool noop, operation* op);
0569
0570
0571 BOOST_ASIO_DECL void start_send_to_op(base_implementation_type& impl,
0572 WSABUF* buffers, std::size_t buffer_count, const void* addr,
0573 int addrlen, socket_base::message_flags flags, operation* op);
0574
0575
0576 BOOST_ASIO_DECL void start_receive_op(base_implementation_type& impl,
0577 WSABUF* buffers, std::size_t buffer_count,
0578 socket_base::message_flags flags, bool noop, operation* op);
0579
0580
0581 BOOST_ASIO_DECL int start_null_buffers_receive_op(
0582 base_implementation_type& impl, socket_base::message_flags flags,
0583 reactor_op* op, operation* iocp_op);
0584
0585
0586 BOOST_ASIO_DECL void start_receive_from_op(base_implementation_type& impl,
0587 WSABUF* buffers, std::size_t buffer_count, void* addr,
0588 socket_base::message_flags flags, int* addrlen, operation* op);
0589
0590
0591 BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl,
0592 bool peer_is_open, socket_holder& new_socket, int family, int type,
0593 int protocol, void* output_buffer, DWORD address_length, operation* op);
0594
0595
0596 BOOST_ASIO_DECL void start_reactor_op(base_implementation_type& impl,
0597 int op_type, reactor_op* op);
0598
0599
0600 BOOST_ASIO_DECL int start_connect_op(base_implementation_type& impl,
0601 int family, int type, const void* remote_addr, std::size_t remote_addrlen,
0602 win_iocp_socket_connect_op_base* op, operation* iocp_op);
0603
0604
0605
0606 BOOST_ASIO_DECL void close_for_destruction(base_implementation_type& impl);
0607
0608
0609 BOOST_ASIO_DECL void update_cancellation_thread_id(
0610 base_implementation_type& impl);
0611
0612
0613
0614
0615 BOOST_ASIO_DECL select_reactor& get_reactor();
0616
0617
0618 typedef BOOL (PASCAL *connect_ex_fn)(SOCKET,
0619 const socket_addr_type*, int, void*, DWORD, DWORD*, OVERLAPPED*);
0620
0621
0622
0623
0624 BOOST_ASIO_DECL connect_ex_fn get_connect_ex(
0625 base_implementation_type& impl, int type);
0626
0627
0628 typedef LONG (NTAPI *nt_set_info_fn)(HANDLE, ULONG_PTR*, void*, ULONG, ULONG);
0629
0630
0631
0632
0633
0634 BOOST_ASIO_DECL nt_set_info_fn get_nt_set_info();
0635
0636
0637
0638
0639
0640 BOOST_ASIO_DECL void* interlocked_compare_exchange_pointer(
0641 void** dest, void* exch, void* cmp);
0642
0643
0644
0645
0646 BOOST_ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val);
0647
0648
0649 class iocp_op_cancellation : public operation
0650 {
0651 public:
0652 iocp_op_cancellation(SOCKET s, operation* target)
0653 : operation(&iocp_op_cancellation::do_complete),
0654 socket_(s),
0655 target_(target)
0656 {
0657 }
0658
0659 static void do_complete(void* owner, operation* base,
0660 const boost::system::error_code& result_ec,
0661 std::size_t bytes_transferred)
0662 {
0663 iocp_op_cancellation* o = static_cast<iocp_op_cancellation*>(base);
0664 o->target_->complete(owner, result_ec, bytes_transferred);
0665 }
0666
0667 void operator()(cancellation_type_t type)
0668 {
0669 #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
0670 if (!!(type &
0671 (cancellation_type::terminal
0672 | cancellation_type::partial
0673 | cancellation_type::total)))
0674 {
0675 HANDLE sock_as_handle = reinterpret_cast<HANDLE>(socket_);
0676 ::CancelIoEx(sock_as_handle, this);
0677 }
0678 #else
0679 (void)type;
0680 #endif
0681 }
0682
0683 private:
0684 SOCKET socket_;
0685 operation* target_;
0686 };
0687
0688
0689 class accept_op_cancellation : public operation
0690 {
0691 public:
0692 accept_op_cancellation(SOCKET s, operation* target)
0693 : operation(&iocp_op_cancellation::do_complete),
0694 socket_(s),
0695 target_(target),
0696 cancel_requested_(0)
0697 {
0698 }
0699
0700 static void do_complete(void* owner, operation* base,
0701 const boost::system::error_code& result_ec,
0702 std::size_t bytes_transferred)
0703 {
0704 accept_op_cancellation* o = static_cast<accept_op_cancellation*>(base);
0705 o->target_->complete(owner, result_ec, bytes_transferred);
0706 }
0707
0708 long* get_cancel_requested()
0709 {
0710 return &cancel_requested_;
0711 }
0712
0713 void operator()(cancellation_type_t type)
0714 {
0715 #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
0716 if (!!(type &
0717 (cancellation_type::terminal
0718 | cancellation_type::partial
0719 | cancellation_type::total)))
0720 {
0721 HANDLE sock_as_handle = reinterpret_cast<HANDLE>(socket_);
0722 ::CancelIoEx(sock_as_handle, this);
0723 }
0724 #else
0725 (void)type;
0726 #endif
0727 }
0728
0729 private:
0730 SOCKET socket_;
0731 operation* target_;
0732 long cancel_requested_;
0733 };
0734
0735
0736 class reactor_op_cancellation : public operation
0737 {
0738 public:
0739 reactor_op_cancellation(SOCKET s, operation* base)
0740 : operation(&reactor_op_cancellation::do_complete),
0741 socket_(s),
0742 target_(base),
0743 reactor_(0),
0744 reactor_data_(0),
0745 op_type_(-1)
0746 {
0747 }
0748
0749 void use_reactor(select_reactor* r,
0750 select_reactor::per_descriptor_data* p, int o)
0751 {
0752 reactor_ = r;
0753 reactor_data_ = p;
0754 op_type_ = o;
0755 }
0756
0757 static void do_complete(void* owner, operation* base,
0758 const boost::system::error_code& result_ec,
0759 std::size_t bytes_transferred)
0760 {
0761 reactor_op_cancellation* o = static_cast<reactor_op_cancellation*>(base);
0762 o->target_->complete(owner, result_ec, bytes_transferred);
0763 }
0764
0765 void operator()(cancellation_type_t type)
0766 {
0767 if (!!(type &
0768 (cancellation_type::terminal
0769 | cancellation_type::partial
0770 | cancellation_type::total)))
0771 {
0772 if (reactor_)
0773 {
0774 reactor_->cancel_ops_by_key(socket_,
0775 *reactor_data_, op_type_, this);
0776 }
0777 else
0778 {
0779 #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
0780 HANDLE sock_as_handle = reinterpret_cast<HANDLE>(socket_);
0781 ::CancelIoEx(sock_as_handle, this);
0782 #endif
0783 }
0784 }
0785 }
0786
0787 private:
0788 SOCKET socket_;
0789 operation* target_;
0790 select_reactor* reactor_;
0791 select_reactor::per_descriptor_data* reactor_data_;
0792 int op_type_;
0793 };
0794
0795
0796 execution_context& context_;
0797
0798
0799
0800 win_iocp_io_context& iocp_service_;
0801
0802
0803
0804 select_reactor* reactor_;
0805
0806
0807 void* connect_ex_;
0808
0809
0810 void* nt_set_info_;
0811
0812
0813 boost::asio::detail::mutex mutex_;
0814
0815
0816 base_implementation_type* impl_list_;
0817 };
0818
0819 }
0820 }
0821 }
0822
0823 #include <boost/asio/detail/pop_options.hpp>
0824
0825 #if defined(BOOST_ASIO_HEADER_ONLY)
0826 # include <boost/asio/detail/impl/win_iocp_socket_service_base.ipp>
0827 #endif
0828
0829 #endif
0830
0831 #endif