Boost logo

Boost :

Subject: [boost] [scope_exit] D-style scope(failure) and scope(success) in C++
From: Evgeny Panasyuk (evgeny.panasyuk_at_[hidden])
Date: 2012-10-02 08:53:45


Hello all,

D language has scope(exit), scope(success) and scope(failure) features -
http://dlang.org/statement.html#ScopeGuardStatement :
"...
scope(exit) executes NonEmptyOrScopeBlockStatement when the scope exits
normally or when it exits due to exception unwinding. scope(failure)
executes NonEmptyOrScopeBlockStatement when the scope exits due to
exception unwinding. scope(success) executes
NonEmptyOrScopeBlockStatement when the scope exits normally.
..."
Andrei Alexandrescu describes some of uses cases for scope(exit),
scope(success), scope(failure) at his recent talk :
http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Three-Unlikely-Successful-Features-of-D

There is Boost.ScopeExit library which emulates D's scope(exit) via
BOOST_SCOPE_EXIT macro, but there are no analogues for D's
scope(failure) and scope(success).
Current alternative for these features is ScopeGuard idiom (
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Scope_Guard ,
http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758
).

Boost.ScopeExit library itself suggests to use ScopeGuard -
http://www.boost.org/doc/libs/1_51_0/libs/scope_exit/doc/html/scope_exit/alternatives.html#scope_exit.alternatives.the_d_programming_language
:
"
Boost.ScopeExit is similar to scope(exit) feature built into the D
programming language.
A curious reader may notice that the library does not implement
scope(success) and scope(failure) of the D language. Unfortunately,
these are not possible in C++ because failure or success conditions
cannot be determined by calling std::uncaught_exception (see Guru of the
Week #47 for details about std::uncaught_exception and if it has any
good use at all). However, this is not a big problem because these two
D's constructs can be expressed in terms of scope(exit) and a bool
commit variable (similarly to some examples presented in the Tutorial
section).
"

I have made small library (
https://github.com/panaseleus/stack_unwinding#d-style-scope-guardsactions )
which supplies primitives (class unwinding_indicator,
UNWINDING_AWARE_DESTRUCTOR macro) to determining when object destructor
is called due to stack-unwinding or due to normal scope leaving.
Currently it is implemented on top of platform-specific implementation
of uncaught_exception_count function and tested on:
{MSVC2005, MSVC2008, MSVC2010, MSVC2012, GCC4.1.2, GCC4.4.6,
Clang3.2}x{x32, x64}x{default settings}.
uncaught_exception_count is a function similar to
std::uncaught_exception from standard library, but instead of boolean
result it returns unsigned int showing current count of uncaught exceptions.

Such primitives allow us to implement scope(success) and scope(failure)
features in C++. I have made several proof-of-concepts:
*
https://github.com/panaseleus/stack_unwinding/blob/master/examples/scope_actions.cpp
*
https://github.com/panaseleus/stack_unwinding/blob/master/examples/example_from_dlang_dot_org.cpp
*
https://github.com/panaseleus/stack_unwinding/blob/master/examples/scope_guard.cpp
*
https://github.com/panaseleus/stack_unwinding/blob/master/examples/boost_scopes.cpp

boost_scopes.cpp example shows usage of BOOST_SCOPE_FAILURE and
BOOST_SCOPE_SUCCESS:
try
{
     cout << "Case #1: stack unwinding" << endl;
     BOOST_SCOPE_EXIT(void) { cout << "exit" << endl; } BOOST_SCOPE_EXIT_END
     BOOST_SCOPE_FAILURE(void) { cout << "failure" << endl; }
BOOST_SCOPE_FAILURE_END
     BOOST_SCOPE_SUCCESS(void) { cout << "success" << endl; }
BOOST_SCOPE_SUCCESS_END
     throw 1;
} catch(int){}
{
     cout << "Case #2: normal exit" << endl;
     BOOST_SCOPE_EXIT(void) { cout << "exit" << endl; } BOOST_SCOPE_EXIT_END
     BOOST_SCOPE_FAILURE(void) { cout << "failure" << endl; }
BOOST_SCOPE_FAILURE_END
     BOOST_SCOPE_SUCCESS(void) { cout << "success" << endl; }
BOOST_SCOPE_SUCCESS_END
}
Output is:
"
Case #1: stack unwinding
failure
exit
Case #2: normal exit
success
exit
"

Currently BOOST_SCOPE_FAILURE and BOOST_SCOPE_SUCCESS are implemented
based on boost_1_51_0/boost/scope_exit.hpp by copy-paste and replace
(just for proof-or-concept, of course it is possible solution with much
less duplication).
Semantically meaningful changes can be viewed as diff at
https://github.com/panaseleus/stack_unwinding/commit/d5513404323490ea99d9b6b77ff1b88f454a4a42

Before posting here, I made posts on several C++ forums, but
unfortunately get only a few feedbacks regarding ScopeFailure and
ScopeSuccess.
What do you think?

Thank you.

P.S. Related discussion:
http://lists.boost.org/Archives/boost/2010/09/171051.php

Best Regards,
Evgeny Panasyuk


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