in demo_example/asio/asio/detail/impl/win_iocp_socket_service_base.ipp [235:326]
asio::error_code win_iocp_socket_service_base::cancel(
win_iocp_socket_service_base::base_implementation_type& impl,
asio::error_code& ec)
{
if (!is_open(impl))
{
ec = asio::error::bad_descriptor;
return ec;
}
ASIO_HANDLER_OPERATION((iocp_service_.context(),
"socket", &impl, impl.socket_, "cancel"));
if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
{
// The version of Windows supports cancellation from any thread.
typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
cancel_io_ex_t cancel_io_ex = reinterpret_cast<cancel_io_ex_t>(
reinterpret_cast<void*>(cancel_io_ex_ptr));
socket_type sock = impl.socket_;
HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
if (!cancel_io_ex(sock_as_handle, 0))
{
DWORD last_error = ::GetLastError();
if (last_error == ERROR_NOT_FOUND)
{
// ERROR_NOT_FOUND means that there were no operations to be
// cancelled. We swallow this error to match the behaviour on other
// platforms.
ec = asio::error_code();
}
else
{
ec = asio::error_code(last_error,
asio::error::get_system_category());
}
}
else
{
ec = asio::error_code();
}
}
#if defined(ASIO_ENABLE_CANCELIO)
else if (impl.safe_cancellation_thread_id_ == 0)
{
// No operations have been started, so there's nothing to cancel.
ec = asio::error_code();
}
else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
{
// Asynchronous operations have been started from the current thread only,
// so it is safe to try to cancel them using CancelIo.
socket_type sock = impl.socket_;
HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
if (!::CancelIo(sock_as_handle))
{
DWORD last_error = ::GetLastError();
ec = asio::error_code(last_error,
asio::error::get_system_category());
}
else
{
ec = asio::error_code();
}
}
else
{
// Asynchronous operations have been started from more than one thread,
// so cancellation is not safe.
ec = asio::error::operation_not_supported;
}
#else // defined(ASIO_ENABLE_CANCELIO)
else
{
// Cancellation is not supported as CancelIo may not be used.
ec = asio::error::operation_not_supported;
}
#endif // defined(ASIO_ENABLE_CANCELIO)
// Cancel any operations started via the reactor.
if (!ec)
{
select_reactor* r = static_cast<select_reactor*>(
interlocked_compare_exchange_pointer(
reinterpret_cast<void**>(&reactor_), 0, 0));
if (r)
r->cancel_ops(impl.socket_, impl.reactor_data_);
}
return ec;
}