Boost logo

Boost :

From: Alexander Nasonov (alnsn_at_[hidden])
Date: 2007-04-03 16:16:34


Hans Larsen wrote:
> Better than finally, yes. I thought you were saying better than my
> solution ;-)

No, I said:
> It's much better than the finally keyword ;-)
because I was replying to the subject rather than to the message.

> >> Why do you need that library and is it absolutely necessary?
> > Because I saw so much exception unaware code.
>
> I don't see any case of valid exceptions in the use of this library.
Sorry, I don't understand this statement.

> With my code?
> finally f;
> f( if_then( ref(f), bind(std::fclose, ref(f)) ) );
>
> I admit this solution is less readable than yours, but it's still
> possible using bind.

Well, my example is extremely simple. How would you bindify (or
lambda-ify) ten lines of ordinary code?

> Why not put the code inside the macro?
>
> Example (same as your hello world):
> #define MY_BOOST_EXIT( w, x, y ) BOOST_SCOPE_EXIT(w, x) \
> y \
> BOOST_SCOPE_EXIT_END(w)
>
> int main()
> {
> try
> {
> std::string hello("Hello"), world("World");
>
> MY_BOOST_EXIT( _id, (hello)(world),
> {
> std::clog << world << ", " << hello << "!\n";
> } )
>
> // other code
> } catch(...) {} /*
> ^ "World, Hello\n" is printed at this point */
> }

There is a way to avoid _id, see below.

> This way the id is used once. I'm trying to figure out a way to not
> use the id at all (when constructing local structs). If I find
> something I'll let you know :)

A global or thread-scope variable can be used to save a pointer to an
object holding all references (hello and world in the example).
Actually, the first version was based on that technique.

This code demonstrates how it works under the hood:

// Somewhere in the library
__thread void* g_args;

    // User code
    BOOST_SCOPE_EXIT( (hello)(world) ) // line 1
    /* Expands to:
       struct args_line1 { std::string &hello, &world; } args_line1 = { hello, world };
       g_args = &args_line1;
       struct scope_exit_line1 {
           void* m_args;
           ~scope_exit() {
               struct args_line1* p = (struct args_line1*)m_args;
               doit(p->hello, p->world);
            }
            static void doit(std::string& hello, std::string& world)
    */
    {
        // scope(exit) code
    }
    BOOST_SCOPE_EXIT_END // line 5
    /*
       } scope_exit_line5 = { g_args };
    */

Without g_args, it's not easy to know a name of args_line1 at line 5.

Although a next instruction after writing to g_args is reading it,
thread-safety is a problem and that's why I abandoned this approach.

> > You can rewrite it like this:
> > std::auto_ptr< helper_t<T> > p(new helper_t<T>(t) );
> > vec.push_back( p.get() );
> > p.release();
>
> mmmh... I fail to see the difference. There is really two cases
> where exceptions may occur:
> - operator new( size_t ) throws an exception (Out-Of-Memory). No
> memory is allocated.
> - push_back reallocs the vector and operator new( size_t ) throws an
> exception (Out-Of-Memory). Strong guarantee occurs... (?)

- push_back throws, vector doesn't leak but new helper_t<T>(t) is lost.

> > --
> > Alexander Nasonov
> > http://nasonov.blogspot.com
> >
> > To be pleased with one`s limits is a wretched state. -- Johann
> > Wolfgang von Goethe --
> >
> > This quote is generated by:
> > /usr/pkg/bin/curl -L http://tinyurl.com/veusy \
> > | sed -e 's/^document\.write(.//' -e 's/.);$/ --/' \
> > -e 's/<[^>]*>//g' -e 's/^More quotes from //' \
> > | fmt | tee ~/.signature-quote
> > _______________________________________________
> > Unsubscribe & other changes: http://lists.boost.org/mailman/
> > listinfo.cgi/boost
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

-- 
Alexander Nasonov
http://nasonov.blogspot.com
An inconvenience is only an adventure wrongly considered; an adventure
is an inconvenience rightly considered. -- GK Chesterton --
This quote is generated by: 
	/usr/pkg/bin/curl -L http://tinyurl.com/veusy         \
	  | sed -e 's/^document\.write(.//' -e 's/.);$/ --/'  \
	        -e 's/<[^>]*>//g' -e 's/^More quotes from //' \
	  | fmt | tee ~/.signature-quote

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