|
Boost : |
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2023-04-14 06:39:51
niedz., 9 kwi 2023 o 03:11 Andrey Semashev via Boost <boost_at_[hidden]>
napisaÅ(a):
> On 4/9/23 03:20, Andrzej Krzemienski wrote:
> >
> > Well, in my experience, the scope fail/success is exclusively about
> > exceptions, so I will still focus on exceptions.
> > Here is a small benchmark comparing the deactivation-based mechanism
> > of a scope_guard with uncaught_exception-based mechanism of
> scope_fail.
> > The former performed like 36 times faster, as it doesn't have to
> > perform the calls to the runtime.
> >
> > Sorry. Forgot the link. Here it is:
> > https://quick-bench.com/q/0InBohGrnD5-soYT_GwvaCEaG74
> > <https://quick-bench.com/q/0InBohGrnD5-soYT_GwvaCEaG74>
>
> The thing with manually dismissing (or activating) the scope guard
> before leaving the scope diminishes the usefulness of the scope guard.
> The first and foremost reason to use a scope guard is to automate
> execution of the action upon exiting the scope. If you now have to
> manually ensure this at every point where you might leave the function,
> what's the point of using it in the first place?
>
To "automate" is just one goal. A more modest one is to "make it
manageable". Like in the case where you want to push_back into two vectors
in a transactional-like fashion:
vec1.push_back(Connection{params});
scope_guard pushGuard {[&]{ vec1.pop_back(); }}
vec2.push_back(Storage{params});
pushGuard.deactivate();
The problem is contained, so I do not mind the call to deactivate().
But without the scope_guard, I would have to define my own class that does
a pop-back in the destructor.
>
> Yes, you can manually (de)activate the guard in small and contained
> cases, but in general I would very much prefer it to work automatically.
> Otherwise, it quickly becomes a maintenance nightmare that it was
> supposed to fix.
>
True. Therefore in my code I would contain the code that requires a guard.
(In general, I prefer RAII.)
But even contained cases need a scope guard.
So, the trade-off is this:
scope_fail:
- requires no manual deactivate
scope_guard with deactivate():
- works uniformly and unsurprisingly in all contexts, including coroutines
- is fast.
I would recommend that this trade-off is documented.
Regards,
&rzej;
>
> > Regarding failure conditions other than exceptions, the problem with
> > coroutines may still appear if a thread-local storage is used, such
> > as errno.
>
> errno is volatile (not in core C++ terms but in terms of it changing its
> value in various non-obvious ways), so you would normally read its value
> into a local variable immediately after a syscall for testing before
> returning. It is that local variable that you check in the scope guard,
> not errno itself.
>
>
> _______________________________________________
> 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