[PATCH] D134009: [Coroutines] Introduce `always_complete_coroutine` attribute to guide optimization (1/2)

Adrian Vogelsgesang via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 16 13:33:59 PDT 2022


avogelsgesang added a comment.

high-level design comment (I didn't look at the code; wouldn't understand it anyway):
I think there is another important case to cover, besides "a coroutine can only be destroyed after it ran to its final suspension point":
"A coroutine can only be destroy after it ran to its final suspension point *or* before it executed until after its initial suspension point"

Assuming an execution model similar to https://github.com/lewissbaker/cppcoro, i.e. coroutines are always constructed in suspended state, and there is a `when_all` function to combine multiple coroutine tasks, I tend to write code like

  lazy<int> foo(std::unique_ptr<int>);
  lazy<int> bar(std::unique_ptr<float>);
  
  lazy<int> foobar() {
       lazy<int> coro1 = foo(make_unique<int>(12));
       lazy<int> coro2 = bar(make_unique<float>(1.2));
       auto [x,y] = co_await when_all(std::move(coro1), std::move(coro2));
       return x + y;
  }

In this case, `coro1` and `coro2` can be destroyed after both of them finished execution (i.e. after the `when_all` returned).
In addition, `coro1` could be destroyed before it is ever co_awaited on, in case `bar` throws.
However, if `coro1`/`coro2` ever left their initial suspend point, i.e. if they were ever co_awaited on, we know for sure that they won't be destroyed while suspended at one of the intermediate suspension points.
I guess this usage pattern is rather common? If so, I think we should design this attribute, such that it also accomodates that use case...


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134009/new/

https://reviews.llvm.org/D134009



More information about the llvm-commits mailing list