Boost logo

Boost :

From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2023-04-07 16:04:29


pt., 7 kwi 2023 o 17:43 Andrey Semashev via Boost <boost_at_[hidden]>
napisał(a):

> On 4/7/23 15:55, Andrzej Krzemienski wrote:
> >
> >
> > czw., 6 kwi 2023 o 23:51 Andrey Semashev via Boost
> > <boost_at_[hidden] <mailto:boost_at_[hidden]>> napisał(a):
> >
> > On 4/6/23 21:26, Andrzej Krzemienski via Boost wrote:
> > > Hi Everyone,
> > > It is my understanding that the reason scope_fail was left to die
> > in the
> > > C++ Extensions for Library Fundamentals v3 was that it is not
> > > implementable.
> >
> > I'm not sure what you mean in the "left to die" part. Do you mean
> that
> > these facilities are being deprecated?
> >
> > There are two motivations for putting something into a TS. One is to
> > encourage vendors to implement the feature and gather usage and
> > deployment experience. The other is to postpone the addition of the
> > feature or to politely say that it is not wanted in the Standard. I
> > *believe* this is the case with the subset of scope guards. I have seen
> > no movement towards moving scope_fail into the Standard. and not moving
> > them into the standard in reality means abandoning them.
>
> My understanding is that the TS exist to gather practical usage
> experience in real world with the components before including (or not
> including) them into the main standard. In fact, this very thread is a
> piece of this real world feedback. I see no point in including something
> into a TS only to abandon it afterwards. That said, I have no close
> knowledge of the standard committee processes and may be wrong.
>
> In any case, the problem you highlighted may well be a reason for
> reluctance to include scope_success/scope_fail into the standard, at
> least not with the current wording that is given in the TS. But I think
> the components can be defined differently, with coroutines in mind. That
> new definition would not use uncaught_exceptions() as a criteria for
> detecting failure but some other, possibly "implementation-defined" or
> otherwise undisclosed mechanism that allows to implement the correct
> semantics wrt. coroutines.
>

That would be nice.

>
> > I must say I have no experience with coroutines, but my
> understanding is
> > that they are basically incompatible with any mechanism that relies
> on
> > thread-specific state, including the uncaught exceptions counter.
> >
> > Indeed. Note that the example I provided uses just one thread. The
> > problem is the suspension itself.
>
> The problem is that the uncaught exceptions counter does not correspond
> to the current coroutine, but to the current thread.
>
> > Thus I
> > wouldn't say scope_success/scope_fail are unimplementable - they
> clearly
> > are - but that they are incompatible with coroutines. That is, these
> > scope guards will work as expected as long as you don't switch
> > coroutines within the guarded scope.
> >
> > Maybe this is just a question of the choice of words.
> > But the docs do not present the situation in this way.
> >
> > "Although it is possible to specify arbitrary condition function
> > objects, typically |scope_success
> > <
> https://lastique.github.io/scope/libs/scope/doc/html/boost/scope/scope_success.html>|
> invokes its action when the scope is left normally (i.e. not via an
> exception) and |scope_fail <
> https://lastique.github.io/scope/libs/scope/doc/html/boost/scope/scope_fail.html>|
> should typically be used to handle errors, including exceptions."
> >
> > This guarantee (when scope is exited not normally) cannot be satisfied
> > in general. One cannot use it in a coroutine: directly or indirectly.
> > One might not even know the context.
> >
> > "By default, |scope_success
> > <
> https://lastique.github.io/scope/libs/scope/doc/html/boost/scope/scope_success.html>|
> will invoke its action if it is destroyed normally, |scope_fail <
> https://lastique.github.io/scope/libs/scope/doc/html/boost/scope/scope_fail.html>|
> - if it is destroyed due to an exception being thrown."
>
> Note the "typically". :) In this documentation I tried to describe these
> facilities in more or less simple language, describing the most typical
> use cases. For this simplicity, I had to omit some formalities and
> corner cases that would detract the reader from the main purpose and
> intended use case of the components. Perhaps, I should improve the
> wording, but I would still like the docs to be easily readable.
>
> And, as I admitted earlier, I completely forgot about coroutines. I will
> add a note about coroutenes in relation to the default failure condition
> used by scope_success/scope_fail.
>
> > (BTW, The synopsis in
> >
> https://lastique.github.io/scope/libs/scope/doc/html/boost/scope/scope_fail.html
> <
> https://lastique.github.io/scope/libs/scope/doc/html/boost/scope/scope_fail.html
> >
> > does not indicate that there is any default Cond.)
>
> Hmm, for some reason Doxygen removed the default template arguments for
> scope_success/scope_fail. I'll see if I can fix this. Thanks for noticing.
>
> > This is not true when a scope guard is used across coroutine
> > suspensions: by default [...] scope_fail is not destroyed due to
> > exception being thrown. The reality is, it is destroyed based on the
> > comparison of two measurements of the number of uncaught exceptions,
> > potentially measured in different threads.
> >
> > I admit this is a notable limitation, and I will document it. But I
> do
> > not consider this limitation fatal, as there is plenty code out there
> > that doesn't use coroutines - I'd even say, much more code than that
> > does.
> >
> > This is one way of looking at it: that the problem is rare. A different
> > way is to say that if something works in 99% of the cases and fails only
> > in 1%, we have a dangerous situation, as we are unprepared when the 1%
> > case happens.
>
> Well, every technology has its limits. And if a utility is not usable in
> 1% of use cases, I don't see why it shouldn't exist to benefit the rest
> 99%.
>

Let me clarify my point here a bit. We can distinguish two situations here.
The first is this. A tool compiles and works fine in 99% of the cases, and
in the remaining 1% it fails to compile, or signals an error.
The second is this. A tool compiles and works fine in 99% of the cases, and
in the remaining 1%it compiles fine, reports no error, and works against
the user's expectations or the declared intent.

In the first case, this is an acceptable trade-off. In the second case, it
may be debatable, but I personally would find it a bad trade-off. My claim
is that the situation with scope_fail is closer to the second one.
Especially, given that a 100% alternative exists: just explicitly
deactivate an active guard.

Regards,
&rzej;

> > Also, I forgot to mention that Boost.Scope's scope_success/scope_fail
> > support custom failure predicates which may not rely on the exception
> > state at all.
> >
> > Can it be used to fix the coroutine case? (That is to detect that the
> > scope is left due to an exception being thrown?)
>
> To my knowledge, not in pure C++. With current real coroutine
> implementations? I don't know, probably not either. You could use this
> feature with your own error reporting mechanism, like checking an error
> code.
>
> I could imagine a mechanism that would capture the unhandled exceptions
> count upon entering a coroutine. Throwing and catching exceptions from
> the coroutine would then update this cached counter the same way as it
> does for the thread-specific counter. Resuming the coroutine would
> maintain its own counter regardless of the caller's state. Then
> scope_success/scope_fail could use some internal API to use this counter
> (say, co_unhandled_exceptions()) instead of unhandled_exceptions() to
> detect a thrown exception.
>
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk