On Tuesday, June 30th, 2026 at 2:45 PM, Rainer Deyke via Boost <boost@lists.boost.org> wrote:
The strength of coroutines is that they allow chains of callbacks to be written as if they were linear functions. Using capy::run reads like a callback. Using resume_on reads like a linear function.
Callback version:
task<> f() { auto image = co_await load_image(); main_thread_callbacks.push_back([image = std::move(image)] { upload_texture_to_opengl(image); }); }
capy::run version:
task<> f() { auto image = co_await load_image(); capy::run(main_thread_executor)([image = std::move(image)] { upload_texture_to_opengl(image); }); }
resume_on version:
task<> f() { auto image = co_await load_image(); resume_on(main_thread_executor); upload_texture_to_opengl(image); }
Can you see the similarity of the first two, and how the third one differs?
I found your argument compelling which led to me to think more about resume_on(). I also injected my own assumption that you meant "co_await resume_on(ex);" -- correct me if I'm wrong. Let's explore another example: task<> task_B() { co_await resume_on( other_ex ); } task<> task_A() { for(;;) co_await task_B(); } I think this may illustrate the point of contention. If you launch task_A on a certain executor, we currently can make that guarantee to the user that task_A will run on said executor. I suspect the implementation you desire for resume_on(ex) is essentially a cheap/efficient executor switch. If we did that, task_B can switch the executor that task_A resumes on which breaks what we're trying to do here. If that implementation is not correct, then it needs to move closer to what run() already does.