Boost logo

Boost :

From: Matt Gruenke (mgruenke_at_[hidden])
Date: 2006-11-26 21:23:01


Perhaps I'm missing something (in which case it might help if you stated
your goals more clearly), but I'm not sure it needs to be quite so
complicated. Here's what I've done, in the past.

First, a usage example:

            glob_t result_glob;

            BOOST_FINALLY__BEGIN
            {
                globfree( &result_glob );
            }
            BOOST_FINALLY__END

            int err = glob( pattern.c_str(), flags_glob, NULL,
&result_glob );
            if (err == 0)
            {
                ...
                return result;
            }
            else throw CGlobError( "Glob error" );

            // Whether we exited via throw or return, globfree() was
            // called, avoiding a possible memory leak.

The implementation is simply:

#define BOOST_FINALLY__BEGIN BOOST_FINALLY__BEGIN__INTERNAL1( __LINE__ )
#define BOOST_FINALLY__BEGIN__INTERNAL1( uniq )
BOOST_FINALLY__BEGIN__INTERNAL2( uniq )
#define BOOST_FINALLY__BEGIN__INTERNAL2( uniq ) \
    struct boost_finally_##uniq \
    { \
        ~boost_finally_##uniq() \
        {

    //! Ends an BOOST_FINALLY block (see BOOST_FINALLY__BEGIN, for details).
#define BOOST_FINALLY__END BOOST_FINALLY__END__INTERNAL1( __LINE__ )
#define BOOST_FINALLY__END__INTERNAL1( uniq )
BOOST_FINALLY__END__INTERNAL2( uniq )
#define BOOST_FINALLY__END__INTERNAL2( uniq ) \
        } \
    } boost_finally_inst_##uniq UNUSED;

Where UNUSED is defined as (for gcc):
    #define UNUSED __attribute__ ((__unused__))

And the explanation:

The basic idea is to use the destructor of an instance of a local struct
as the mechanism through which the "at scope exit" code gets invoked.
In order to facilitate multiple such blocks in the same scope, type and
variable names are made unique by appending the source file line number
to both names.

To avoid compiler warnings that these variables are unused, GCC's
'unused' attribute is applied. For simplicity, I just used my own
definition, here.

I should note that this was designed for use in functions, only. Also,
there are some cases in which I've found this unsatisfactory, and have
defined my own scoped_ptr-inspired templates that, upon destruction,
call a user-specified function.

Matt

Alexander Nasonov wrote:

>I uploaded version 0.01 of scope_exit. It doesn't have tests and a
>documentation yet (only README.scope_exit) but I'm pretty sure I'll
>finish them before the review.
>
>The library can be downloaded from http://tinyurl.com/y58k33
>I attached README.scope_exit. Please review it. There are some problems
>that may be interested to other people. One related to boost.typeof and
>another to faster mt code (spin-locks, lock-free whatever).
>
>
>
>------------------------------------------------------------------------
>
>Boost Candiate library scope_exit, version 0.01
>
>Overview
>
>The library provides BOOST_SCOPE_EXIT macro similar to D's scope(exit)
>feature [D-ScopeBlock].
>
>Syntax
>
>{ BOOST_SCOPE_EXIT ( scope-exit-arg-pp-seq )
> scope-exit-body
>} direct-declarator;
>
>scope-exit-body:
> function-body
> function-try-block
>
>The scope-exit-arg-pp-seq is Boot.Preprocessor sequence of identifiers
>that can be used inside scope-exit-body. The direct-declarator is
>declarator-id followed by optional argument of type boost::scope_exit_group
>(inside brackets or after the equal sign).
>
>This construct executes scope-exit-body at the close of the current scope.
>
>For example, the following code prints classical "Hello, World":
>
> {
> std::string hello("Hello"), world("World");
>
> { BOOST_SCOPE_EXIT( (hello)(world) ) {
> std::cout << hello << ", " << world << "!\n";
> }} _;
>
> // other code ...
> }
>// ^ "Hello, World\n" is printed at this point
>
>Note that the _ is a direct-declarator. Similar to Prolog or Haskell,
>it means that we don't care about a name of this variable. Unlike
>those languages, if we had two scope(exit) blocks in one scope, we
>would have to use a different name for the second block.
>
>The code above relies on non-standard __thread or __declspec(thread)
>specifiers. To get rid of these, you can pass scope_exit_group to a
>block:
>
> boost::scope_exit_group se_group;
>
> { BOOST_SCOPE_EXIT( (se_group)(hello)(world) ) {
> std::cout << hello << ", " << world << "!\n";
> }} se_block(se_group);
>
>The se_group should be passed to scope-exit-arg-pp-seq AND as an
>initializer to se_block. Copy initialization is acceptable too (that
>is, se_block = se_group).
>More than one block can be associated with one scope_exit_group
>object. Execution of all associated blocks can be canceled with
>scope_exit_group::cancel() function. The scope_exit_group object
>can be declared const, in this case cancel can't be called.
>
>The D language has also scope(failure) and scope(success) but
>std::uncaught_exception cannot be used to detect a failure or a
>success.
>
>Testing
>
>It is recommended to use a compiler with native typeof. Emulation
>is tested successfully on VC 7.1, VC 8.0 and Intel for Linux 8.1.038.
>Gcc 3.4.6 doesn't compile ./libs/scope_exit/example/all.cpp in
>emulation mode unless all function templates are commented out.
>Intel for Linux 8.1.038 and gcc 3.4.6 compile all examples in native
>mode.
>
>References
>
>[D-ScopeBlock] http://www.digitalmars.com/d/statement.html#ScopeGuardStatement
>
>Problems
>
>1. gcc 3.4 doesn't compile this code
>
>template<class T> void foo(T const& t) {
> struct X {
> typedef __typeof__(t) type;
> };
> typedef X::type type;
>}
>int main() { foo(0); }
>
>This can be fixed by adding typename before X::type.
>Until it gets fixed, gcc 3.4 users should use BOOST_SCOPE_EXIT_TMPL
>in function templates.
>
>2. Emulation is dependent context is not supported. Probably it's
>not worth having BOOST_SCOPE_EXIT_TPL and wait for typeof acceptance
>by the standard.
>
>3. Use spin-locks instead of OS locking primitives when
>BOOST_SCOPE_EXIT_NO_THREAD_STATIC_KEYWORD is defined.
>
>4. Improve pthreads and Win32 code fragments.
>
>Files
>
>./README.scope_exit
>./boost/scope_exit.hpp
>./libs/scope_exit/example/all.cpp
>./libs/scope_exit/example/hello.cpp
>
>
>
>------------------------------------------------------------------------
>
>_______________________________________________
>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