00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
00013 #define ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
00014
00015 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00016 # pragma once
00017 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00018
00019 #include "asio/detail/push_options.hpp"
00020
00021 #include "asio/detail/win_iocp_io_service_fwd.hpp"
00022
00023 #if defined(ASIO_HAS_IOCP)
00024
00025 #include "asio/detail/push_options.hpp"
00026 #include <boost/cstdint.hpp>
00027 #include "asio/detail/pop_options.hpp"
00028
00029 #include "asio/buffer.hpp"
00030 #include "asio/error.hpp"
00031 #include "asio/io_service.hpp"
00032 #include "asio/detail/bind_handler.hpp"
00033 #include "asio/detail/handler_alloc_helpers.hpp"
00034 #include "asio/detail/handler_invoke_helpers.hpp"
00035 #include "asio/detail/mutex.hpp"
00036 #include "asio/detail/win_iocp_io_service.hpp"
00037
00038 namespace asio {
00039 namespace detail {
00040
00041 class win_iocp_handle_service
00042 : public asio::detail::service_base<win_iocp_handle_service>
00043 {
00044 public:
00045
00046 typedef win_iocp_io_service::operation operation;
00047
00048
00049 typedef HANDLE native_type;
00050
00051
00052 class implementation_type
00053 {
00054 public:
00055
00056 implementation_type()
00057 : handle_(INVALID_HANDLE_VALUE),
00058 safe_cancellation_thread_id_(0),
00059 next_(0),
00060 prev_(0)
00061 {
00062 }
00063
00064 private:
00065
00066 friend class win_iocp_handle_service;
00067
00068
00069 native_type handle_;
00070
00071
00072
00073
00074
00075 DWORD safe_cancellation_thread_id_;
00076
00077
00078 implementation_type* next_;
00079 implementation_type* prev_;
00080 };
00081
00082 win_iocp_handle_service(asio::io_service& io_service)
00083 : asio::detail::service_base<win_iocp_handle_service>(io_service),
00084 iocp_service_(asio::use_service<win_iocp_io_service>(io_service)),
00085 mutex_(),
00086 impl_list_(0)
00087 {
00088 }
00089
00090
00091 void shutdown_service()
00092 {
00093
00094 asio::detail::mutex::scoped_lock lock(mutex_);
00095 implementation_type* impl = impl_list_;
00096 while (impl)
00097 {
00098 close_for_destruction(*impl);
00099 impl = impl->next_;
00100 }
00101 }
00102
00103
00104 void construct(implementation_type& impl)
00105 {
00106 impl.handle_ = INVALID_HANDLE_VALUE;
00107 impl.safe_cancellation_thread_id_ = 0;
00108
00109
00110 asio::detail::mutex::scoped_lock lock(mutex_);
00111 impl.next_ = impl_list_;
00112 impl.prev_ = 0;
00113 if (impl_list_)
00114 impl_list_->prev_ = &impl;
00115 impl_list_ = &impl;
00116 }
00117
00118
00119 void destroy(implementation_type& impl)
00120 {
00121 close_for_destruction(impl);
00122
00123
00124 asio::detail::mutex::scoped_lock lock(mutex_);
00125 if (impl_list_ == &impl)
00126 impl_list_ = impl.next_;
00127 if (impl.prev_)
00128 impl.prev_->next_ = impl.next_;
00129 if (impl.next_)
00130 impl.next_->prev_= impl.prev_;
00131 impl.next_ = 0;
00132 impl.prev_ = 0;
00133 }
00134
00135
00136 asio::error_code assign(implementation_type& impl,
00137 const native_type& native_handle, asio::error_code& ec)
00138 {
00139 if (is_open(impl))
00140 {
00141 ec = asio::error::already_open;
00142 return ec;
00143 }
00144
00145 if (iocp_service_.register_handle(native_handle, ec))
00146 return ec;
00147
00148 impl.handle_ = native_handle;
00149 ec = asio::error_code();
00150 return ec;
00151 }
00152
00153
00154 bool is_open(const implementation_type& impl) const
00155 {
00156 return impl.handle_ != INVALID_HANDLE_VALUE;
00157 }
00158
00159
00160 asio::error_code close(implementation_type& impl,
00161 asio::error_code& ec)
00162 {
00163 if (is_open(impl))
00164 {
00165 if (!::CloseHandle(impl.handle_))
00166 {
00167 DWORD last_error = ::GetLastError();
00168 ec = asio::error_code(last_error,
00169 asio::error::get_system_category());
00170 return ec;
00171 }
00172
00173 impl.handle_ = INVALID_HANDLE_VALUE;
00174 impl.safe_cancellation_thread_id_ = 0;
00175 }
00176
00177 ec = asio::error_code();
00178 return ec;
00179 }
00180
00181
00182 native_type native(const implementation_type& impl) const
00183 {
00184 return impl.handle_;
00185 }
00186
00187
00188 asio::error_code cancel(implementation_type& impl,
00189 asio::error_code& ec)
00190 {
00191 if (!is_open(impl))
00192 {
00193 ec = asio::error::bad_descriptor;
00194 }
00195 else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
00196 ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
00197 {
00198
00199 typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
00200 cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
00201 if (!cancel_io_ex(impl.handle_, 0))
00202 {
00203 DWORD last_error = ::GetLastError();
00204 if (last_error == ERROR_NOT_FOUND)
00205 {
00206
00207
00208
00209 ec = asio::error_code();
00210 }
00211 else
00212 {
00213 ec = asio::error_code(last_error,
00214 asio::error::get_system_category());
00215 }
00216 }
00217 else
00218 {
00219 ec = asio::error_code();
00220 }
00221 }
00222 else if (impl.safe_cancellation_thread_id_ == 0)
00223 {
00224
00225 ec = asio::error_code();
00226 }
00227 else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
00228 {
00229
00230
00231 if (!::CancelIo(impl.handle_))
00232 {
00233 DWORD last_error = ::GetLastError();
00234 ec = asio::error_code(last_error,
00235 asio::error::get_system_category());
00236 }
00237 else
00238 {
00239 ec = asio::error_code();
00240 }
00241 }
00242 else
00243 {
00244
00245
00246 ec = asio::error::operation_not_supported;
00247 }
00248
00249 return ec;
00250 }
00251
00252 class overlapped_wrapper
00253 : public OVERLAPPED
00254 {
00255 public:
00256 explicit overlapped_wrapper(asio::error_code& ec)
00257 {
00258 Internal = 0;
00259 InternalHigh = 0;
00260 Offset = 0;
00261 OffsetHigh = 0;
00262
00263
00264 hEvent = ::CreateEvent(0, TRUE, FALSE, 0);
00265 if (hEvent)
00266 {
00267
00268
00269
00270 *reinterpret_cast<DWORD_PTR*>(&hEvent) |= 1;
00271 }
00272 else
00273 {
00274 DWORD last_error = ::GetLastError();
00275 ec = asio::error_code(last_error,
00276 asio::error::get_system_category());
00277 }
00278 }
00279
00280 ~overlapped_wrapper()
00281 {
00282 if (hEvent)
00283 {
00284 ::CloseHandle(hEvent);
00285 }
00286 }
00287 };
00288
00289
00290 template <typename ConstBufferSequence>
00291 size_t write_some(implementation_type& impl,
00292 const ConstBufferSequence& buffers, asio::error_code& ec)
00293 {
00294 return write_some_at(impl, 0, buffers, ec);
00295 }
00296
00297
00298
00299 template <typename ConstBufferSequence>
00300 size_t write_some_at(implementation_type& impl, boost::uint64_t offset,
00301 const ConstBufferSequence& buffers, asio::error_code& ec)
00302 {
00303 if (!is_open(impl))
00304 {
00305 ec = asio::error::bad_descriptor;
00306 return 0;
00307 }
00308
00309
00310 asio::const_buffer buffer;
00311 typename ConstBufferSequence::const_iterator iter = buffers.begin();
00312 typename ConstBufferSequence::const_iterator end = buffers.end();
00313 for (DWORD i = 0; iter != end; ++iter, ++i)
00314 {
00315 buffer = asio::const_buffer(*iter);
00316 if (asio::buffer_size(buffer) != 0)
00317 break;
00318 }
00319
00320
00321 if (asio::buffer_size(buffer) == 0)
00322 {
00323 ec = asio::error_code();
00324 return 0;
00325 }
00326
00327 overlapped_wrapper overlapped(ec);
00328 if (ec)
00329 {
00330 return 0;
00331 }
00332
00333
00334 overlapped.Offset = offset & 0xFFFFFFFF;
00335 overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
00336 BOOL ok = ::WriteFile(impl.handle_,
00337 asio::buffer_cast<LPCVOID>(buffer),
00338 static_cast<DWORD>(asio::buffer_size(buffer)), 0, &overlapped);
00339 if (!ok)
00340 {
00341 DWORD last_error = ::GetLastError();
00342 if (last_error != ERROR_IO_PENDING)
00343 {
00344 ec = asio::error_code(last_error,
00345 asio::error::get_system_category());
00346 return 0;
00347 }
00348 }
00349
00350
00351 DWORD bytes_transferred = 0;
00352 ok = ::GetOverlappedResult(impl.handle_,
00353 &overlapped, &bytes_transferred, TRUE);
00354 if (!ok)
00355 {
00356 DWORD last_error = ::GetLastError();
00357 ec = asio::error_code(last_error,
00358 asio::error::get_system_category());
00359 }
00360
00361 ec = asio::error_code();
00362 return bytes_transferred;
00363 }
00364
00365 template <typename ConstBufferSequence, typename Handler>
00366 class write_operation
00367 : public operation
00368 {
00369 public:
00370 write_operation(win_iocp_io_service& io_service,
00371 const ConstBufferSequence& buffers, Handler handler)
00372 : operation(io_service,
00373 &write_operation<ConstBufferSequence, Handler>::do_completion_impl,
00374 &write_operation<ConstBufferSequence, Handler>::destroy_impl),
00375 work_(io_service.get_io_service()),
00376 buffers_(buffers),
00377 handler_(handler)
00378 {
00379 }
00380
00381 private:
00382 static void do_completion_impl(operation* op,
00383 DWORD last_error, size_t bytes_transferred)
00384 {
00385
00386 typedef write_operation<ConstBufferSequence, Handler> op_type;
00387 op_type* handler_op(static_cast<op_type*>(op));
00388 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
00389 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
00390
00391 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00392
00393 typename ConstBufferSequence::const_iterator iter
00394 = handler_op->buffers_.begin();
00395 typename ConstBufferSequence::const_iterator end
00396 = handler_op->buffers_.end();
00397 while (iter != end)
00398 {
00399 asio::const_buffer buffer(*iter);
00400 asio::buffer_cast<const char*>(buffer);
00401 ++iter;
00402 }
00403 #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00404
00405
00406
00407 Handler handler(handler_op->handler_);
00408
00409
00410 ptr.reset();
00411
00412
00413 asio::error_code ec(last_error,
00414 asio::error::get_system_category());
00415 asio_handler_invoke_helpers::invoke(
00416 bind_handler(handler, ec, bytes_transferred), &handler);
00417 }
00418
00419 static void destroy_impl(operation* op)
00420 {
00421
00422 typedef write_operation<ConstBufferSequence, Handler> op_type;
00423 op_type* handler_op(static_cast<op_type*>(op));
00424 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
00425 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
00426
00427
00428
00429
00430
00431 Handler handler(handler_op->handler_);
00432 (void)handler;
00433
00434
00435 ptr.reset();
00436 }
00437
00438 asio::io_service::work work_;
00439 ConstBufferSequence buffers_;
00440 Handler handler_;
00441 };
00442
00443
00444
00445 template <typename ConstBufferSequence, typename Handler>
00446 void async_write_some(implementation_type& impl,
00447 const ConstBufferSequence& buffers, Handler handler)
00448 {
00449 async_write_some_at(impl, 0, buffers, handler);
00450 }
00451
00452
00453
00454 template <typename ConstBufferSequence, typename Handler>
00455 void async_write_some_at(implementation_type& impl, boost::uint64_t offset,
00456 const ConstBufferSequence& buffers, Handler handler)
00457 {
00458 if (!is_open(impl))
00459 {
00460 this->get_io_service().post(bind_handler(handler,
00461 asio::error::bad_descriptor, 0));
00462 return;
00463 }
00464
00465
00466 if (impl.safe_cancellation_thread_id_ == 0)
00467 impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
00468 else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
00469 impl.safe_cancellation_thread_id_ = ~DWORD(0);
00470
00471
00472 typedef write_operation<ConstBufferSequence, Handler> value_type;
00473 typedef handler_alloc_traits<Handler, value_type> alloc_traits;
00474 raw_handler_ptr<alloc_traits> raw_ptr(handler);
00475 handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);
00476
00477
00478 asio::const_buffer buffer;
00479 typename ConstBufferSequence::const_iterator iter = buffers.begin();
00480 typename ConstBufferSequence::const_iterator end = buffers.end();
00481 for (DWORD i = 0; iter != end; ++iter, ++i)
00482 {
00483 buffer = asio::const_buffer(*iter);
00484 if (asio::buffer_size(buffer) != 0)
00485 break;
00486 }
00487
00488
00489 if (asio::buffer_size(buffer) == 0)
00490 {
00491 asio::io_service::work work(this->get_io_service());
00492 ptr.reset();
00493 asio::error_code error;
00494 iocp_service_.post(bind_handler(handler, error, 0));
00495 return;
00496 }
00497
00498
00499 DWORD bytes_transferred = 0;
00500 ptr.get()->Offset = offset & 0xFFFFFFFF;
00501 ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
00502 BOOL ok = ::WriteFile(impl.handle_,
00503 asio::buffer_cast<LPCVOID>(buffer),
00504 static_cast<DWORD>(asio::buffer_size(buffer)),
00505 &bytes_transferred, ptr.get());
00506 DWORD last_error = ::GetLastError();
00507
00508
00509 if (!ok && last_error != ERROR_IO_PENDING)
00510 {
00511 asio::io_service::work work(this->get_io_service());
00512 ptr.reset();
00513 asio::error_code ec(last_error,
00514 asio::error::get_system_category());
00515 iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
00516 }
00517 else
00518 {
00519 ptr.release();
00520 }
00521 }
00522
00523
00524 template <typename MutableBufferSequence>
00525 size_t read_some(implementation_type& impl,
00526 const MutableBufferSequence& buffers, asio::error_code& ec)
00527 {
00528 return read_some_at(impl, 0, buffers, ec);
00529 }
00530
00531
00532 template <typename MutableBufferSequence>
00533 size_t read_some_at(implementation_type& impl, boost::uint64_t offset,
00534 const MutableBufferSequence& buffers, asio::error_code& ec)
00535 {
00536 if (!is_open(impl))
00537 {
00538 ec = asio::error::bad_descriptor;
00539 return 0;
00540 }
00541
00542
00543 asio::mutable_buffer buffer;
00544 typename MutableBufferSequence::const_iterator iter = buffers.begin();
00545 typename MutableBufferSequence::const_iterator end = buffers.end();
00546 for (DWORD i = 0; iter != end; ++iter, ++i)
00547 {
00548 buffer = asio::mutable_buffer(*iter);
00549 if (asio::buffer_size(buffer) != 0)
00550 break;
00551 }
00552
00553
00554 if (asio::buffer_size(buffer) == 0)
00555 {
00556 ec = asio::error_code();
00557 return 0;
00558 }
00559
00560 overlapped_wrapper overlapped(ec);
00561 if (ec)
00562 {
00563 return 0;
00564 }
00565
00566
00567 overlapped.Offset = offset & 0xFFFFFFFF;
00568 overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
00569 BOOL ok = ::ReadFile(impl.handle_,
00570 asio::buffer_cast<LPVOID>(buffer),
00571 static_cast<DWORD>(asio::buffer_size(buffer)), 0, &overlapped);
00572 if (!ok)
00573 {
00574 DWORD last_error = ::GetLastError();
00575 if (last_error != ERROR_IO_PENDING)
00576 {
00577 if (last_error == ERROR_HANDLE_EOF)
00578 {
00579 ec = asio::error::eof;
00580 }
00581 else
00582 {
00583 ec = asio::error_code(last_error,
00584 asio::error::get_system_category());
00585 }
00586 return 0;
00587 }
00588 }
00589
00590
00591 DWORD bytes_transferred = 0;
00592 ok = ::GetOverlappedResult(impl.handle_,
00593 &overlapped, &bytes_transferred, TRUE);
00594 if (!ok)
00595 {
00596 DWORD last_error = ::GetLastError();
00597 if (last_error == ERROR_HANDLE_EOF)
00598 {
00599 ec = asio::error::eof;
00600 }
00601 else
00602 {
00603 ec = asio::error_code(last_error,
00604 asio::error::get_system_category());
00605 }
00606 }
00607
00608 ec = asio::error_code();
00609 return bytes_transferred;
00610 }
00611
00612 template <typename MutableBufferSequence, typename Handler>
00613 class read_operation
00614 : public operation
00615 {
00616 public:
00617 read_operation(win_iocp_io_service& io_service,
00618 const MutableBufferSequence& buffers, Handler handler)
00619 : operation(io_service,
00620 &read_operation<
00621 MutableBufferSequence, Handler>::do_completion_impl,
00622 &read_operation<
00623 MutableBufferSequence, Handler>::destroy_impl),
00624 work_(io_service.get_io_service()),
00625 buffers_(buffers),
00626 handler_(handler)
00627 {
00628 }
00629
00630 private:
00631 static void do_completion_impl(operation* op,
00632 DWORD last_error, size_t bytes_transferred)
00633 {
00634
00635 typedef read_operation<MutableBufferSequence, Handler> op_type;
00636 op_type* handler_op(static_cast<op_type*>(op));
00637 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
00638 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
00639
00640 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00641
00642 typename MutableBufferSequence::const_iterator iter
00643 = handler_op->buffers_.begin();
00644 typename MutableBufferSequence::const_iterator end
00645 = handler_op->buffers_.end();
00646 while (iter != end)
00647 {
00648 asio::mutable_buffer buffer(*iter);
00649 asio::buffer_cast<char*>(buffer);
00650 ++iter;
00651 }
00652 #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00653
00654
00655 asio::error_code ec(last_error,
00656 asio::error::get_system_category());
00657 if (!ec && bytes_transferred == 0 || last_error == ERROR_HANDLE_EOF)
00658 {
00659 ec = asio::error::eof;
00660 }
00661
00662
00663
00664 Handler handler(handler_op->handler_);
00665
00666
00667 ptr.reset();
00668
00669
00670 asio_handler_invoke_helpers::invoke(
00671 bind_handler(handler, ec, bytes_transferred), &handler);
00672 }
00673
00674 static void destroy_impl(operation* op)
00675 {
00676
00677 typedef read_operation<MutableBufferSequence, Handler> op_type;
00678 op_type* handler_op(static_cast<op_type*>(op));
00679 typedef asio::detail::handler_alloc_traits<
00680 Handler, op_type> alloc_traits;
00681 asio::detail::handler_ptr<alloc_traits> ptr(
00682 handler_op->handler_, handler_op);
00683
00684
00685
00686
00687
00688 Handler handler(handler_op->handler_);
00689 (void)handler;
00690
00691
00692 ptr.reset();
00693 }
00694
00695 asio::io_service::work work_;
00696 MutableBufferSequence buffers_;
00697 Handler handler_;
00698 };
00699
00700
00701
00702 template <typename MutableBufferSequence, typename Handler>
00703 void async_read_some(implementation_type& impl,
00704 const MutableBufferSequence& buffers, Handler handler)
00705 {
00706 async_read_some_at(impl, 0, buffers, handler);
00707 }
00708
00709
00710
00711
00712 template <typename MutableBufferSequence, typename Handler>
00713 void async_read_some_at(implementation_type& impl, boost::uint64_t offset,
00714 const MutableBufferSequence& buffers, Handler handler)
00715 {
00716 if (!is_open(impl))
00717 {
00718 this->get_io_service().post(bind_handler(handler,
00719 asio::error::bad_descriptor, 0));
00720 return;
00721 }
00722
00723
00724 if (impl.safe_cancellation_thread_id_ == 0)
00725 impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
00726 else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
00727 impl.safe_cancellation_thread_id_ = ~DWORD(0);
00728
00729
00730 typedef read_operation<MutableBufferSequence, Handler> value_type;
00731 typedef handler_alloc_traits<Handler, value_type> alloc_traits;
00732 raw_handler_ptr<alloc_traits> raw_ptr(handler);
00733 handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);
00734
00735
00736 asio::mutable_buffer buffer;
00737 typename MutableBufferSequence::const_iterator iter = buffers.begin();
00738 typename MutableBufferSequence::const_iterator end = buffers.end();
00739 for (DWORD i = 0; iter != end; ++iter, ++i)
00740 {
00741 buffer = asio::mutable_buffer(*iter);
00742 if (asio::buffer_size(buffer) != 0)
00743 break;
00744 }
00745
00746
00747 if (asio::buffer_size(buffer) == 0)
00748 {
00749 asio::io_service::work work(this->get_io_service());
00750 ptr.reset();
00751 asio::error_code error;
00752 iocp_service_.post(bind_handler(handler, error, 0));
00753 return;
00754 }
00755
00756
00757 DWORD bytes_transferred = 0;
00758 ptr.get()->Offset = offset & 0xFFFFFFFF;
00759 ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
00760 BOOL ok = ::ReadFile(impl.handle_,
00761 asio::buffer_cast<LPVOID>(buffer),
00762 static_cast<DWORD>(asio::buffer_size(buffer)),
00763 &bytes_transferred, ptr.get());
00764 DWORD last_error = ::GetLastError();
00765 if (!ok && last_error != ERROR_IO_PENDING)
00766 {
00767 asio::io_service::work work(this->get_io_service());
00768 ptr.reset();
00769 asio::error_code ec(last_error,
00770 asio::error::get_system_category());
00771 iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
00772 }
00773 else
00774 {
00775 ptr.release();
00776 }
00777 }
00778
00779 private:
00780
00781 size_t write_some(implementation_type& impl,
00782 const null_buffers& buffers, asio::error_code& ec);
00783 size_t write_some_at(implementation_type& impl, boost::uint64_t offset,
00784 const null_buffers& buffers, asio::error_code& ec);
00785 template <typename Handler>
00786 void async_write_some(implementation_type& impl,
00787 const null_buffers& buffers, Handler handler);
00788 template <typename Handler>
00789 void async_write_some_at(implementation_type& impl, boost::uint64_t offset,
00790 const null_buffers& buffers, Handler handler);
00791 size_t read_some(implementation_type& impl,
00792 const null_buffers& buffers, asio::error_code& ec);
00793 size_t read_some_at(implementation_type& impl, boost::uint64_t offset,
00794 const null_buffers& buffers, asio::error_code& ec);
00795 template <typename Handler>
00796 void async_read_some(implementation_type& impl,
00797 const null_buffers& buffers, Handler handler);
00798 template <typename Handler>
00799 void async_read_some_at(implementation_type& impl, boost::uint64_t offset,
00800 const null_buffers& buffers, Handler handler);
00801
00802
00803
00804 void close_for_destruction(implementation_type& impl)
00805 {
00806 if (is_open(impl))
00807 {
00808 ::CloseHandle(impl.handle_);
00809 impl.handle_ = INVALID_HANDLE_VALUE;
00810 impl.safe_cancellation_thread_id_ = 0;
00811 }
00812 }
00813
00814
00815
00816 win_iocp_io_service& iocp_service_;
00817
00818
00819 asio::detail::mutex mutex_;
00820
00821
00822 implementation_type* impl_list_;
00823 };
00824
00825 }
00826 }
00827
00828 #endif // defined(ASIO_HAS_IOCP)
00829
00830 #include "asio/detail/pop_options.hpp"
00831
00832 #endif // ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP