如何使用yield_context作为resolver.async_resolve的处理程序?

时间:2014-08-14 01:08:44

标签: c++ c++11 boost boost-asio

使用yield_context作为堆栈协程中Asio异步操作的处理程序真棒!但是ip::basic_resolver::async_resolve的处理程序与仅仅接收错误代码的签名不同(我很好奇为什么它不会将resolver::iterator &作为async_resolve中的参数,比如basic_socket_acceptor::async_accept中的basic_socket<Protocol1, SocketService> &参数。有没有办法使用yield作为它的处理程序?

同样的问题也适用于async_connect

1 个答案:

答案 0 :(得分:5)

Stackful Coroutines overview中所述,将yield_context作为处理程序传递给initiating function,其异步操作的处理程序具有以下形式:

void handler(boost::system::error_code ec, result_type result);

启动函数将返回result_type。在这种情况下,basic_resolver::async_resolve()的处理程序类型要求为ResolverHandler,其格式为:

void resolve_handler(
    const boost::system::error_code& ec,
    boost::asio::ip::tcp::resolver::iterator iterator)

因此,basic_resolver::async_resolve(..., yield_context)将返回resolver::iterator


以下是演示此行为的完整最小示例:

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>

int main()
{
  boost::asio::io_service io_service;

  boost::asio::spawn(io_service,
    [&](boost::asio::yield_context yield)
    {
      using tcp = boost::asio::ip::tcp;
      tcp::resolver resolver(io_service);

      // The async_resolve initiating function will return an iterator, as
      // a yield_context is being passed as a handler.
      tcp::resolver::iterator iterator = resolver.async_resolve(
          tcp::resolver::query("www.google.com", "80"), yield);

      // Iterator over endpoints.
      for(tcp::resolver::iterator end; iterator != end; ++iterator)
      {
        std::cout << iterator->endpoint().address().to_string() << std::endl;
      }
    });

  io_service.run();
}

输出:

74.125.227.209
74.125.227.210
74.125.227.211
74.125.227.212
74.125.227.208
2607:f8b0:4000:80a::1012