CodexBloom - Programming Q&A Platform

C++20 Coroutines - implementing Promise and Future when using std::suspend_always

👀 Views: 2 💬 Answers: 1 📅 Created: 2025-06-01
c++20 coroutines future promise C++

I've encountered a strange issue with I've encountered a strange issue with I'm working on a C++20 project where I'm trying to implement asynchronous tasks using coroutines... I have a coroutine that returns a `std::future<int>` via a promise. However, I encounter an unexpected behavior when I use `std::suspend_always` in the coroutine's body. Here’s the simplified code I'm working with: ```cpp #include <coroutine> #include <future> #include <iostream> struct Promise { std::promise<int> promise; auto get_return_object() { return promise.get_future(); } std::suspend_always initial_suspend() { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void return_void() {} void unhandled_exception() { std::terminate(); } void yield_value(int value) { promise.set_value(value); std::suspend_always(); } }; struct Coroutine { using promise_type = Promise; std::coroutine_handle<promise_type> handle; Coroutine(std::coroutine_handle<promise_type> h) : handle(h) {} ~Coroutine() { handle.destroy(); } }; Coroutine async_task() { co_await std::suspend_always(); // First suspension co_yield 42; // This should pass 42 to the promise } int main() { auto future = async_task(); std::cout << "Result: " << future.get() << std::endl; // Expected output: 42 return 0; } ``` However, when I run this code, I get an exception saying `std::future_error: promise already satisfied` on the line `promise.set_value(value);`. It seems like the promise is being satisfied twice or not being awaited correctly. I’ve tried removing the `std::suspend_always` in `yield_value` and just using `co_yield 42;`, but then the coroutine doesn’t suspend correctly, and I don’t get the expected output. I’m not sure how to properly manage the promise's state when using `std::suspend_always`. Can anyone guide to understand what I'm missing or how to fix this scenario? Hoping someone can shed some light on this.