我们如何将值传递给协程

问题描述 投票:0回答:1

我想知道一种将值从调用者传递到协程的方法。

我的想法: 任何等待者类型都必须提供

await_resume() 
函数。这个函数可以向协程内部的
co_await
返回一些东西。

是否可以在awaiter内部设置值来将数据传输到协程? 本例中的问题是:我们如何在调用者内部获取等待者对象?

示例:

#include <coroutine>
#include <iostream>

struct ReturnObject {
    struct promise_type {
        unsigned value_;

        ReturnObject get_return_object() 
        {   
            return ReturnObject 
            {
                .h_ = std::coroutine_handle<promise_type>::from_promise(*this)
            };
        }

        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void unhandled_exception() {}
    };  

    std::coroutine_handle<promise_type> h_; 
    operator std::coroutine_handle<promise_type>() const { return h_; }
};

struct MyAwaiter
{
    bool suspend;
    bool await_ready() const noexcept { return suspend; }
    void await_suspend( std::coroutine_handle<> ) const noexcept { std::cout << "My awaiter suspend" << std::endl;}
    std::string await_resume() const noexcept { std::cout << "My awaiter resume" << std::endl; return "Test!";}
};


    ReturnObject
counter()
{
    for (unsigned i = 0;; ++i)
    {   
        std::cout << "i: " << i << std::endl;
        std::string ret = co_await MyAwaiter{false};
        std::cout << "Ret: " << ret << std::endl;
    }
}

int main()
{
    std::coroutine_handle<ReturnObject::promise_type> h = counter();
    ReturnObject::promise_type &promise = h.promise();

    for (int i = 0; i < 3; ++i)
    {   
        std::cout << "Next iteration" << std::endl;
        h();
/// how we can get the awaiter object here??? If we can get it, we can modify 
/// it to pass data to the coroutine. Is this possible?
    }
    h.destroy();
}

也许我完全错了,还有其他方法可以将数据从调用者传递到协程。如果是这样:请给我一个提示,最好是给我一个最小的工作示例。

c++ coroutine
1个回答
0
投票

await_suspend
会发送一个
std::coroutine_handle<void>
,您可以重载它来匹配
std::coroutine_handle<ReturnObject::promise_type>
,这样它的
.promise()
成员将返回原始的 Promise 对象。

void await_suspend( std::coroutine_handle<ReturnObject::promise_type> h) noexcept { 
    std::cout << "My awaiter suspend on ReturnObject" << std::endl;
    h.promise().awaiter = this;
}

然后在主程序中就可以使用了。

std::cout << promise.awaiter->data << '\n';

完整示例

#include <coroutine>
#include <iostream>


struct MyAwaiter;

struct ReturnObject {
    struct promise_type {
        unsigned value_;

        ReturnObject get_return_object() 
        {   
            return ReturnObject 
            {
                .h_ = std::coroutine_handle<promise_type>::from_promise(*this)
            };
        }
        MyAwaiter* awaiter = nullptr;
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void unhandled_exception() {}
    };  

    std::coroutine_handle<promise_type> h_; 
    operator std::coroutine_handle<promise_type>() const { return h_; }
};

struct MyAwaiter
{
    bool suspend;
    bool await_ready() const noexcept { return suspend; }
    void await_suspend( std::coroutine_handle<ReturnObject::promise_type> h) noexcept { 
    std::cout << "My awaiter suspend on ReturnObject" << std::endl;
    h.promise().awaiter = this;
    }
    void await_suspend( std::coroutine_handle<> ) const noexcept { std::cout << "My awaiter suspend" << std::endl;}
    std::string data = "foo";
    std::string await_resume() const noexcept { std::cout << "My awaiter resume" << std::endl; return "Test!";}
};


    ReturnObject
counter()
{
    for (unsigned i = 0;; ++i)
    {   
        std::cout << "i: " << i << std::endl;
        std::string ret = co_await MyAwaiter{false};
        std::cout << "Ret: " << ret << std::endl;
    }
}

int main()
{
    std::coroutine_handle<ReturnObject::promise_type> h = counter();
    ReturnObject::promise_type &promise = h.promise();

    for (int i = 0; i < 3; ++i)
    {   
        std::cout << "Next iteration" << std::endl;
        h();
        std::cout << promise.awaiter->data << '\n';
    }
    h.destroy();
}

神箭链接

© www.soinside.com 2019 - 2024. All rights reserved.