【问题标题】:Is it necessary to call destroy on a std::coroutine_handle?是否有必要在 std::coroutine_handle 上调用销毁?
【发布时间】:2018-06-18 05:02:10
【问题描述】:

std::coroutine_handle 是 C++20 新协程的重要组成部分。例如,生成器经常(总是?)使用它。在我见过的所有示例中,句柄都是在协程的析构函数中手动销毁的:

struct Generator {
    // Other stuff...
    std::coroutine_handle<promise_type> ch;

    ~Generator() {
        if (ch) ch.destroy();
    }
}

这真的有必要吗?如果是,为什么coroutine_handle 还没有完成这项工作,是否存在具有这种行为方式的coroutine_handle 的RAII 版本,如果我们省略destroy 调用会发生什么?

例子:

  1. https://en.cppreference.com/w/cpp/coroutine/coroutine_handle(谢谢463035818_is_not_a_number
  2. C++20 标准还在 9.5.4.10 示例 2 中提到它(在 N4892 上检查)。
  3. (德语)https://www.heise.de/developer/artikel/Ein-unendlicher-Datenstrom-dank-Coroutinen-in-C-20-5991142.html
  4. https://www.scs.stanford.edu/~dm/blog/c++-coroutines.html - 提到如果不调用它会泄漏,但没有引用标准中的段落或为什么不在std::coroutine_handle 的析构函数中调用它。

【问题讨论】:

  • 嗯,在我见过的所有示例中,它从未在任何协程的析构函数中手动销毁...
  • @Fureeish 提问哪些例子更好。
  • @463035818_is_not_a_number 实际上甚至 C++20 标准(我查看了 n4892,但我猜真正的版本也有类似的措辞)包括它。见 9.5.4.10。
  • 我在这里找到了一个示例 en.cppreference.com/w/cpp/coroutine/coroutine_handle。不过,我认为您应该在问题中引用一个示例,以便其他人知道您在说什么
  • 根据我在 CPPwinrt 方面的经验......这取决于。如果您使用的是生成器,则需要调用destroy。如果你不是,那么没有。但我不会认为这是权威的。编辑cppcoro 有一些合适的例子。

标签: c++ c++20 coroutine


【解决方案1】:

这是因为您希望协程能够比其句柄长,句柄应该是非拥有的。句柄只是一个“视图”,很像std::string_view -&gt; std::string。如果std::string_view 超出范围,您不希望std::string 自行破坏。

如果您确实想要这种行为,那么围绕它创建自己的包装器将是微不足道的。

话虽如此,标准specifies

当控制流结束时,协程状态被破坏 协程destroy成员函数 ([coroutine.handle.resumption]) 的协程句柄 调用协程的([coroutine.handle])

协程状态在运行结束后会自行清理,因此不会泄漏,除非控制没有从最后流出。

当然,在生成器的情况下,控制通常不会流到最后,因此程序员必须手动销毁协程。协程有多种用途,因此标准不能真正无条件地强制句柄析构函数调用destroy()

【讨论】:

  • 如果我理解正确的话,生成器控制流通常不会自行结束,因为它们内部通常有无限循环。
  • @Brotcrunsher 对于生成器的情况通常是这样,但这不是协程的唯一用途,因此您不能无条件地在标准 PoV 的句柄析构函数上调用 destroy()
  • 非常接近接受这个答案。唯一缺少的是标准中的引用,说明如果我们未能调用 destroy 会发生什么。可能是泄漏,但也可能是 UB。
  • @Brotcrunsher AFAIK 标准对此并没有多说。它只给了我们在未挂起的协程上调用destroy的反情况,那就是UB。我相信不调用destroy() 意味着你有一个协程状态,它存在于内存中的某个地方,你不能再访问或破坏,从而导致泄漏。就像不在new 上打电话给delete
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-06
  • 1970-01-01
  • 2014-01-22
  • 2012-12-23
  • 2013-01-21
  • 2012-11-07
相关资源
最近更新 更多