asio::error_code win_iocp_socket_service_base::cancel()

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;
}