gpt4 book ai didi

c++ - boost async_* 函数和 shared_ptr 的

转载 作者:IT老高 更新时间:2023-10-28 21:50:51 26 4
gpt4 key购买 nike

我经常在代码中看到这种模式,将 shared_from_this 作为第一个参数绑定(bind)到成员函数并使用 async_* 函数调度结果。这是另一个问题的示例:

void Connection::Receive()
{
boost::asio::async_read(socket_,boost::asio::buffer(this->read_buffer_),
boost::bind(&Connection::handle_Receive,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}

使用 shared_from_this() 而不是 this 的唯一原因是在调用成员函数之前保持对象处于事件状态。但除非在某处有某种 boost 魔法,因为 this 指针的类型是 Connection*,这就是 handle_Receive 可以采用的所有内容,而 smart返回的指针应立即转换为常规指针。如果发生这种情况,则没有任何东西可以使对象保持活力。当然,调用 shared_from_this 时没有指针。

但是,我经常看到这种模式,我不敢相信它会像我认为的那样完全被打破。当操作完成时,是否有一些 Boost 魔术导致 shared_ptr 稍后转换为常规指针?如果是这样,这是否记录在某处?

特别是,它是否在某处记录了共享指针将保持存在直到操作完成?在强指针上调用 get_pointer 然后在返回的指针上调用成员函数是不够的,除非强指针直到成员函数返回才被销毁。

最佳答案

简而言之,boost::bind创建 boost::shared_ptr<Connection> 的拷贝从 shared_from_this() 返回, 和 boost::asio可以创建处理程序的拷贝。处理程序的拷贝将保持事件状态,直到发生以下情况之一:

  • 处理程序已由服务的run() 所在的线程调用。 , run_one() , poll()poll_one()成员函数已被调用。
  • io_service被销毁了。
  • io_service::service拥有处理程序的通过 shutdown_service() 关闭.

以下是文档的相关摘录:

  • boost::bind documentation :

    The arguments that bind takes are copied and held internally by the returned function object.

  • boost::asio io_service::post :

    The io_service guarantees that the handler will only be called in a thread in which the run(), run_one(), poll() or poll_one() member functions is currently being invoked. [...] The io_service will make a copy of the handler object as required.

  • boost::asio io_service::~io_service :

    Uninvoked handler objects that were scheduled for deferred invocation on the io_service, or any associated strand, are destroyed.

    Where an object's lifetime is tied to the lifetime of a connection (or some other sequence of asynchronous operations), a shared_ptr to the object would be bound into the handlers for all asynchronous operations associated with it. [...] When a single connection ends, all associated asynchronous operations complete. The corresponding handler objects are destroyed, and all shared_ptr references to the objects are destroyed.


虽然日期为 (2007),但 Networking Library Proposal for TR2 (Revision 1)源自 Boost.Asio。栏目5.3.2.7. Requirements on asynchronous operationsasync_ 的参数提供了一些详细信息功能:

In this clause, an asynchronous operation is initiated by a function that is named with the prefix async_. These functions shall be known as initiating functions. [...] The library implementation may make copies of the handler argument, and the original handler argument and all copies are interchangeable.

The lifetime of arguments to initiating functions shall be treated as follows:

  • If the parameter is declared as a const reference or by-value [...] the implementation may make copies of the argument, and all copies shall be destroyed no later than immediately after invocation of the handler.

[...] Any calls made by the library implementation to functions associated with the initiating function's arguments will be performed such that calls occur in a sequence call1 to calln, where for all i, 1 ≤ i < n, calli precedes call i+1.

因此:

  • 实现可能会创建处理程序的拷贝。在示例中,复制的 处理程序 将创建 shared_ptr<Connection> 的拷贝,增加 Connection 的引用计数实例,而 handler 的拷贝仍然存在。
  • 实现可能会在调用 handler 之前销毁 handler。如果异步操作在 io_serive::service 时未完成,则会发生这种情况。正在关闭或 io_service被摧毁。在示例中,处理程序的拷贝将被销毁,从而减少 Connection 的引用计数。 ,并可能导致 Connection要销毁的实例。
  • 如果 handler 被调用,那么一旦从处理程序返回执行,所有处理程序的拷贝将立即被销毁。同样,处理程序的拷贝将被销毁,从而减少 Connection 的引用计数。 ,并可能导致其被破坏。
  • asnyc_ 相关的函数的参数,将按顺序执行,而不是并发执行。这包括 io_handler_deallocateio_handler_invoke .这保证了在调用 handler 时不会释放 handler。在 boost::asio 的大部分地区实现时,处理程序被复制或移动到堆栈变量,一旦执行退出声明它的 block ,就允许销毁发生。在示例中,这确保了 Connection 的引用计数在调用 handler 期间将至少为 1。

关于c++ - boost async_* 函数和 shared_ptr 的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11356742/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com