Exception Safe Code - RAII
Hi,
I just read an (old) ddj article of Andrej Alexandrescu about a nifty
RAII-supporting class for exception-safety issues. He uses the some
kind of the following pattern:
class ScopeGuardImplBase
{
mutable bool dismissed_;
public:
void dismiss() const
{ dismissed_ = true; }
bool dismissed()
{ return dismissed_; }
protected:
ScopeGuardImplBase()
: dismissed_( false )
{ }
ScopeGuardImplBase( ScopeGuardImplBase& other )
: dismissed_( other.dismissed_ )
{ }
~ScopeGuardImplBase()
{ }
private:
ScopeGuardImplBase& operator=( const ScopeGuardImplBase& );
};
template <typename Func, typename Parm>
class ScopeGuardImpl1 : public ScopeGuardImplBase
{
const Func& func_;
const Parm parm_;
public:
ScopeGuardImpl1( const Func& func, const Parm& parm )
: func_( func )
, parm_( parm )
{ }
ScopeGuardImpl1( const ScopeGuardImpl1& other )
: func_( other.func_ )
, parm_( other.parm_ )
{ }
~ScopeGuardImpl1()
{ if ( ! dismissed() ) func_( parm_ ); }
private:
ScopeGuardImpl1& operator=( const ScopeGuardImpl1& );
};
// Convenience-Function to allow template-argument deduction
template <typename Func, typename Parm>
ScopeGuardImpl1<Func, Parm> makeScopeGuard(
const Func& func, const Parm& parm )
{
return ScopeGuardImpl1<Func, Parm>( func, parm );
}
typedef const ScopeGuardImplBase& ScopeGuard;
There are other templates to support more (or less) arguments and
member functions, but that doesn't matter here.
The intention is do automize the RAII idiom.
I.e. (please don't mind the global variables and the use of malloc,
it's just for simplicity):
#include <memory.h>
char *v1 = 0;
char *v2 = 0;
void cleanUpVar( char** v )
{
free( *v );
*v = 0;
}
void initVars( size_t v1Size, size_t v2Size )
{
v1 = (char*) malloc( v1Size );
ScopeGuard sg = makeScopeGuard( cleanUpVar, &v1 );
v2 = (char*) malloc( v2Size );
sg.dismiss();
}
Did Andrej forget a 'try..catch'-clause in the D'tor of
ScopeGuardImpl1?
In my example free() can't throw. But the template can be used for any
cleanup-Function.
Isn't it necessary to define D'tor as follows?
ScopeGuardImpl1::~ScopeGuardImpl1() //thow()
{
try {
if ( ! dismissed() ) func_( parm_ );
}
catch (...) {
}
}
Why not?
Best regards
Kasimir
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]