added convenient wxON_BLOCK_EXIT_SET() macro
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@52857 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -226,6 +226,7 @@ All:
|
|||||||
if the wxVariantData::Clone function is implemented.
|
if the wxVariantData::Clone function is implemented.
|
||||||
- Added wxWeakRef<T>, wxScopedPtr<T>, wxSharedPtr<T> class templates
|
- Added wxWeakRef<T>, wxScopedPtr<T>, wxSharedPtr<T> class templates
|
||||||
- Added wxVector<T> class templates
|
- Added wxVector<T> class templates
|
||||||
|
- Added wxON_BLOCK_EXIT_SET() and wxON_BLOCK_EXIT_NULL() to wx/scopeguard.h.
|
||||||
|
|
||||||
All (Unix):
|
All (Unix):
|
||||||
|
|
||||||
|
@@ -51,9 +51,12 @@
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#if !defined(__GNUC__) || wxCHECK_GCC_VERSION(2, 95)
|
|
||||||
// namespace support was first implemented in gcc-2.95,
|
// namespace support was first implemented in gcc-2.95,
|
||||||
// so avoid using it for older versions.
|
// so avoid using it for older versions.
|
||||||
|
#if !defined(__GNUC__) || wxCHECK_GCC_VERSION(2, 95)
|
||||||
|
|
||||||
|
#define wxHAS_NAMESPACES
|
||||||
|
|
||||||
namespace wxPrivate
|
namespace wxPrivate
|
||||||
{
|
{
|
||||||
#else
|
#else
|
||||||
@@ -124,6 +127,9 @@ private:
|
|||||||
wxScopeGuardImplBase& operator=(const wxScopeGuardImplBase&);
|
wxScopeGuardImplBase& operator=(const wxScopeGuardImplBase&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// wxScopeGuard is just a reference, see the explanation in CUJ article
|
||||||
|
typedef const wxScopeGuardImplBase& wxScopeGuard;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxScopeGuardImpl0: scope guard for actions without parameters
|
// wxScopeGuardImpl0: scope guard for actions without parameters
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -318,21 +324,98 @@ wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
|
|||||||
MakeObjGuard(obj, memFun, p1, p2);
|
MakeObjGuard(obj, memFun, p1, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxVariableSetter: use the same technique as for wxScopeGuard to allow
|
||||||
|
// setting a variable to some value on block exit
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef wxHAS_NAMESPACES
|
||||||
|
|
||||||
|
namespace wxPrivate
|
||||||
|
{
|
||||||
|
|
||||||
|
// empty class just to be able to define a reference to it
|
||||||
|
class VariableSetterBase { };
|
||||||
|
|
||||||
|
typedef const VariableSetterBase& VariableSetter;
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
class VariableSetterImpl : public VariableSetterBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VariableSetterImpl(T& var, const U& value)
|
||||||
|
: m_var(var),
|
||||||
|
m_value(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~VariableSetterImpl()
|
||||||
|
{
|
||||||
|
m_var = m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T& m_var;
|
||||||
|
const U& m_value;
|
||||||
|
|
||||||
|
// suppress the warning about assignment operator not being generated
|
||||||
|
VariableSetterImpl<T, U>& operator=(const VariableSetterImpl<T, U>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class VariableNullerImpl : public VariableSetterBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VariableNullerImpl(T& var)
|
||||||
|
: m_var(var)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~VariableNullerImpl()
|
||||||
|
{
|
||||||
|
m_var = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T& m_var;
|
||||||
|
|
||||||
|
VariableNullerImpl<T>& operator=(const VariableNullerImpl<T>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace wxPrivate
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
inline
|
||||||
|
wxPrivate::VariableSetterImpl<T, U> wxMakeVarSetter(T& var, const U& value)
|
||||||
|
{
|
||||||
|
return wxPrivate::VariableSetterImpl<T, U>(var, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// calling wxMakeVarSetter(ptr, NULL) doesn't work because U is deduced to be
|
||||||
|
// "int" and subsequent assignment of "U" to "T *" fails, so provide a special
|
||||||
|
// function for this special case
|
||||||
|
template <typename T>
|
||||||
|
inline
|
||||||
|
wxPrivate::VariableNullerImpl<T> wxMakeVarNuller(T& var)
|
||||||
|
{
|
||||||
|
return wxPrivate::VariableNullerImpl<T>(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // wxHAS_NAMESPACES
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// public stuff
|
// macros for declaring unnamed scoped guards (which can't be dismissed)
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
// wxScopeGuard is just a reference, see the explanation in CUJ article
|
|
||||||
typedef const wxScopeGuardImplBase& wxScopeGuard;
|
|
||||||
|
|
||||||
// when an unnamed scope guard is needed, the macros below may be used
|
|
||||||
//
|
|
||||||
// NB: the original code has a single (and much nicer) ON_BLOCK_EXIT macro
|
// NB: the original code has a single (and much nicer) ON_BLOCK_EXIT macro
|
||||||
// but this results in compiler warnings about unused variables and I
|
// but this results in compiler warnings about unused variables and I
|
||||||
// didn't find a way to work around this other than by having different
|
// didn't find a way to work around this other than by having different
|
||||||
// macros with different names
|
// macros with different names or using a less natural syntax for passing
|
||||||
|
// the arguments (e.g. as Boost preprocessor sequences, which would mean
|
||||||
|
// having to write wxON_BLOCK_EXIT(fwrite, (buf)(size)(n)(fp)) instead of
|
||||||
|
// wxON_BLOCK_EXIT4(fwrite, buf, size, n, fp)).
|
||||||
|
|
||||||
#define wxGuardName wxMAKE_UNIQUE_NAME(scopeGuard)
|
#define wxGuardName wxMAKE_UNIQUE_NAME(wxScopeGuard)
|
||||||
|
|
||||||
#define wxON_BLOCK_EXIT0_IMPL(n, f) \
|
#define wxON_BLOCK_EXIT0_IMPL(n, f) \
|
||||||
wxScopeGuard n = wxMakeGuard(f); \
|
wxScopeGuard n = wxMakeGuard(f); \
|
||||||
@@ -381,4 +464,21 @@ typedef const wxScopeGuardImplBase& wxScopeGuard;
|
|||||||
#define wxON_BLOCK_EXIT_THIS2(m, p1, p2) \
|
#define wxON_BLOCK_EXIT_THIS2(m, p1, p2) \
|
||||||
wxON_BLOCK_EXIT_OBJ2(*this, m, p1, p2)
|
wxON_BLOCK_EXIT_OBJ2(*this, m, p1, p2)
|
||||||
|
|
||||||
|
|
||||||
|
#define wxSetterName wxMAKE_UNIQUE_NAME(wxVarSetter)
|
||||||
|
|
||||||
|
#define wxON_BLOCK_EXIT_SET_IMPL(n, var, value) \
|
||||||
|
wxPrivate::VariableSetter n = wxMakeVarSetter(var, value); \
|
||||||
|
wxPrivateUse(n)
|
||||||
|
|
||||||
|
#define wxON_BLOCK_EXIT_SET(var, value) \
|
||||||
|
wxON_BLOCK_EXIT_SET_IMPL(wxSetterName, var, value)
|
||||||
|
|
||||||
|
#define wxON_BLOCK_EXIT_NULL_IMPL(n, var) \
|
||||||
|
wxPrivate::VariableSetter n = wxMakeVarNuller(var); \
|
||||||
|
wxPrivateUse(n)
|
||||||
|
|
||||||
|
#define wxON_BLOCK_EXIT_NULL(ptr) \
|
||||||
|
wxON_BLOCK_EXIT_NULL_IMPL(wxSetterName, ptr)
|
||||||
|
|
||||||
#endif // _WX_SCOPEGUARD_H_
|
#endif // _WX_SCOPEGUARD_H_
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
//@{
|
//@{
|
||||||
/**
|
/**
|
||||||
This macro ensures that the global @a function with 0, 1, 2 or more
|
This macro ensures that the global @a function with 0, 1, 2 or more
|
||||||
parameters (up to some implementaton-defined limit) is executed on scope
|
parameters (up to some implementation-defined limit) is executed on scope
|
||||||
exit, whether due to a normal function return or because an exception has
|
exit, whether due to a normal function return or because an exception has
|
||||||
been thrown. A typical example of its usage:
|
been thrown. A typical example of its usage:
|
||||||
|
|
||||||
@@ -57,3 +57,39 @@
|
|||||||
#define wxON_BLOCK_EXIT_THIS2(method, p1, p2)
|
#define wxON_BLOCK_EXIT_THIS2(method, p1, p2)
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
/** @ingroup group_funcmacro_misc */
|
||||||
|
//@{
|
||||||
|
/**
|
||||||
|
This macro sets a variable to the specified value on scope exit.
|
||||||
|
|
||||||
|
Example of usage:
|
||||||
|
@code
|
||||||
|
void foo()
|
||||||
|
{
|
||||||
|
bool isDoingSomething = true;
|
||||||
|
{
|
||||||
|
wxON_BLOCK_EXIT_SET(isDoingSomething, false);
|
||||||
|
... do something ...
|
||||||
|
}
|
||||||
|
... isDoingSomething is false now ...
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@see wxON_BLOCK_EXIT_OBJ0(), wxON_BLOCK_EXIT_NULL()
|
||||||
|
|
||||||
|
@header{wx/scopeguard.h}
|
||||||
|
*/
|
||||||
|
#define wxON_BLOCK_EXIT_SET(var, value)
|
||||||
|
|
||||||
|
/**
|
||||||
|
This macro sets the pointer passed to it as argument to NULL on scope exit.
|
||||||
|
|
||||||
|
It must be used instead of wxON_BLOCK_EXIT_SET() when the value being set
|
||||||
|
is @c NULL.
|
||||||
|
|
||||||
|
@header{wx/scopeguard.h}
|
||||||
|
*/
|
||||||
|
#define wxON_BLOCK_EXIT_NULL(ptr)
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
@@ -61,6 +61,7 @@ public:
|
|||||||
CPPUNIT_TEST(BlockExit);
|
CPPUNIT_TEST(BlockExit);
|
||||||
CPPUNIT_TEST(BlockExitObj);
|
CPPUNIT_TEST(BlockExitObj);
|
||||||
CPPUNIT_TEST(BlockExitThis);
|
CPPUNIT_TEST(BlockExitThis);
|
||||||
|
CPPUNIT_TEST(BlockExitSetVar);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
void Normal();
|
void Normal();
|
||||||
@@ -68,6 +69,7 @@ public:
|
|||||||
void BlockExit();
|
void BlockExit();
|
||||||
void BlockExitObj();
|
void BlockExitObj();
|
||||||
void BlockExitThis();
|
void BlockExitThis();
|
||||||
|
void BlockExitSetVar();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Zero() { m_count = 0; }
|
void Zero() { m_count = 0; }
|
||||||
@@ -206,3 +208,39 @@ void ScopeGuardTestCase::BlockExitThis()
|
|||||||
CPPUNIT_ASSERT_EQUAL( 5, m_count );
|
CPPUNIT_ASSERT_EQUAL( 5, m_count );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScopeGuardTestCase::BlockExitSetVar()
|
||||||
|
{
|
||||||
|
m_count = 1;
|
||||||
|
{
|
||||||
|
wxON_BLOCK_EXIT_SET(m_count, 17);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL( 1, m_count );
|
||||||
|
}
|
||||||
|
CPPUNIT_ASSERT_EQUAL( 17, m_count );
|
||||||
|
|
||||||
|
|
||||||
|
int count = 1;
|
||||||
|
{
|
||||||
|
wxON_BLOCK_EXIT_SET(count, 17);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL( 1, count );
|
||||||
|
}
|
||||||
|
CPPUNIT_ASSERT_EQUAL( 17, count );
|
||||||
|
|
||||||
|
|
||||||
|
wxString s("hi");
|
||||||
|
{
|
||||||
|
wxON_BLOCK_EXIT_SET(s, "bye");
|
||||||
|
|
||||||
|
WX_ASSERT_STR_EQUAL( "hi", s );
|
||||||
|
}
|
||||||
|
WX_ASSERT_STR_EQUAL( "bye", s );
|
||||||
|
|
||||||
|
ScopeGuardTestCase *p = this;
|
||||||
|
{
|
||||||
|
wxON_BLOCK_EXIT_NULL(p);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT( p );
|
||||||
|
}
|
||||||
|
CPPUNIT_ASSERT( !p );
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user