admin管理员组

文章数量:1122846

I want to know a method to pass values from the caller to the coroutine.

My idea: Any awaiter type must provide a await_resume() function. This function can return something to the co_await inside the coroutine.

Is it possible to set the value inside the awaiter to transport data to the coroutine? The question in this case is: How we can get the awaiter object inside the caller?

Example:

#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();
}

Maybe I am totally wrong and there is any other way to pass data from the caller to the coroutine. If so: Please give me a hint and in best case a minimal working example.

I want to know a method to pass values from the caller to the coroutine.

My idea: Any awaiter type must provide a await_resume() function. This function can return something to the co_await inside the coroutine.

Is it possible to set the value inside the awaiter to transport data to the coroutine? The question in this case is: How we can get the awaiter object inside the caller?

Example:

#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();
}

Maybe I am totally wrong and there is any other way to pass data from the caller to the coroutine. If so: Please give me a hint and in best case a minimal working example.

Share Improve this question asked Nov 22, 2024 at 14:06 KlausKlaus 25.6k9 gold badges65 silver badges129 bronze badges 0
Add a comment  | 

1 Answer 1

Reset to default 1

await_suspend accepts a std::coroutine_handle<void> which you can overload to match std::coroutine_handle<ReturnObject::promise_type> and it will be called if it is awaited by that promise_type, and handle.promise() will give you access to the 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; // new member in promise_type
}

then in the caller you can get this information from the promise and modify the awaiter.

h.promise().awaiter->data = "foo";

Both the awaiter and the return object have access to the promise_type, which should be used to store the relevant information, like why the coroutine was suspended, and what it is waiting on, so the caller can respond to the awaiter.

full example

#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;
    std::string await_resume() const noexcept { std::cout << "My awaiter resume" << std::endl; return data;}
};


    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.promise().awaiter->data = "foo";
        h();
    }
    h.destroy();
}

godbolt link

本文标签: chow we can pass values to a coroutineStack Overflow