[review] [LEAF] LEAF Review Starts May 22
The Boost formal review for LEAF (Lightweight Error Augmentation Framework) will take place May 22, 2020 through May 31st. LEAF is brought to us by Emil Dotchevski, the author of Boost.Exception. Similar to Boost.Exception, this library allows arbitrary error objects to be returned; however, unlike Boost.Exception it does not require dynamic memory. The library can be used with or without exception handling. Error handling is such an import part of every software system. LEAF provides a unique solution to the problem. The excellent documentation can be found here: https://zajo.github.io/leaf/ and includes a tutorial, examples, reference, design rationale, and comparisons to other error handling approaches/libraries. The source is available at github. The review branch will be used during the review period. https://github.com/zajo/leaf/tree/review The purpose of this announcement is to give people some time to start looking at the documentation and source code for the library. Feel free to begin asking questions. Most of all, get involved! Everybody has some experience with handling errors. Tell the Boost community what you think of LEAF. Thank you for your participation! michael -- Michael Caisse Ciere Consulting ciere.com
On 01/05/2020 06:57, Michael Caisse via Boost wrote:
LEAF is brought to us by Emil Dotchevski, the author of Boost.Exception. Similar to Boost.Exception, this library allows arbitrary error objects to be returned; however, unlike Boost.Exception it does not require dynamic memory. The library can be used with or without exception handling.
Before someone inevitably asks what the differences are between LEAF and Outcome: - Emil gives his list at https://zajo.github.io/leaf/#boost_outcome - Note that his benchmarks are for Outcome v2.1, and Outcome v2.2 (on the "better_optimisation" branch) significantly improves its comparative benchmarking. It doesn't eliminate the gap, but there are orders of magnitude improvement. I would like to thank Emil for openly sharing those benchmarks, and motivating me to invest effort into Outcome to close the gap. I do want to stress that I have found zero observable difference between v2.1 and v2.2 Outcome in real world code on out of order CPUs at least as new as the decade old ARM Cortex A15. - I don't otherwise disagree with Emil's summary, though he has a different starting point and view point of the differences than I would have. - For me with Outcome, use of thread local storage and assumption of reasonable RAM availability was a non-starter. It prevents use of Outcome in constexpr, Freestanding, GPUs, embedded systems. LEAF can be configured with some effort to avoid use of TLS, but ultimately it is cleanest to use with TLS, and almost everybody who wants deterministic failure and doesn't mind TLS (gaming folk mainly) will find LEAF with TLS natural. I don't think LEAF would work well on systems with 2Kb of RAM, whereas there are people using Outcome on such systems (judging from bug reports filed). - For me with Outcome, I wanted every potential control flow inversion point to appear explicitly in the source code. Then code could be audited much more easily for correctness in both the failure and success code paths. LEAF is success-orientated, like C++ exceptions it aims to "disappear" for the sucess control flow. Outcome is success-failure-balanced, it treats success and failure with equal priority (though default internally hints to the compiler to expect success). - A good chunk of LEAF is the matcher interface, which I personally think is both cool and much more universal potentially than just for LEAF. Outcome awaits WG21 to implement language support for matchers. - Finally, I have actually wrapped Outcome into a LEAF-like implementation in production code I have shipped. I intentionally and deliberately left open customisation points in Outcome to make that kind of extension possible, so if you are on a platform with TLS and plenty of RAM, you can achieve all the non-matcher parts of LEAF with very little extra work in Outcome. I don't mean this to say "Outcome already does LEAF". Rather, I'd like this to be interpreted as "I endorse the fundamental design proposal which LEAF makes as I do the same thing in my own code". Should Outcome offer LEAF-like extensions? Should Outcome and LEAF be merged? In my personal opinion no. LEAF can already wrap Outcome and transport it around. Any LEAF-like extension (apart from the matchers) Outcome could offer is so trivial that I don't think it worth shipping, users can implement such extensions locally with such little effort there is no point on insisting on a common implementation, in my opinion. Finally, my thanks to Emil for bringing yet another high quality library to use for review, and to Michael for review managing this. Niall
On Fri, May 1, 2020 at 3:45 AM Niall Douglas via Boost < boost@lists.boost.org> wrote:
cleanest to use with TLS, and almost everybody who wants deterministic failure and doesn't mind TLS (gaming folk mainly) will find LEAF with TLS natural. I don't think LEAF would work well on systems with 2Kb of RAM, whereas there are people using Outcome on such systems (judging from bug reports filed).
Re:TLS, someone may think that LEAF stores error objects in TLS. It does not, the error objects being communicated are stored on the stack. There are no dynamic allocations. In terms of portability, LEAF is a C++11 library. It requires TLS or, alternatively, BOOST_NO_THREADS. On systems with extreme RAM limitations it could be more efficient than Outcome or less efficient, depending on the use case.
- For me with Outcome, I wanted every potential control flow inversion point to appear explicitly in the source code. Then code could be audited much more easily for correctness in both the failure and success code paths. LEAF is success-orientated.
This is not true, the design of LEAF has no happy path bias, but it does have a bias towards the common case where lower level failures are forwarded up rather than handled. This makes sense, since there are many more scopes that only check for errors, than scopes that handle errors. When a failure is detected, error objects are moved directly to the correct error-handling scope, while the intermediate scopes are limited to inspecting the discriminant and communicating it up. It can be said that LEAF doesn't bother to deliver error objects to scopes that have no use for them.
Should Outcome offer LEAF-like extensions? Should Outcome and LEAF be merged? In my personal opinion no.
I think these are the wrong questions to ask, as they're based on the presumption that C++ programmers can agree on using a single all-powerful error-handling interface that devours everything else. The design of LEAF is based on the understanding that in any non-trivial program there will be many different error-handling interfaces, so the focus is on helping the user communicate arbitrary error objects efficiently and as safely as possible, using any available mechanism. For example this program uses LEAF to handle errors, even though functions which may fail return outcome::result<T> rather than leaf::result<T>: https://github.com/zajo/leaf/blob/master/examples/print_file_outcome_result.... .
participants (3)
-
Emil Dotchevski
-
Michael Caisse
-
Niall Douglas