Hi Everyone, I will not be able to write a decent review due to the lack of time (I am now on vacation), but I wanted to share some partial feedback. I am not well familiar with C++ coroutines. I wrote some toy examples of an async TCP echo server in ASIO in the past, to try to learn how coroutines work, but my knowledge is very superficial. I hoped to understand coroutines better from studying Boost.Async's docs. When I discovered Boost some 18 years ago, I found it useful not only because of the high quality libraries but also because of extraordinary documentation that often provided a very deep insight into the problem domain, a lot of rationale, design goals, and the documentation of engineering trade-offs of different sorts. I do not know how people feel about the importance of documentation nowadays. For me, however, it is the primary focus. I devoted like 10 hours in total for studying the docs and running some toy examples. Because I am not very good at C++ coroutines, you get a typical, I would think, feedback from a user that wants to learn how coroutines are used, what problems they solve, and what problems they do not solve. Regarding the *really* asynchronous part, promises and tasks, I guess they would work fine. By "really asynchronous" I mean the situations where a coroutine is resumed by events unpredictable by the programmer (when data arrives, when certain time passes, when an external connection is requested). I also guess that when Marcelo and Ruben say they successfully integrated Boost.Async into their projects, they meant types `task` and `promise`, rather than `generator`. My investigation was interrupted by `generator` which I cannot understand or appreciate. It feels like a type quite separate from the rest of the library. For instance, through all the simple examples in the docs, only the examples for `generator` never use the trick with `co_await async::this_coro::executor`. I needed to ask a lot of questions, and even though Klemens is very responsive and very helpful, I still do not understand how `async::generator` solves real problems. This may indicate that either I am a very slow learner, or that there is something wrong with the design of `generator`. But even if it is the former, I think I represent the average user of this library. When I try to use a C+23 std::generator, the usage is intuitive and straightforward to me. I know how to easily yield a sequence of values, and on the caller side how to easily check if I can still obtain the next value from the generator: ``` std::generator<int> seq(int from, int to) { for (int i = from; i <= to; ++i) co_yield i; } int main() { for(int i : seq(1, 4)) std::cout << i << std::endl; } ``` https://godbolt.org/z/PTvz3v4Y6 But when I try what I believe to be an analogous example in Boost.Async, I get an exception: ``` async::generator<int> seq(int from, int to) { for (int i = from; i <= to; ++i) co_yield i; } async::main co_main(int argc, char* argv[]) { auto s = seq(1, 4); while (s) { std::cout << co_await s << std::endl; } } ``` And the docs or examples don't help me understand why this use case doesn't work. The case with the eager generator that can be injected values is even weirder. I think it is wrong. Klemens thinks otherwise, but the docs do not give any convincing example of where and how it could be used. The lack of examples or description can be just that, but it could also indicate that the design for generators is missing something. In this feedback, I am only mentioning generators, because this is the place where I stuck in my review. I guess that other parts of the library do not have this problem. I am pretty sure that this library will be accepted into Boost at some point. It addresses a real need (although not necessarily the generators), and the feedback from Ruben and Marcelo are strong testimony to the quality of the library. But at this point, I am not comfortable with adding a library whose design for generators cannot be explained in the docs to the extent that I consider satisfactory. Would this library lose in usability if generators were removed? I know it is not a fair review. I only covered one subject, and my feeling is that it is not the most relevant one. So please consider it as "just feedback" rather than a review. Again, thanks Klemens for writing and sharing this library. I hope that this message does not come across as negative. I want to think that I am contributing to the quality of Boost.Async. Regards, &rzej;
On 19/08/2023 00:05, Andrzej Krzemienski via Boost wrote:
Hi Everyone, I will not be able to write a decent review due to the lack of time (I am now on vacation), but I wanted to share some partial feedback.
I am not well familiar with C++ coroutines. I wrote some toy examples of an async TCP echo server in ASIO in the past, to try to learn how coroutines work, but my knowledge is very superficial. I hoped to understand coroutines better from studying Boost.Async's docs.
When I discovered Boost some 18 years ago, I found it useful not only because of the high quality libraries but also because of extraordinary documentation that often provided a very deep insight into the problem domain, a lot of rationale, design goals, and the documentation of engineering trade-offs of different sorts. I do not know how people feel about the importance of documentation nowadays. For me, however, it is the primary focus. I devoted like 10 hours in total for studying the docs and running some toy examples. Because I am not very good at C++ coroutines, you get a typical, I would think, feedback from a user that wants to learn how coroutines are used, what problems they solve, and what problems they do not solve.
Regarding the *really* asynchronous part, promises and tasks, I guess they would work fine. By "really asynchronous" I mean the situations where a coroutine is resumed by events unpredictable by the programmer (when data arrives, when certain time passes, when an external connection is requested). I also guess that when Marcelo and Ruben say they successfully integrated Boost.Async into their projects, they meant types `task` and `promise`, rather than `generator`.
My investigation was interrupted by `generator` which I cannot understand or appreciate. It feels like a type quite separate from the rest of the library. For instance, through all the simple examples in the docs, only the examples for `generator` never use the trick with `co_await async::this_coro::executor`.
I needed to ask a lot of questions, and even though Klemens is very responsive and very helpful, I still do not understand how `async::generator` solves real problems. This may indicate that either I am a very slow learner, or that there is something wrong with the design of `generator`. But even if it is the former, I think I represent the average user of this library.
When I try to use a C+23 std::generator, the usage is intuitive and straightforward to me. I know how to easily yield a sequence of values, and on the caller side how to easily check if I can still obtain the next value from the generator:
``` std::generator<int> seq(int from, int to) { for (int i = from; i <= to; ++i) co_yield i; }
int main() { for(int i : seq(1, 4)) std::cout << i << std::endl; } ``` https://godbolt.org/z/PTvz3v4Y6
But when I try what I believe to be an analogous example in Boost.Async, I get an exception:
``` async::generator<int> seq(int from, int to) { for (int i = from; i <= to; ++i) co_yield i; }
async::main co_main(int argc, char* argv[]) { auto s = seq(1, 4); while (s) { std::cout << co_await s << std::endl; } } ```
And the docs or examples don't help me understand why this use case doesn't work. The case with the eager generator that can be injected values is even weirder. I think it is wrong. Klemens thinks otherwise, but the docs do not give any convincing example of where and how it could be used.
The lack of examples or description can be just that, but it could also indicate that the design for generators is missing something.
In this feedback, I am only mentioning generators, because this is the place where I stuck in my review. I guess that other parts of the library do not have this problem.
I am pretty sure that this library will be accepted into Boost at some point. It addresses a real need (although not necessarily the generators), and the feedback from Ruben and Marcelo are strong testimony to the quality of the library.
But at this point, I am not comfortable with adding a library whose design for generators cannot be explained in the docs to the extent that I consider satisfactory.
Would this library lose in usability if generators were removed?
I know it is not a fair review. I only covered one subject, and my feeling is that it is not the most relevant one. So please consider it as "just feedback" rather than a review.
Again, thanks Klemens for writing and sharing this library. I hope that this message does not come across as negative. I want to think that I am contributing to the quality of Boost.Async.
Regards, &rzej;
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Just a question, did you also look at the ticker example? The generator is used there. Regards, Matthijs
sob., 19 sie 2023 o 13:48 Matthijs Möhlmann
Hi Everyone, I will not be able to write a decent review due to the lack of time (I am now on vacation), but I wanted to share some partial feedback.
I am not well familiar with C++ coroutines. I wrote some toy examples of an async TCP echo server in ASIO in the past, to try to learn how coroutines work, but my knowledge is very superficial. I hoped to understand coroutines better from studying Boost.Async's docs.
When I discovered Boost some 18 years ago, I found it useful not only because of the high quality libraries but also because of extraordinary documentation that often provided a very deep insight into the problem domain, a lot of rationale, design goals, and the documentation of engineering trade-offs of different sorts. I do not know how people feel about the importance of documentation nowadays. For me, however, it is
primary focus. I devoted like 10 hours in total for studying the docs and running some toy examples. Because I am not very good at C++ coroutines, you get a typical, I would think, feedback from a user that wants to learn how coroutines are used, what problems they solve, and what problems they do not solve.
Regarding the *really* asynchronous part, promises and tasks, I guess
On 19/08/2023 00:05, Andrzej Krzemienski via Boost wrote: the they
would work fine. By "really asynchronous" I mean the situations where a coroutine is resumed by events unpredictable by the programmer (when data arrives, when certain time passes, when an external connection is requested). I also guess that when Marcelo and Ruben say they successfully integrated Boost.Async into their projects, they meant types `task` and `promise`, rather than `generator`.
My investigation was interrupted by `generator` which I cannot understand or appreciate. It feels like a type quite separate from the rest of the library. For instance, through all the simple examples in the docs, only the examples for `generator` never use the trick with `co_await async::this_coro::executor`.
I needed to ask a lot of questions, and even though Klemens is very responsive and very helpful, I still do not understand how `async::generator` solves real problems. This may indicate that either I am a very slow learner, or that there is something wrong with the design of `generator`. But even if it is the former, I think I represent the average user of this library.
When I try to use a C+23 std::generator, the usage is intuitive and straightforward to me. I know how to easily yield a sequence of values, and on the caller side how to easily check if I can still obtain the next value from the generator:
``` std::generator<int> seq(int from, int to) { for (int i = from; i <= to; ++i) co_yield i; }
int main() { for(int i : seq(1, 4)) std::cout << i << std::endl; } ``` https://godbolt.org/z/PTvz3v4Y6
But when I try what I believe to be an analogous example in Boost.Async, I get an exception:
``` async::generator<int> seq(int from, int to) { for (int i = from; i <= to; ++i) co_yield i; }
async::main co_main(int argc, char* argv[]) { auto s = seq(1, 4); while (s) { std::cout << co_await s << std::endl; } } ```
And the docs or examples don't help me understand why this use case doesn't work. The case with the eager generator that can be injected values is even weirder. I think it is wrong. Klemens thinks otherwise, but the docs do not give any convincing example of where and how it could be used.
The lack of examples or description can be just that, but it could also indicate that the design for generators is missing something.
In this feedback, I am only mentioning generators, because this is the place where I stuck in my review. I guess that other parts of the library do not have this problem.
I am pretty sure that this library will be accepted into Boost at some point. It addresses a real need (although not necessarily the generators), and the feedback from Ruben and Marcelo are strong testimony to the quality of the library.
But at this point, I am not comfortable with adding a library whose design for generators cannot be explained in the docs to the extent that I consider satisfactory.
Would this library lose in usability if generators were removed?
I know it is not a fair review. I only covered one subject, and my feeling is that it is not the most relevant one. So please consider it as "just feedback" rather than a review.
Again, thanks Klemens for writing and sharing this library. I hope that this message does not come across as negative. I want to think that I am contributing to the quality of Boost.Async.
Regards, &rzej;
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Just a question, did you also look at the ticker example? The generator is used there.
Thanks! I missed that one. Regards, &rzej;
Regards, Matthijs
participants (2)
-
Andrzej Krzemienski
-
Matthijs Möhlmann