qcoro/qcoro

Task::then() should consume the original task and leave it empty

Opened this issue · 0 comments

Right now it's possible to do this:

auto task = my_coroutine();
auto subtask = task.then([]() -> QCoro::Task<> { .... });

co_await task;
co_await subtask;

This means that it's effectively possible to co_await on task from multiple places, making it behave somewhat like a SharedTask, but not really (Task is not copyable for example). Also it makes the code internally more complex.

Thus I propose to reduce the API to make .then() available only on rvalue or xvalue Task, so that

auto task = my_coroutine().then([]() -> QCoro::Task<> { ... });

is valid, and

auto task = my_coroutine();
auto subtask = task.then([]() -> QCoro::Task<> { ... });

is invalid.

Finally, there's this case:

auto task = my_coroutine();
auto subtask = std::move(task).then([]() -> QCoro::Task<>{ ... });

This should compile and should leave task in a moved-from state, further we should define that co_awaiting a moved-from Task is an error. We can choose to

  1. assert, or
  2. print a runtime warning and suspend indefinitely (since the task is not assigned to any coroutine anymore that would resume us)

I still need to think this through properly, but I think it's the right thing to do.

If people want to attach .then() continuation to an lvalue task, they should use QCoro::SharedTask which can be copied (once I implement it 😆 ), so that the .then() continuation can internally capture a copy of the shared task.