是否有必要在std::coroutine_Handle上调用Destroy?

2022-05-16 00:00:00 coroutine c++ c++20
std::coroutine_handle是C++20新协程的重要组成部分。例如,生成器经常(Always?)用它吧。在我看到的所有示例中,句柄都是在协例程的析构函数中手动销毁的:

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

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

这真的有必要吗?如果是,为什么coroutine_handle还没有这样做,有没有RAII版本的coroutine_handle是这样的,如果我们省略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的析构函数中调用它。

解决方案

这是因为您希望协程比其句柄更长,句柄应该是非所属。句柄只是一个视图,与std::string_view -> std::string非常相似。如果std::string_view超出作用域,您不希望std::string自我销毁。

如果您确实想要此行为,为其创建自己的包装将是微不足道的。

话虽如此,标准specifies:

当控制流出 协程或destroy成员函数 ([coroutine.handle.resumption])协程句柄 ([coroutine.handle]),表示调用了协程。

协程状态将在完成运行后自行清理,因此除非控制未流出末尾,否则不会泄漏。

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

相关文章