Boost logo

Boost :

From: Marc-Antoine Ruel (maruel_at_[hidden])
Date: 2003-12-19 13:30:05


The code isn't following the boost conventions. That could be changed.
There are threads that talked about adding this functionality one year
ago and it seemed that people were against it. I still post my code here
since it is the fastest code I could find. I think that using
boost::lambda::bind is faster than using boost::bind but I haven't
verified. Anyway my "library" isn't "binded" to any of them. :) It
hasn't been tested that much (only for 1/2 days :) but it seems to work
well. IT MAY STILL CONTAINS BUGS.

I have 2 uses. The first one (a define MAKE_SCOPE_GUARD) create a
anonymous ScopeGuard and the second makes a named ScopeGuard. The
anonymous have the dismissed code removed as an optimization which
results in a small bit faster code. It is simple enough that you can
make your own code.
By the way, the reason I still use fopen and not fstream is because of
UTF-16 support on Windows. fstream's are not well adapted for that.
Here's an untested and useless example:

  FILE * hFile = fopen("Bar", "r");
  if ( !hFile ) return false;

* then add *

  MAKE_SCOPE_GUARD( bind(fclose, var(hFile) ) );
  fclose(hFile)
  hFile = fopen("Foo", "w");
  // Auto-use new hFile. If fopen fails, hFile == NULL and fclose
  // will fail.

* or *

  ScopeGuard A = bind(fclose, hFile);
  fclose(hFile)
  A.Dismiss();
  hFile = fopen("Foo", "w"); // hFile changes of value
  ScopeGuard B = bind(fclose, hFile); // Code bloat :)

In this case I used var() to be able to open the file in case of
problems and don't have to create a second ScopeGuard object and dismis
the first one.

Here's my code. Sorry the copy-pasting didn't work well. I really need
to use another news reader...
------------ cut here -------------

template <class T> inline void no_unused_variable_warning(const T&) {}

// Only usable with boost and C++.
// Assumes :
// #include <boost/lambda/lambda.hpp>
// #include <boost/lambda/bind.hpp>
// using namespace boost::lambda; TBR
// Credits to Daniel Wallin, Andrei Alexandrescu and Petru Marginean.
// But I had the basic idea by myself! ;-P
// Thanks to Paul A. Bristow for warning removal. I had another solution
// but your's better.
// So some copyrights are still left of Marc-Antoine Ruel
namespace DetailsScopeGuard
{
    struct ScopeGuardBase
    {
      ScopeGuardBase() : m_dismissed(false) {}
      void Dismiss() const throw() { m_dismissed = true; }
    protected:
      mutable bool m_dismissed;
    };
    template<class T>
    struct ScopeGuardImpl : public ScopeGuardBase
    {
      explicit ScopeGuardImpl(const T& x) : m_action(x) {}
      ~ScopeGuardImpl() { if (!m_dismissed) m_action(); }
    private:
      T m_action;
    };
    struct ScopeGuardAnonBase
    {
    };
    template<class T>
    struct ScopeGuardAnonImpl : public ScopeGuardAnonBase
    {
      explicit ScopeGuardAnonImpl(const T& x) : m_action(x) {}
      ~ScopeGuardAnonImpl() { m_action(); }
    private:
      T m_action;
    };
}

template<class T>
DetailsScopeGuard::ScopeGuardAnonImpl<T> MakeScopeGuardAnon(T x)
{
    return DetailsScopeGuard::ScopeGuardAnonImpl<T>(x);
}

template<class T>
DetailsScopeGuard::ScopeGuardImpl<T> MakeScopeGuard(T x)
{
    return DetailsScopeGuard::ScopeGuardImpl<T>(x);
}

typedef const DetailsScopeGuard::ScopeGuardAnonBase & ScopeGuardAnon;
typedef const DetailsScopeGuard::ScopeGuardBase & ScopeGuard;

#define ANONYMOUS_VARIABLE(str) BOOST_JOIN(str, __LINE__)

// Make a ScopeGuardAnon reference object which points to a
// DetailsScopeGuard::ScopeGuardImpl<T> object.
#define MAKE_SCOPE_GUARD( _X_ ) ScopeGuardAnon \
ANONYMOUS_VARIABLE(ScopeGuard) = MakeScopeGuardAnon( _X_ ); \
no_unused_variable_warning(ANONYMOUS_VARIABLE(ScopeGuard))

------------ cut here -------------

Suggestions are welcomed. I don't think there is an easy way to add
functionality/speed even though I'm more looking for speed than
functionality.
As you may guess, I renamed OnReturn to ScopeGuard :)

Marc-Antoine Ruel

Thorsten Ottosen wrote:

>
> > Hi all,
> >
> > I've missed this functionality many times and I think it would be very
> > nice to have this in the function lib. What do you think?
>
> I'm would like to something like it.
>
> br
>
> Thorsten
>


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