Re: [boost] Fwd: [boost.async] Andrzej's review
Andrzej, Firstly, it's weird I don't see this on the Boost mailing list. In fact, I seem to only get about half the mail to the Boost mailing list ever since they fiddled with the servers. So thanks for sending this review to me directly. I've also caught up with all your other posts on Boost.Async from https://lists.boost.org/Archives/boost/2023/09/index.php, none of which I had seen before now. Thanks for the review. If you don't mind if I jump in with a few bits myself which are intentionally not about the review itself ... On 29/09/2023 14:08, Andrzej Krzemienski wrote:
Regarding the choice and design of "coroutine types", I have certain reservations. It is still not clear to me why we have two -- promise and task -- and when I should use which. The docs give some answer: promise is eager, task can be awaited/spawned on another executor than it was created on. But is that it? I sense that there is a good reason to have them as two types, a better/clearer one than this described in the docs.But I fail to see it, and the docs do not explain it clearly enough, I think.
Outcome calls the same thing eager and lazy. I felt lazy is a more descriptive name than task. I mean, why should a task be lazy rather than eager? The reason is simply because Lewis Baker happened to choose that default, and it's stuck since, but there isn't any strong rational for "task ~= lazy" other than convention.
One problem is how the `generator` signals that it has finished. In all the examples it has to create a dummy value. I hear from Klemens that it is a necessity imposed by the coroutine design in C++. I do not feel competent to confirm it or not. But I note that std::generator does not require the user to `co_return` anything. And that asio::experimental::coro does allow the user to specify that they do not want to co_return even if they co_yield things.
It's been a while since I used coroutine generators, but my memory is when the coroutine exits then the generator returns its end iterator value. I don't remember dummy values. But then I 99.9% use C++ coroutines with Result, to avoid ever throwing C++ exceptions through C++ coroutine machinery which *still* is riddled with showstopper bugs in current compilers.
On the documentation. The only other library offering coroutine support and any documentation that I know of is Boost.ASIO.
There are actually a good few Boost libraries with C++ coroutine support now in one form or other. Outcome is obviously one, but there is at least one other apart from ASIO (somebody else may remind me which one now). Boost.Async's are much fuller featured obviously, but even Outcome's simple ones are usually good enough for most use cases. You don't need to use them with Result either.
But this doesn't work, because now I am co_yield-ing from a non-coroutine. And I have to resort to manually inspecting the variant, which is taught to be error prone.
BTW tip for the future: just use helper coroutine lambdas if you need to do coroutine stuff from within normal code. These normally don't work with the Coroutine support from cppcoro, stdexec, libunifex nor ASIOs because their coroutines don't allow it. But Boost.Async's does, as does Boost.Outcome's. It cannot be understated the usefulness of being able to dip in and out of "coroutine land" using inline lambdas from normal code. It makes C++ coroutines vastly more convenient to use. Niall
On Fri, Sep 29, 2023 at 7:47 AM Niall Douglas via Boost < boost@lists.boost.org> wrote:
Firstly, it's weird I don't see this on the Boost mailing list. In fact, I seem to only get about half the mail to the Boost mailing list ever since they fiddled with the servers.
Point of reference: I got the review through the mailing list. Thanks
participants (2)
-
Niall Douglas
-
Vinnie Falco