Recent submissions

Comment · 2 years ago
Thank you for clearing that up.

Regarding modern features, for example, the return value from the executor in TaskFlow is a custom tf::Future derived from std::future. This means if you want to check for the result, you need to use a try-catch block with the get() method on the future.

Personally, I prefer using std::expected for value/exception handling. It allows checking for errors with a simple if statement, and if you don't want to handle the exception, you can just return an error value from the coroutine.

As for "monadic-chaining," TaskFlow can achieve the same thing with its easy graph construction, you can set up a graph and execute it, which is comparable to and_then chaining in my library.

Another point is related to performance and ease of use. In a simple example like Fibonacci, TaskFlow requires using subflows, which I feel is less "ergonomic".

Overall, for simple task parallelism, if you don't need the graph expressiveness of TaskFlow, I believe my library is a more "ergonomic" choice (though I may be biased here). I also find value handling simpler in my library with std::expected. That said, TaskFlow is a much larger library with more features like GPU integration.

I hope this better addresses your point!

Comment · 2 years ago
Thank you for your feedback and appreciation.

During development, I initially tried implementing coroutines in a way that executing them without spawning a new thread would be possible. However, it introduced complications, so I eventually scrapped that approach.

Now, with eye on potential improvements, I can revisit this idea from the perspective of I/O operations.

Comment · 2 years ago
Thank you for bringing this up.

I hadn’t come across folly::Coro until now. It does seem quite similar at first glance, and some of the utility functions they have are ones I’m also planning to implement, as others have also pointed out are currently missing.

One difference is that they use a custom Try<T> type for handling exceptions and values, I’ve opted for std::expected introduced in C++23. I’ve also added "monadic-like" chaining of tasks.

Overall, it’s a very similar library, and I’ll definitely look into it for inspiration and potential improvements.

Comment · 2 years ago
Thanks for spotting that! I appreciate the feedback and will update the README.
Comment · 2 years ago
Thank you for asking!

I've skimmed through Taskflow, and from what I understand, its main focus is on graph parallelism, allowing users to express computations as a graph.

I haven't done extensive benchmarking against 3rd-party libraries yet, which others have also mentioned. I'll definitely do more performance testing in the future to better assess and optimize performance.

Comment · 2 years ago
Comment · 2 years ago
Yes, exactly. Coroutines are one possible implementation of green threads. Once they are scheduled/loaded on an OS thread, they behave just like regular functions with their own call stack. This means they can indeed call blocking operations at the OS level. A possible approach to handle such operations would be to wrap the blocking call, suspend the coroutine, and then resume it once the operation is complete, perhaps by polling(checking for completion).
Comment · 2 years ago
Thank you for your response!

I don't have experience with WinRT, but it does seem quite similar at first glance. One of the key reasons I focused on modern C++ was to ensure cross-platform compatibility. However, I completely understand that if you're working on Windows and are already familiar with WinRT, sticking with it makes perfect sense. I'll take a closer look at WinRT to see if there are any significant differences.

Comment · 2 years ago
Thank you for your feedback.

I understand that working with tasks and retrieving values can feel a bit clunky. The main reason I've structured it this way is that individual tasks are RAII objects, and their coroutine state is destroyed once they go out of scope. However, I could modify the awaitable returned from wait_tasks to store tasks, and then return values directly to the user. This could definitely be a more ergonomic overload for the function. I'll look into it!

Comment · 2 years ago
Hopefully, you find it useful! If you have any ideas or suggestions for improvement, feel free to open an issue or let me know. Thanks for considering it!
Comment · 2 years ago
Thank you for your question.

I've included a link to Lewis Baker's blog (the author of CppCoro) in my repository as an excellent explanation of coroutines. From my understanding, after reviewing his library, it is no longer in active development and hasn’t been updated for a couple of years. CppCoro was an experimental library intended to explore coroutines while they were still an experimental feature. For example, CppCoro uses a custom type for storing values, similar to std::optional from the standard library (if I'm not mistaken).

For my implementation, I've opted to leverage std::expected from C++23 for storing values. I've also implemented monadic-like chaining. CppCoro, however, seems to focus more on asynchronous operations, whereas my library focuses more on task-based parallelism.

I don't have experience with Boost.Cobalt, so I can't provide insights there, but I will definitely look into it now that you've mentioned it.

Hope this helps.

Comment · 2 years ago
Comment · 2 years ago
Comment · 2 years ago
Thank you for your thoughtful feedback.

I've just skimmed through the paper, and it raises interesting and valid point about scalability in parallel computing. I'll definitely look into it more thoroughly, as well as the talk you mentioned.

I'm glad you find the usage examples well-designed and appreciate your positive remarks about the library's architecture. Thank you again for your insights.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton