Boost logo

Boost :

Subject: Re: [boost] D-style scope guards?
From: Yakov Galka (ybungalobill_at_[hidden])
Date: 2010-09-17 06:37:53


Why don't you use std::uncaught_exception() instead of exception_thrown?

Also in my opinion this is a cleaner solution:
void foo()
{
    BOOST_SCOPE_EXIT(empty capture list not supported yet)
        cout << "Returning from foo()" << endl;
        if(!std::uncaught_exception())
            cout << "foo(): No Errors occurred!" << endl;
        else
            cout << "foo(): Exception caught!" << endl;
    BOOST_SCOPE_EXIT_END
    // ...
}

Anyway in real code using a commit variable directly reflects the intent
better. Perhaps if I'm wrong, please give a real-world example when your
scope guards are more appropriate.

On Fri, Sep 17, 2010 at 09:06, Martin Christiansson <
martin.christiansson_at_[hidden]> wrote:

> Hi,
>
> I have used the good old scopeguard in the past and recently done some
> experiments with the Boost.ScopeExit library. Still I feel that the clean
> scope statements in D is missing.
>
> It will not be possible to do an equally clean solution without having the
> same features in the language itself, but I could reach as far as this
> example that reuses the ScopeExit library:
>
> void foo()
> { GUARDED_SCOPE_BEGIN
>
> GUARDED_SCOPE_EXIT() {
> cout << "Returning from foo()" << endl;
> } GUARDED_SCOPE_EXIT_END
>
> GUARDED_SCOPE_SUCCESS() {
> cout << "foo(): No Errors occurred!" << endl;
> } GUARDED_SCOPE_SUCCESS_END
>
> GUARDED_SCOPE_FAILURE() {
> cout << "foo(): Exception caught!" << endl;
> } GUARDED_SCOPE_FAILURE_END
>
> GUARDED_SCOPE_END
> }
>
>
> The GUARDED_SCOPE_BEGIN macro declares one boolean guard to handle return
> from several levels of nested scopes and one boolean to guard the current
> scope from exceptions (will be shadowed in nested scopes).
> GUARDED_SCOPE_END will set the exception_thrown guard to false before that
> variable is used by the GUARDED_SCOPE_*() destructors. The latter is
> actually reused ScopeExit code with an added wrapper with a single
> if-statement.
> GUARDED_SCOPE_EXIT() will allways run on scope exit.
> GUARDED_SCOPE_SUCCESS() will only run if the function is exited with wrapper
> for return keyword (GUARDED_SCOPE_RETURN). The wrapper must be used since it
> updates the hidden guard variables. Using plain "return" will behave as if
> exception was thrown.
> GUARDED_SCOPE_FAILURE() will run when exception is thrown.
>
> There is also a separate GUARDED_SCOPE_NESTED_BEGIN that is supposed to be
> used for all nested scopes. A reference is kept to the return_called
> variable in the top-level-scope (variable declared by GUARDED_SCOPE_BEGIN).
>
> The biggest issue here is that any extra closing curly bracket inserted
> between GUARDED_SCOPE_*-definitions and GUARDED_SCOPE_END will cause
> destructors to run before update of guard variable. Could happen if someone
> thinks it "looks better" without understanding how stuff works. That kind of
> error will behave as if exception was thrown.
>
> Is this something to investigate further? Messy or potentially useful?
> Suggestions for improvements?
> I've appended the contents of my small test program at the end of this
> email.
> Can be tested by inserting GUARDED_SCOPE_RETURN() and "throw exception();".
>
> Regards,
> /Martin
>
> -----------
>
> #include <iostream>
> #include <exception>
>
> #include <boost/scope_exit.hpp>
>
> using namespace std;
>
> #define GUARDED_SCOPE_BEGIN bool return_called = false; { bool&
> return_called_ref = return_called; bool exception_thrown = true;
> #define GUARDED_SCOPE_NESTED_BEGIN { bool& return_called_ref =
> return_called; bool exception_thrown = true;
> #define GUARDED_SCOPE_END exception_thrown = false; (void)
> return_called_ref; }
>
> #define GUARDED_SCOPE_RETURN(rc) { return_called_ref = true; return rc;
> }
>
> #define GUARDED_SCOPE_EXIT(Seq) BOOST_SCOPE_EXIT(Seq)
> #define GUARDED_SCOPE_EXIT_END BOOST_SCOPE_EXIT_END
>
> #define GUARDED_SCOPE_SUCCESS(Seq) BOOST_SCOPE_EXIT( (&return_called_ref)
> (&exception_thrown) Seq) { if(return_called_ref || !exception_thrown)
> #define GUARDED_SCOPE_SUCCESS_END } BOOST_SCOPE_EXIT_END
>
> #define GUARDED_SCOPE_FAILURE(Seq) BOOST_SCOPE_EXIT( (&return_called_ref)
> (&exception_thrown) Seq) { if(!return_called_ref && exception_thrown)
> #define GUARDED_SCOPE_FAILURE_END } BOOST_SCOPE_EXIT_END
>
> void foo()
> { GUARDED_SCOPE_BEGIN
>
> GUARDED_SCOPE_EXIT() {
> cout << "Returning from foo()" << endl;
> } GUARDED_SCOPE_EXIT_END
>
> GUARDED_SCOPE_SUCCESS() {
> cout << "foo(): No Errors occurred!" << endl;
> } GUARDED_SCOPE_SUCCESS_END
>
> GUARDED_SCOPE_FAILURE() {
> cout << "foo(): Exception caught!" << endl;
> } GUARDED_SCOPE_FAILURE_END
>
> do { GUARDED_SCOPE_NESTED_BEGIN
>
> GUARDED_SCOPE_FAILURE() {
> cout << "Inner scope: Exception caught!" << endl;
> } GUARDED_SCOPE_FAILURE_END
>
> GUARDED_SCOPE_SUCCESS() {
> cout << "Inner scope: No Errors occurred!" << endl;
> } GUARDED_SCOPE_SUCCESS_END
>
> GUARDED_SCOPE_END
> } while(0);
>
> GUARDED_SCOPE_END
> }
>
> int main() {
>
> try {
> foo();
> } catch(exception& e) {
> cout << "main(): Caught exception: " << e.what() << endl;
> return -1;
> }
>
> cout << "main(): No Errors occurred!" << endl;
> return 0;
> }
>
>
> _______________________________________________
> 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