【问题标题】:Boost.asio and asynchronous chain, unique_ptr?Boost.asio 和异步链,unique_ptr?
【发布时间】:2016-05-09 06:39:10
【问题描述】:

我对异步编程不是很熟悉,我有一个问题。

我的问题如下。鉴于 boost.asio 中 C++11 的 echo_server 示例:http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp

我想知道 std::make_shared<session> 在 C++14 中是否可以在 C++14 中替换为 std::unique_ptr<session>,从而避免引用计数的开销。

我不确定,因为我们有 shared_from_this(),但没有 unique_from_this() 这样的东西,那么我如何从 this 内部访问 unique_ptr<session>?。

【问题讨论】:

  • 您知道开销是每个实例的额外内存的单个指针以及共享 ptr 创建和删除时的引用计数增加——否则它与普通指针完全相同。此外,不清楚您指的是哪个 shared_ptr,因为该示例中有多个。
  • “unique_from_this”的概念甚至没有意义。你不能简单地任意创建一个指向内存地址的唯一指针,因为你会有一个关于谁清理内存的竞争条件。

标签: c++ asynchronous boost boost-asio asyncsocket


【解决方案1】:

不,在asio 编程中使用 shared_ptr 是惯用的。

这个想法是未完成处理程序的数量与启动异步操作的对象的共享计数相匹配。这是通过将管理对象的shared_ptr 的副本绑定到处理函数对象中来实现的。

c++11/14 的方法是将boost::shared_ptr 替换为std::shared_ptrstd::bind、lambdas 等也可以与 asio 完美配合)。

更新,现在我完全理解了这个问题:

在您链接的示例中,我认为您指的是在方法 go() 中创建的名为 self 的 shared_ptr ?如果你愿意,你可以在没有 shared_ptr 的情况下编写它。你必须把它作为 go() 的最后一行删除。您还必须记住捕获任何异常以确保采用此代码路径。当然,可以设置一个 unique_ptr 来执行此操作,但是在会话的构建和成功创建采用 unique_ptr 之间存在生命周期管理问题。 shared_ptr 减轻了一个原子公司成本的管理负担......

在这种情况下,答案绝对是“是”,但恕我直言,我会建议,因为它更脆弱。

【讨论】:

  • 据我了解,您的会话对象将通过处理程序的管道,一次一个。您的会话状态永远不会共享。为什么 unique_ptr 没有意义?关键是当最新的处理程序完成时,内存将被释放。这是真的吗?
  • 最新的还是最后的?如果有任何涉及会话的未完成处理程序,它们最终都会触发(即使由于破坏套接字而被取消)。您可以保留未完成处理程序的手动计数并在会话达到零时删除您的会话,但为什么呢? shared_ptr 正是这样做的,几乎没有开销。
  • 如果有会话,asio 的循环中仍有工作。它不会完成。所以,如果我没记错的话,将会发生以下情况:如果你对每个会话使用 unique_ptr,只有当没有更多工作时,循环才会结束。我同意开销可能很低,这更像是一个理论问题:)
  • 在您链接的示例中,我认为您指的是在 go() 方法中创建的名为 self 的 shared_ptr ?如果你愿意,你可以在没有 shared_ptr 的情况下编写它。您必须将delete this 作为go() 的最后一行。您还必须记住捕获任何异常以确保采用此代码路径。当然,可以设置一个 unique_ptr 来执行此操作,但是在会话的构建和成功创建采用 unique_ptr 之间存在生命周期管理问题。 shared_ptr 减轻了一个原子公司成本的管理负担。
  • @GermánDiago ...在这种情况下,当我说“不”时,我的意思是“是”:)
【解决方案2】:

据我了解,您的会话对象将通过一系列处理程序,一次一个。您的会话状态永远不会共享。为什么 unique_ptr 没有意义?关键是当最新的处理程序完成时,内存将被释放。这是真的吗?

是的,这就是诀窍。该库是围绕可复制的完成处理程序设计的。

如果您担心开销,请确实避免 shared_ptr。

在这种情况下,只需携带对具有外部控制生命周期的某个状态的引用。只需确保它保持活动状态(就像您对 io_service 对象本身所做的那样)。

【讨论】:

  • 我明白这一点,但这并没有回答我原来的问题,即:我可以使用一个 unique_ptr 并执行一个 unique_pr ,它将自动进行到会话本身结束吗?
  • 如果你明白了,为什么要did you ask?另外,我不知道如何更清楚地回答。 Is std::unique_ptr copyable?如果不是,那么直接在完成处理程序中使用它是不可能的,并且在间接“覆盖”时充其量是一个杂物。我的建议在我的回答中。
  • 在 C++14 中,您可以捕获 [my_ptr=move(my_ptr)] 但我想知道是否还有其他问题。最关心“unique_from_this()”或类似的东西,所以我想知道这是否真的可以实现:用 unique_ptr 替换并有类似的东西。
  • 您可以,但这不会使结果可复制。正如其他人提到的那样,“unique_from_this”是零意义的。我对“类似的东西”的建议从一开始就在答案中。 delete this 是破解该结果的一种方法。我认为这是一种代码味道,但它可能接近你的思维模式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多