From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2020-05-03 23:15:15
I have a remark regarding the LEAF library. But first, I would like to
thank Emil for writing and sharing this library. Handling failures is an
important aspect of writing programs that does not have an ultimate answer
in C++, and is still a subject of exploration. LEAF seems to confirm this.
I would also like to thank Michael for managing this upcoming review and
for making the announcement ahead of time. A ten-day review period is
usually too short (even if later extended), and the early announcement
gives the opportunity to devote more time into reviewing a library and
interact with the author.
The following is not a review, but I wanted to highlight only one aspect of
the library. Namely, the usage of thread-local storage.
There is a number of reasons people do not want to or cannot use the C++
exception handling mechanism. One of them is that the implementation of
exception handling requires the usage of TLS, and TLS is not implementable
on some platforms, like GPUs. If Nvidia's compiler does not implement C++
exception handling mechanism, it is not because it would be slow, but
because it would require TLS support. From this perspective, if I cannot
use C++ exceptions because of TLS and I have to use something else, then
another TLS-based library is not really an alternative. In this case it
does not matter that it is only IDs that are stored in TLS. The sole fact
of even employing TLS is a deal breaker.
Of course, LEAF does not have to satisfy all the people that cannot use C++
exceptions. It can service the environments where TLS is affordable. But
the usage or non-usage of TLS is an important factor in making a decision
what tool/framework/library to use for handling failures, and because of
this it deserves to be mentioned in the beginning of the documentation, so
that potential clients can quickly make a decision if this library is for
them. If your concern is that people would be incorrectly led to think that
the entire error objects are stored in TLS, you can also say explicitly up
front that it is only about int-size IDs. Otherwise, people will be mislead
anyway. A person will ask, "how is it possible that this library does not
return the entire error object in leaf::result<> and it does not take the
pointer to the allocated object as function argument? Is it using TLS?
Let's grep for `thread_local`. Positive: it must be using TLS for storing
For a similar reason, I find the comparison with Boost.Outcome, at the end
of documentation, unfair. If the goal of this comparison is to help people
decide which library is best suited for them, LEAF or Outcome, the usage or
non-usage of TLS is an important factor.
Another thing is that I cannot see how a TLS-based implementation can work
with C++20 coroutines. In C++ 20 the following piece of code
means that when the call to B() will be potentially "packaged" as a task
and scheduled to be executed possibly on a different thread. It means that
B() will be executed on a different thread than A(), which means that any
attempt to communicate between A() and B() using TLS will not be reliable
(e.g. if A() is in fact a call to leaf::preload()). This is the reason why
we still cannot implement the feature known as "on scope failure" (like
destructor call, but only when we are leaving the scope due to exception)
in C++ even though we have `std::uncaught_exceptions()` (which uses TLS
under the hood). This is why a proposal like P0052 (
didn't make it to C++20.
Now, LEAF may have a solution to this problem, but I cannot figure it out
from the documentation. So, I do not know if it is safe to use LEAF with
coroutines in multi-threaded environment.
I would really want this to be clarified in the docs before the library
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk