可以复制C ++ 20协程吗?

艾杰

我一直在玩C ++ 20协程,并尝试将我的一些代码库移到使用它们。不过,我遇到了一个问题,因为似乎新的协程似乎无法复制。这些generator对象已删除了复制构造函数和复制赋值运算符,而我研究的内容似乎都没有办法。

能做到吗?

作为参考,我编写了一个小测试程序,尝试复制C ++ 20协程失败,并且尝试成功执行相同的操作boost::asio::coroutine这使用的是Visual Studio 2019版本16.3.7

#include <sdkddkver.h>
#include <string>
#include <algorithm>
#include <iterator>
#include <experimental\resumable>
#include <experimental\generator>
#include <cassert>

#include <boost\asio\yield.hpp>

namespace std_coroutines {
    auto letters() {
        for (auto c = 'a'; ; ++c)
            co_yield c;
    }

    void run() {
        auto gen = letters();
        std::string s1, s2;
        std::copy_n(gen.begin(), 3, std::back_inserter(s1)); // append "abc" to s1
        //auto gen_copy = gen; // doesn't compile

        std::copy_n(gen.begin(), 3, std::back_inserter(s1)); // append "def" to s1
        //std::copy_n(gen_copy.begin(), 3, std::back_inserter(s2)); // append "def" to s2

        assert(s1 == "abcdef");
        assert(s2 == "def"); // fails
    }
};// namespace std_coroutines

namespace boost_asio_coroutines {
    struct letters : boost::asio::coroutine {
        char c = 'a';
        char operator()() {
            reenter(this) for (;; ++c)
            {
                yield return c;
            }
        }
    };

    void run() {
        auto gen = letters();
        std::string s1, s2;
        std::generate_n(std::back_inserter(s1), 3, std::ref(gen)); // append "abc" to s1
        auto gen_copy = gen;
        std::generate_n(std::back_inserter(s1), 3, std::ref(gen)); // append "def" to s1
        std::generate_n(std::back_inserter(s2), 3, std::ref(gen_copy)); // append "def" to s2

        assert(s1 == "abcdef");
        assert(s2 == "def");
    }
} // namespace boost_asio_coroutines

int main() {
    boost_asio_coroutines::run();
    std_coroutines::run();
}
安迪

TS并未明确禁止复制。如您所述,std::experimental::generatorpromise对象已删除复制操作。我认为最初的实现对于副本还是比较保守的,因为有很多需要考虑的地方。

协同程序管理的句柄协程的激活上下文,正式称为协同程序状态N4775此状态是在堆还是堆栈上(出于优化原因)是实现定义的。协程存储本身的格式也是实现定义的。

只要沿着shared_ptr确立了协程句柄的所有权语义,该实现就可以实现浅表复制weak_ptr(类比有所分散,因为只有一个协程是该状态的实际所有者,而所有其他协程都是观察者) 。

如果您要询问深层副本,那么您最终会得到两个互不影响的独立生成器,那么我想所有的含义也是有可能的。

我可以想到的一些含义:

  • 深度复制函数的局部变量非常昂贵,而这种额外的分配开销可能会使用户感到意外。
  • 复制协程的句柄将始终*需要驻留在堆上,这意味着您可能最终会遇到“原始”协程性能出色而复制后的协程性能很差的情况。偶然的副本可能会无声地破坏优化。

*协程存储通过调用全局非数组new函数获得。从理论上讲,您可以重载此函数以匹配协程,但是由于存储是实现定义的,因此您必须了解您的平台。尽管如此,从理论上讲,这仍将允许您利用已保留堆栈大块的全局区域分配器

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

C ++ 20中的协程是什么?

C#协程是异步的吗?

协程可以返回std :: future吗?(无法找到此协程的promise类型)

如何检测 C++20 协程中的堆栈展开?

C ++ 20协程的Lambda生命周期说明

C ++ 20协程框架必须保留多少内存?

C ++ 20协程使用final_suspend进行延续

无栈C ++ 20协程是否有问题?

如何用C ++ 20协程说Hello World?

C ++ 20协程:实现可期待的未来

Clang 中 C++20 协程支持的状态如何?

在 C++20 中删除协程的复制/移动函数并实例化它是否合法?

可以暂停带有超时的协程吗?

可以始终使用WorkManager代替协程吗?

定位JavaScript时,可以在Kotlin中使用协程吗?

协程可以在Python中产生值吗?

我可以在异步协程上使用阻塞锁吗?

我可以在 while() 中放入协程吗?

C ++ 20协程,std返回类型和状态持久性

对称传输不会阻止 C++20 协程的堆栈溢出

您可以将协程添加到事件循环队列的前面吗?

我可以在没有 asyncio 的情况下运行 Python 协程吗?

协程恢复后,`co_yield`可以从调用者返回值吗?

SendChannel.offer,CompletableDeferred.complete和类似名称可以在协程外部调用吗?

我可以在纯Java项目中使用由Kotlin协程构建的库吗?

可以在生产中使用“实验性” Kotlin协程吗?

python asycio协程可以有一个没有等待的代码路径吗?

可以在没有等待或屈服的情况下实现Python协程吗?

Python协程可以在不先执行“下一步”的情况下“发送”吗?