File indexing completed on 2025-01-18 09:28:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
0013 #define BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
0014
0015 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0016 # pragma once
0017 #endif
0018
0019 #include <boost/asio/detail/config.hpp>
0020
0021 #if defined(BOOST_ASIO_HAS_IOCP)
0022
0023 #include <boost/asio/associated_cancellation_slot.hpp>
0024 #include <boost/asio/error.hpp>
0025 #include <boost/asio/execution_context.hpp>
0026 #include <boost/asio/detail/buffer_sequence_adapter.hpp>
0027 #include <boost/asio/detail/cstdint.hpp>
0028 #include <boost/asio/detail/handler_alloc_helpers.hpp>
0029 #include <boost/asio/detail/memory.hpp>
0030 #include <boost/asio/detail/mutex.hpp>
0031 #include <boost/asio/detail/operation.hpp>
0032 #include <boost/asio/detail/win_iocp_handle_read_op.hpp>
0033 #include <boost/asio/detail/win_iocp_handle_write_op.hpp>
0034 #include <boost/asio/detail/win_iocp_io_context.hpp>
0035
0036 #include <boost/asio/detail/push_options.hpp>
0037
0038 namespace boost {
0039 namespace asio {
0040 namespace detail {
0041
0042 class win_iocp_handle_service :
0043 public execution_context_service_base<win_iocp_handle_service>
0044 {
0045 public:
0046
0047 typedef HANDLE native_handle_type;
0048
0049
0050 class implementation_type
0051 {
0052 public:
0053
0054 implementation_type()
0055 : handle_(INVALID_HANDLE_VALUE),
0056 safe_cancellation_thread_id_(0),
0057 next_(0),
0058 prev_(0)
0059 {
0060 }
0061
0062 private:
0063
0064 friend class win_iocp_handle_service;
0065
0066
0067 native_handle_type handle_;
0068
0069
0070
0071
0072
0073 DWORD safe_cancellation_thread_id_;
0074
0075
0076 implementation_type* next_;
0077 implementation_type* prev_;
0078 };
0079
0080 BOOST_ASIO_DECL win_iocp_handle_service(execution_context& context);
0081
0082
0083 BOOST_ASIO_DECL void shutdown();
0084
0085
0086 BOOST_ASIO_DECL void construct(implementation_type& impl);
0087
0088
0089 BOOST_ASIO_DECL void move_construct(implementation_type& impl,
0090 implementation_type& other_impl);
0091
0092
0093 BOOST_ASIO_DECL void move_assign(implementation_type& impl,
0094 win_iocp_handle_service& other_service,
0095 implementation_type& other_impl);
0096
0097
0098 BOOST_ASIO_DECL void destroy(implementation_type& impl);
0099
0100
0101 BOOST_ASIO_DECL boost::system::error_code assign(implementation_type& impl,
0102 const native_handle_type& handle, boost::system::error_code& ec);
0103
0104
0105 bool is_open(const implementation_type& impl) const
0106 {
0107 return impl.handle_ != INVALID_HANDLE_VALUE;
0108 }
0109
0110
0111 BOOST_ASIO_DECL boost::system::error_code close(implementation_type& impl,
0112 boost::system::error_code& ec);
0113
0114
0115 BOOST_ASIO_DECL native_handle_type release(implementation_type& impl,
0116 boost::system::error_code& ec);
0117
0118
0119 native_handle_type native_handle(const implementation_type& impl) const
0120 {
0121 return impl.handle_;
0122 }
0123
0124
0125 BOOST_ASIO_DECL boost::system::error_code cancel(implementation_type& impl,
0126 boost::system::error_code& ec);
0127
0128
0129 template <typename ConstBufferSequence>
0130 size_t write_some(implementation_type& impl,
0131 const ConstBufferSequence& buffers, boost::system::error_code& ec)
0132 {
0133 return write_some_at(impl, 0, buffers, ec);
0134 }
0135
0136
0137
0138 template <typename ConstBufferSequence>
0139 size_t write_some_at(implementation_type& impl, uint64_t offset,
0140 const ConstBufferSequence& buffers, boost::system::error_code& ec)
0141 {
0142 boost::asio::const_buffer buffer =
0143 buffer_sequence_adapter<boost::asio::const_buffer,
0144 ConstBufferSequence>::first(buffers);
0145
0146 return do_write(impl, offset, buffer, ec);
0147 }
0148
0149
0150
0151 template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
0152 void async_write_some(implementation_type& impl,
0153 const ConstBufferSequence& buffers,
0154 Handler& handler, const IoExecutor& io_ex)
0155 {
0156 associated_cancellation_slot_t<Handler> slot
0157 = boost::asio::get_associated_cancellation_slot(handler);
0158
0159
0160 typedef win_iocp_handle_write_op<
0161 ConstBufferSequence, Handler, IoExecutor> op;
0162 typename op::ptr p = { boost::asio::detail::addressof(handler),
0163 op::ptr::allocate(handler), 0 };
0164 operation* o = p.p = new (p.v) op(buffers, handler, io_ex);
0165
0166 BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
0167 reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some"));
0168
0169
0170 if (slot.is_connected())
0171 o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);
0172
0173 start_write_op(impl, 0,
0174 buffer_sequence_adapter<boost::asio::const_buffer,
0175 ConstBufferSequence>::first(buffers), o);
0176 p.v = p.p = 0;
0177 }
0178
0179
0180
0181 template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
0182 void async_write_some_at(implementation_type& impl,
0183 uint64_t offset, const ConstBufferSequence& buffers,
0184 Handler& handler, const IoExecutor& io_ex)
0185 {
0186 associated_cancellation_slot_t<Handler> slot
0187 = boost::asio::get_associated_cancellation_slot(handler);
0188
0189
0190 typedef win_iocp_handle_write_op<
0191 ConstBufferSequence, Handler, IoExecutor> op;
0192 typename op::ptr p = { boost::asio::detail::addressof(handler),
0193 op::ptr::allocate(handler), 0 };
0194 operation* o = p.p = new (p.v) op(buffers, handler, io_ex);
0195
0196 BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
0197 reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some_at"));
0198
0199
0200 if (slot.is_connected())
0201 o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);
0202
0203 start_write_op(impl, offset,
0204 buffer_sequence_adapter<boost::asio::const_buffer,
0205 ConstBufferSequence>::first(buffers), o);
0206 p.v = p.p = 0;
0207 }
0208
0209
0210 template <typename MutableBufferSequence>
0211 size_t read_some(implementation_type& impl,
0212 const MutableBufferSequence& buffers, boost::system::error_code& ec)
0213 {
0214 return read_some_at(impl, 0, buffers, ec);
0215 }
0216
0217
0218 template <typename MutableBufferSequence>
0219 size_t read_some_at(implementation_type& impl, uint64_t offset,
0220 const MutableBufferSequence& buffers, boost::system::error_code& ec)
0221 {
0222 boost::asio::mutable_buffer buffer =
0223 buffer_sequence_adapter<boost::asio::mutable_buffer,
0224 MutableBufferSequence>::first(buffers);
0225
0226 return do_read(impl, offset, buffer, ec);
0227 }
0228
0229
0230
0231 template <typename MutableBufferSequence,
0232 typename Handler, typename IoExecutor>
0233 void async_read_some(implementation_type& impl,
0234 const MutableBufferSequence& buffers,
0235 Handler& handler, const IoExecutor& io_ex)
0236 {
0237 associated_cancellation_slot_t<Handler> slot
0238 = boost::asio::get_associated_cancellation_slot(handler);
0239
0240
0241 typedef win_iocp_handle_read_op<
0242 MutableBufferSequence, Handler, IoExecutor> op;
0243 typename op::ptr p = { boost::asio::detail::addressof(handler),
0244 op::ptr::allocate(handler), 0 };
0245 operation* o = p.p = new (p.v) op(buffers, handler, io_ex);
0246
0247 BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
0248 reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some"));
0249
0250
0251 if (slot.is_connected())
0252 o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);
0253
0254 start_read_op(impl, 0,
0255 buffer_sequence_adapter<boost::asio::mutable_buffer,
0256 MutableBufferSequence>::first(buffers), o);
0257 p.v = p.p = 0;
0258 }
0259
0260
0261
0262
0263 template <typename MutableBufferSequence,
0264 typename Handler, typename IoExecutor>
0265 void async_read_some_at(implementation_type& impl,
0266 uint64_t offset, const MutableBufferSequence& buffers,
0267 Handler& handler, const IoExecutor& io_ex)
0268 {
0269 associated_cancellation_slot_t<Handler> slot
0270 = boost::asio::get_associated_cancellation_slot(handler);
0271
0272
0273 typedef win_iocp_handle_read_op<
0274 MutableBufferSequence, Handler, IoExecutor> op;
0275 typename op::ptr p = { boost::asio::detail::addressof(handler),
0276 op::ptr::allocate(handler), 0 };
0277 operation* o = p.p = new (p.v) op(buffers, handler, io_ex);
0278
0279 BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
0280 reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some_at"));
0281
0282
0283 if (slot.is_connected())
0284 o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);
0285
0286 start_read_op(impl, offset,
0287 buffer_sequence_adapter<boost::asio::mutable_buffer,
0288 MutableBufferSequence>::first(buffers), o);
0289 p.v = p.p = 0;
0290 }
0291
0292 private:
0293
0294 size_t write_some(implementation_type& impl,
0295 const null_buffers& buffers, boost::system::error_code& ec);
0296 size_t write_some_at(implementation_type& impl, uint64_t offset,
0297 const null_buffers& buffers, boost::system::error_code& ec);
0298 template <typename Handler, typename IoExecutor>
0299 void async_write_some(implementation_type& impl,
0300 const null_buffers& buffers, Handler& handler,
0301 const IoExecutor& io_ex);
0302 template <typename Handler, typename IoExecutor>
0303 void async_write_some_at(implementation_type& impl, uint64_t offset,
0304 const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex);
0305 size_t read_some(implementation_type& impl,
0306 const null_buffers& buffers, boost::system::error_code& ec);
0307 size_t read_some_at(implementation_type& impl, uint64_t offset,
0308 const null_buffers& buffers, boost::system::error_code& ec);
0309 template <typename Handler, typename IoExecutor>
0310 void async_read_some(implementation_type& impl,
0311 const null_buffers& buffers, Handler& handler,
0312 const IoExecutor& io_ex);
0313 template <typename Handler, typename IoExecutor>
0314 void async_read_some_at(implementation_type& impl, uint64_t offset,
0315 const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex);
0316
0317
0318 class overlapped_wrapper;
0319
0320
0321 BOOST_ASIO_DECL size_t do_write(implementation_type& impl,
0322 uint64_t offset, const boost::asio::const_buffer& buffer,
0323 boost::system::error_code& ec);
0324
0325
0326 BOOST_ASIO_DECL void start_write_op(implementation_type& impl,
0327 uint64_t offset, const boost::asio::const_buffer& buffer,
0328 operation* op);
0329
0330
0331 BOOST_ASIO_DECL size_t do_read(implementation_type& impl,
0332 uint64_t offset, const boost::asio::mutable_buffer& buffer,
0333 boost::system::error_code& ec);
0334
0335
0336 BOOST_ASIO_DECL void start_read_op(implementation_type& impl,
0337 uint64_t offset, const boost::asio::mutable_buffer& buffer,
0338 operation* op);
0339
0340
0341 BOOST_ASIO_DECL void update_cancellation_thread_id(implementation_type& impl);
0342
0343
0344
0345 BOOST_ASIO_DECL void close_for_destruction(implementation_type& impl);
0346
0347
0348 typedef LONG (NTAPI *nt_set_info_fn)(HANDLE, ULONG_PTR*, void*, ULONG, ULONG);
0349
0350
0351
0352
0353
0354 BOOST_ASIO_DECL nt_set_info_fn get_nt_set_info();
0355
0356
0357
0358
0359
0360 BOOST_ASIO_DECL void* interlocked_compare_exchange_pointer(
0361 void** dest, void* exch, void* cmp);
0362
0363
0364
0365
0366 BOOST_ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val);
0367
0368
0369 class iocp_op_cancellation : public operation
0370 {
0371 public:
0372 iocp_op_cancellation(HANDLE h, operation* target)
0373 : operation(&iocp_op_cancellation::do_complete),
0374 handle_(h),
0375 target_(target)
0376 {
0377 }
0378
0379 static void do_complete(void* owner, operation* base,
0380 const boost::system::error_code& result_ec,
0381 std::size_t bytes_transferred)
0382 {
0383 iocp_op_cancellation* o = static_cast<iocp_op_cancellation*>(base);
0384 o->target_->complete(owner, result_ec, bytes_transferred);
0385 }
0386
0387 void operator()(cancellation_type_t type)
0388 {
0389 #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
0390 if (!!(type &
0391 (cancellation_type::terminal
0392 | cancellation_type::partial
0393 | cancellation_type::total)))
0394 {
0395 ::CancelIoEx(handle_, this);
0396 }
0397 #else
0398 (void)type;
0399 #endif
0400 }
0401
0402 private:
0403 HANDLE handle_;
0404 operation* target_;
0405 };
0406
0407
0408
0409 win_iocp_io_context& iocp_service_;
0410
0411
0412 void* nt_set_info_;
0413
0414
0415 mutex mutex_;
0416
0417
0418 implementation_type* impl_list_;
0419 };
0420
0421 }
0422 }
0423 }
0424
0425 #include <boost/asio/detail/pop_options.hpp>
0426
0427 #if defined(BOOST_ASIO_HEADER_ONLY)
0428 # include <boost/asio/detail/impl/win_iocp_handle_service.ipp>
0429 #endif
0430
0431 #endif
0432
0433 #endif