Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过多个嵌套的协同路由进行超级发送_C++_Async Await_C++20_C++ Coroutine - Fatal编程技术网

C++ 通过多个嵌套的协同路由进行超级发送

C++ 通过多个嵌套的协同路由进行超级发送,c++,async-await,c++20,c++-coroutine,C++,Async Await,C++20,C++ Coroutine,我试图理解新的协同程序在C++20中到底是如何工作的,但除了一些非常琐碎的例子之外,我无法让它工作 我的目标是创建深层嵌套函数,允许大多数内部函数中断并将控制返回给大多数外部代码,在某种条件下,它将控制权返回给该内部函数。 这是有效的setjmp和longjmp 我用在网络中找到的一些示例来修改一些代码: #include <iostream> #include <coroutine> #include <optional> template <typ

我试图理解新的协同程序在C++20中到底是如何工作的,但除了一些非常琐碎的例子之外,我无法让它工作

我的目标是创建深层嵌套函数,允许大多数内部函数中断并将控制返回给大多数外部代码,在某种条件下,它将控制权返回给该内部函数。 这是有效的
setjmp
longjmp

我用在网络中找到的一些示例来修改一些代码:

#include <iostream>
#include <coroutine>
#include <optional>

template <typename T>
struct task 
{
    struct task_promise;

    using promise_type = task_promise;
    using handle_type = std::coroutine_handle<promise_type>;

    mutable handle_type m_handle;

    task(handle_type handle)
        : m_handle(handle) 
    {

    }

    task(task&& other) noexcept
        : m_handle(other.m_handle)
    {
        other.m_handle = nullptr;
    }

    bool await_ready()
    {
        return m_handle.done();
    }

    bool await_suspend(std::coroutine_handle<> handle)
    {
        if (!m_handle.done()) {
            m_handle.resume();
        }
        return !m_handle.done();
    }

    auto await_resume()
    {
        return result();
    }

    T result() const
    {     
        if (!m_handle.done())
            m_handle.resume();

        return *m_handle.promise().m_value;
    }

    //manualy wait for finish
    bool one_step()
    {
        if (!m_handle.done())
            m_handle.resume();
        return !m_handle.done();
    }

    ~task()
    {
        if (m_handle)
            m_handle.destroy();
    }

    struct task_promise 
    {
        std::optional<T>    m_value {};

        auto value()
        {
            return m_value;
        }

        auto initial_suspend()
        {
            return std::suspend_always{};
        }

        auto final_suspend()
        {
            return std::suspend_always{};
        }

        auto return_value(T t)
        {
            m_value = t;
            return std::suspend_always{};
        }

        task<T> get_return_object()
        {
            return {handle_type::from_promise(*this)};
        }

        void unhandled_exception()
        {
            std::terminate();
        }

        void rethrow_if_unhandled_exception()
        {

        }
    };

};

static task<int> suspend_one()
{
    std::cout<< "suspend_one in\n";
    co_await std::suspend_always();
    std::cout<< "suspend_one return\n";
    co_return 1;
}
static task<int> suspend_two()
{
    std::cout<< "suspend_two -> suspend_one #1\n";
    auto a = co_await suspend_one();
    std::cout<< "suspend_two -> suspend_one #2\n";
    auto b = co_await suspend_one();
    std::cout<< "suspend_two return\n";
    co_return a + b;
}

static task<int> suspend_five()
{
    std::cout<< "suspend_five -> suspend_two #1\n";
    auto a = co_await suspend_two();
    std::cout<< "suspend_five -> suspend_one #2\n";
    auto b = co_await suspend_one();
    std::cout<< "suspend_five -> suspend_two #3\n";
    auto c = co_await suspend_two();
    std::cout<< "suspend_five return\n";
    co_return a + b + c;
}

static task<int> run()
{
    std::cout<< "run -> suspend_two #1\n";
    auto a = co_await suspend_two();
    std::cout<< "run -> suspend_one #2\n";
    auto b = co_await suspend_one();
    std::cout<< "run -> suspend_five #3\n";
    auto c = co_await suspend_five();
    std::cout<< "run -> suspend_one #4\n";
    auto d = co_await suspend_one();
    std::cout<< "run -> suspend_two #5\n";
    auto e = co_await suspend_two();
    std::cout<< "run return\n";
    co_return a + b + c + d + e;
}

int main()
{
    std::cout<< "main in\n";
    auto r = run();
    std::cout<< "main -> while\n";
    while (r.one_step()){  std::cout<< "<<<< while loop\n"; }

    std::cout<< "main return\n";
    return r.result();
}

我的
任务
版本可能已完全损坏,但我不知道在哪里可以找到此错误,也不知道它应该是什么样子。
或者只是我想要实现的东西不受C++20支持
co_yeld
可能是解决方案的候选,因为手动嵌套它们看起来更可能(
for(auto z:f())co_yeld z;
)但这个问题的目的是理解C++20功能的内部机制,它解决了一些现存的问题。

在深入挖掘和阅读文档后,我得出如下结论:


//手动等待完成
bool one_step()
{
如果(!m_handle.done())
m_handle.resume();
return!m_handle.done();
}
完全被破坏并向后完成。如果内部任务未完成,则不能执行
m\u handle.resume()
,如
m\u handle.internal.done()
。 这意味着我们需要先“移动”最内部的任务,然后才能移动外部的任务

这是新版本的“工作”,可能我错过了一些细节,但至少结果是类似的,我期待

#包括
#包括
#包括
名称空间
{
模板
结构任务
{
结构任务承诺;
使用承诺类型=任务承诺;
使用handle\u type=std::coroutine\u handle;
可变手柄\u型m\u手柄;
任务(句柄类型句柄)
:m_手柄(手柄)
{
}
任务(任务和其他)无例外
:m_句柄(其他.m_句柄)
{
other.m_handle=nullptr;
}
bool wait_ready()
{
返回false;
}
bool wait_suspend(std::coroutine_handle)
{
返回true;
}
bool wait_suspend(std::coroutine_handle)
{
handle.promise().m_internal_handler=m_handle;
m_handle.promise().m_outer_handler=句柄;
返回true;
}
自动等待恢复()
{
返回*m_handle.promise().m_值;
}
//手动等待完成
bool one_step()
{
自动电流=m_手柄;
while(curr)
{
如果(!curr.promise().m\u内部\u处理程序)
{
而(!curr.done())
{
当前恢复();
如果(!curr.done())
{
返回true;
}
if(curr.promise().m_outer_handler)
{
curr=curr.promise().m\u外部\u处理程序;
curr.promise().m_internal_handler=nullptr;
}
其他的
{
返回false;
}
}
打破
}
curr=curr.promise().m\u内部\u处理程序;
}
return!curr.done();
}
~task()
{
if(m_句柄)
m_handle.destroy();
}
结构任务
{
std::可选的m_值{};
std::coroutine_handle m_internal_handler{};
std::coroutine_handle m_outer_handler{};
自动值()
{
返回m_值;
}
自动初始化_suspend()
{
返回std::suspend_never{};
}
自动最终_暂停()
{
返回std::suspend_always{};
}
自动返回_值(T)
{
m_值=t;
返回std::suspend_always{};
}
任务获取\返回\对象()
{
返回{handle_type::from_promise(*this)};
}
无效未处理的\u异常()
{
std::terminate();
}
如果未处理异常()则返回无效\u
{
}
};
};
任务暂停_one()
{
标准::printf(“挂起一个\\\n”);
co_wait std::suspend_always();
标准::printf(“挂起一个/\n”);
co_返回1;
}
任务暂停(二)
{
自动a=co_wait suspend_one();
自动b=co_wait suspend_one();
co_返回a+b;
}
任务暂停(五)
{
自动a=co_wait suspend_two();
auto b=co_wait suspend_two();
co_返回1+a+b;
}
任务运行()
{
std::printf(“运行\n”);
自动a=co_wait suspend_five();
auto b=co_wait suspend_five();
auto c=co_wait suspend_five();
co_返回5+a+b+c;
}
}
int main()
{
标准::printf(“主输入”\n);
自动r=run();
std::printf(“main->while\n”);
while(r.one_step(){std::printf(“while循环\n”);}
标准::printf(“主返回\n”);
返回r.等待恢复();
}

最重要的是:

bool wait\u suspend(std::coroutine\u handle)
{
handle.promise().m_internal_handler=m_handle;
m_handle.promise().m_outer_handler=句柄;
返回true;
}
在这里,我将每个框架连接在一起,并允许我们在“向上堆叠”之前推动最内部的框架


我认为这可以算是一个穷人的堆叠式协同工作。< / P > @奥利弗:我不确定有没有。协同程序机器并不以其简洁著称。@Oliv90%的代码是我的问题,一个是不完整的实现,第二个是不符合我期望的用法。但它仍然是您可以在GCC godbolt上运行的最小工作示例。我可以使用
cppcoro
,但这将错过我的重点,因为它对我来说仍然是一种黑魔法,我不知道它是如何工作的,以及它是如何实现的self@Yankes好吧,这让我的眼睛很痛,我在评论“co_wait std::suspend_always();”时,我本来以为那里没有“步骤”,但仍然是w
std::cout<< "suspend_five -> suspend_two #3\n";