async_resolve中boost :: asio :: ip :: tcp :: resolver :: iterator的生命周期是多长? [英] What's the lifetime of boost::asio::ip::tcp::resolver::iterator from async_resolve?

查看:279
本文介绍了async_resolve中boost :: asio :: ip :: tcp :: resolver :: iterator的生命周期是多长?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我调用boost::asio::ip::tcp::resolver::async_resolve时,我的处理程序收到一个遍历一个或多个ip::tcp::resolver::entriesip::tcp::resolver::iterator. 他们的一生是什么?保持生命的柄是什么?

When I call boost::asio::ip::tcp::resolver::async_resolve, my handler receives an ip::tcp::resolver::iterator that iterates through one or more ip::tcp::resolver::entries. What is their lifetime, and what is the handle that keeps them alive?

例如,如果我得到第一个entry并对其启动一个tcp::async_connect,那么我可以在async_connect处理程序中迭代到下一个entry并启动另一个async_connect到下一个条目(当然,只要我将iterator传递给async_connect处理程序)?

For example, if I get the first entry and launch a tcp::async_connect to it, then in the async_connect handler, can I iterate to the next entry and launch another async_connect to the next entry (as long as I pass the iterator to the async_connect handler, of course)?

什么时候清理resolver::iteratorresolver::entries?我是否需要做一些特别的事情,还是只是让它们超出范围而不受任何回调闭包的约束?

When do the resolver::iterator and resolver::entries get cleaned up? Do I have to do anything special, or just let them go out of scope and not held by any callback closure?

(我知道我可以遍历我的async_resolve处理程序中的所有resolver::entries并将它们存储在智能指向的结构或其他任何东西中,以便我控制它们的生命周期,但是如果asio::ip::tcp::resolver已经在处理它,只要让它执行工作,我的代码就会更简单.)

(I understand that I could run through all the resolver::entries in my async_resolve handler and store them in a smart-pointed structure or whatever, so that I control their lifetime, but if asio::ip::tcp::resolver is already handling it, my code will be simpler if I just let it do its job.)

推荐答案

解构问题

迭代器具有值语义.因此,它们的生命周期始终与周围对象的生命周期或存储期限(自动堆放,动态堆放,有时甚至是静态堆放)绑定在一起.

Deconstructing The Question

Iterators have value semantics. So their lifetime is always bound to the lifetime of the surrounding object, or their storage duration (stack for automatic, heap for dynamic and sometimes even others for e.g. static).

我认为您想了解迭代器的 validity .

I think you want to know about the validity of the iterators instead.

好吧,该文档显示,则迭代器类别为前馈迭代器.前向迭代器具有多遍保证",可以重复取消迭代器副本的引用,从而获得相同的结果¹.

Well, the documentation shows that the iterator category is forward iterator. Forward iterators have the "Multipass guarantee", allowing repeated dereference of copies of iterators, yielding the same result¹.

因此,我们进行了一半:保留迭代器仍然可以.但是,当然,与其他任何[转发]迭代器一样,我们必须考虑迭代器无效.

So, we're halfway: it could still be ok to keep the iterators. However, of course, like with any other [forward] iterator, we have to think of iterator invalidation.

因此,真正的问题归结为:何时解析程序迭代器无效.

So, the real question boils down to: when are resolver iterators invalidated.

resolve函数实现的用例是连接.对于连接而言,第一个有效的端点就足够了,因此无需实际保留列表.

The usecase the resolve function fulfills is connection. For connection, the first endpoint that works is enough, so there is no need for it to actually retain a list.

本着按需购买"的精神,解析器将状态保留的时间比所需时间更长没有意义.另一方面,如果不支持Multipass,则将迭代器归为ForwardIterator类别是没有意义的.

In the spirit of pay-for-what-you-need² it would not make sense for resolver to keep the state around longer than required. On the other hand it would not make sense for the iterator to be in the ForwardIterator category if Multipass weren't supported.

文档什么也没说.我们只有一种方法:深入研究代码

The docs say nothing. We have only one recourse: dive into the code

我们在表面之下找到了一些步骤: asio/detail/resolver_service.hpp:73

Some steps below the surface we find: asio/detail/resolver_service.hpp:73

  // Asynchronously resolve a query to a list of entries.
  template <typename Handler>
  void async_resolve(implementation_type& impl,
      const query_type& query, Handler& handler)
  {
    // Allocate and construct an operation to wrap the handler.
    typedef resolve_op<Protocol, Handler> op;
    typename op::ptr p = { boost::asio::detail::addressof(handler),
      boost_asio_handler_alloc_helpers::allocate(
        sizeof(op), handler), 0 };

resolve_op显示迭代器是使用这将使我们得到答案:在

And this leads us to the answer: in line 251

  typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
  boost::asio::detail::shared_ptr<values_type> values_;
  std::size_t index_;

因此,只要您保留有效迭代器(而不是最终迭代器)的副本,就可以继续取消对其的引用.它甚至会在每个解析器条目中保留查询参数(host_nameservice_name)的副本.这似乎有点浪费,但是我想在设计缓存方案时会派上用场.

So, as long as you a keep a copy of a valid the iterator (not the end iterator) you can keep dereferencing it. It will even keep a copy of the query parameters (host_name and service_name) with each resolver entry. This seems slightly wasteful but I suppose could come in handy when devising a caching scheme.

  • .何时解析程序迭代器无效?
  • A..当有效迭代器的最后一个副本被破坏时.
  • Q. When are resolver iterators invalidated?
  • A. When the last copy of a valid iterator is destructed.

翻译为它们始终有效"(如果它们一直有效).

Which translates "they always remain valid" (if they were ever valid).

¹,而不是例如输入迭代器

¹ as opposed to e.g. input iterators

²通常,C ++实现遵循 零开销原则:您不用的东西,不用付钱[C ++的设计和演进,1994年]

² In general, C++ implementations obey the zero-overhead principle: What you don’t use, you don’t pay for [The Design and Evolution of C++, 1994]

这篇关于async_resolve中boost :: asio :: ip :: tcp :: resolver :: iterator的生命周期是多长?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆