X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/822fc19ef0224d2a257bf01de60a5f5b8506b857..da8b1d4b3b535aba94d04494f5b6e2b3e47901ee:/include/wx/scopeguard.h diff --git a/include/wx/scopeguard.h b/include/wx/scopeguard.h index b8152964a0..da056e08db 100644 --- a/include/wx/scopeguard.h +++ b/include/wx/scopeguard.h @@ -51,8 +51,17 @@ #else +// namespace support was first implemented in gcc-2.95, +// so avoid using it for older versions. +#if !defined(__GNUC__) || wxCHECK_GCC_VERSION(2, 95) + +#define wxHAS_NAMESPACES + namespace wxPrivate { +#else +#define wxPrivate +#endif // in the original implementation this was a member template function of // ScopeGuardImplBase but gcc 2.8 which is still used for OS/2 doesn't // support member templates and so we must make it global @@ -75,7 +84,9 @@ namespace wxPrivate void Use(const T& WXUNUSED(t)) { } +#if !defined(__GNUC__) || wxCHECK_GCC_VERSION(2, 95) } // namespace wxPrivate +#endif #define wxPrivateOnScopeExit(n) wxPrivate::OnScopeExit(n) #define wxPrivateUse(n) wxPrivate::Use(n) @@ -95,6 +106,12 @@ class wxScopeGuardImplBase public: wxScopeGuardImplBase() : m_wasDismissed(false) { } + wxScopeGuardImplBase(const wxScopeGuardImplBase& other) + : m_wasDismissed(other.m_wasDismissed) + { + other.Dismiss(); + } + void Dismiss() const { m_wasDismissed = true; } // for OnScopeExit() only (we can't make it friend, unfortunately)! @@ -103,12 +120,6 @@ public: protected: ~wxScopeGuardImplBase() { } - wxScopeGuardImplBase(const wxScopeGuardImplBase& other) - : m_wasDismissed(other.m_wasDismissed) - { - other.Dismiss(); - } - // must be mutable for copy ctor to work mutable bool m_wasDismissed; @@ -116,6 +127,9 @@ private: 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 // ---------------------------------------------------------------------------- @@ -212,6 +226,41 @@ inline wxScopeGuardImpl2<F, P1, P2> wxMakeGuard(F fun, P1 p1, P2 p2) return wxScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2); } +// ---------------------------------------------------------------------------- +// wxScopeGuardImpl3: scope guard for actions with 3 parameters +// ---------------------------------------------------------------------------- + +template <class F, class P1, class P2, class P3> +class wxScopeGuardImpl3 : public wxScopeGuardImplBase +{ +public: + static wxScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3) + { + return wxScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3); + } + + ~wxScopeGuardImpl3() { wxPrivateOnScopeExit(*this); } + + void Execute() { m_fun(m_p1, m_p2, m_p3); } + +protected: + wxScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) + : m_fun(fun), m_p1(p1), m_p2(p2), m_p3(p3) { } + + F m_fun; + const P1 m_p1; + const P2 m_p2; + const P3 m_p3; + + wxScopeGuardImpl3& operator=(const wxScopeGuardImpl3&); +}; + +template <class F, class P1, class P2, class P3> +inline wxScopeGuardImpl3<F, P1, P2, P3> wxMakeGuard(F fun, P1 p1, P2 p2, P3 p3) +{ + return wxScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3); +} + // ============================================================================ // wxScopeGuards for object methods // ============================================================================ @@ -310,21 +359,131 @@ wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) MakeObjGuard(obj, memFun, p1, p2); } +template <class Obj, class MemFun, class P1, class P2, class P3> +class wxObjScopeGuardImpl3 : public wxScopeGuardImplBase +{ +public: + static wxObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3> + MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2, P3 p3) + { + return wxObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3>(obj, memFun, p1, p2, p3); + } + + ~wxObjScopeGuardImpl3() { wxPrivateOnScopeExit(*this); } + + void Execute() { (m_obj.*m_memfun)(m_p1, m_p2, m_p3); } + +protected: + wxObjScopeGuardImpl3(Obj& obj, MemFun memFun, P1 p1, P2 p2, P3 p3) + : m_obj(obj), m_memfun(memFun), m_p1(p1), m_p2(p2), m_p3(p3) { } + + Obj& m_obj; + MemFun m_memfun; + const P1 m_p1; + const P2 m_p2; + const P3 m_p3; +}; + +template <class Obj, class MemFun, class P1, class P2, class P3> +inline wxObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3> +wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2, P3 p3) +{ + return wxObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3>:: + MakeObjGuard(obj, memFun, p1, p2, p3); +} + +// ---------------------------------------------------------------------------- +// 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, 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, 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 // 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 -// 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) \ wxScopeGuard n = wxMakeGuard(f); \ @@ -336,7 +495,11 @@ typedef const wxScopeGuardImplBase& wxScopeGuard; wxScopeGuard n = wxMakeObjGuard(o, m); \ wxPrivateUse(n) #define wxON_BLOCK_EXIT_OBJ0(o, m) \ - wxON_BLOCK_EXIT_OBJ0_IMPL(wxGuardName, o, m) + wxON_BLOCK_EXIT_OBJ0_IMPL(wxGuardName, o, &m) + +#define wxON_BLOCK_EXIT_THIS0(m) \ + wxON_BLOCK_EXIT_OBJ0(*this, m) + #define wxON_BLOCK_EXIT1_IMPL(n, f, p1) \ wxScopeGuard n = wxMakeGuard(f, p1); \ @@ -348,7 +511,11 @@ typedef const wxScopeGuardImplBase& wxScopeGuard; wxScopeGuard n = wxMakeObjGuard(o, m, p1); \ wxPrivateUse(n) #define wxON_BLOCK_EXIT_OBJ1(o, m, p1) \ - wxON_BLOCK_EXIT_OBJ1_IMPL(wxGuardName, o, m, p1) + wxON_BLOCK_EXIT_OBJ1_IMPL(wxGuardName, o, &m, p1) + +#define wxON_BLOCK_EXIT_THIS1(m, p1) \ + wxON_BLOCK_EXIT_OBJ1(*this, m, p1) + #define wxON_BLOCK_EXIT2_IMPL(n, f, p1, p2) \ wxScopeGuard n = wxMakeGuard(f, p1, p2); \ @@ -360,6 +527,42 @@ typedef const wxScopeGuardImplBase& wxScopeGuard; wxScopeGuard n = wxMakeObjGuard(o, m, p1, p2); \ wxPrivateUse(n) #define wxON_BLOCK_EXIT_OBJ2(o, m, p1, p2) \ - wxON_BLOCK_EXIT_OBJ2_IMPL(wxGuardName, o, m, p1, p2) + wxON_BLOCK_EXIT_OBJ2_IMPL(wxGuardName, o, &m, p1, p2) + +#define wxON_BLOCK_EXIT_THIS2(m, p1, p2) \ + wxON_BLOCK_EXIT_OBJ2(*this, m, p1, p2) + + +#define wxON_BLOCK_EXIT3_IMPL(n, f, p1, p2, p3) \ + wxScopeGuard n = wxMakeGuard(f, p1, p2, p3); \ + wxPrivateUse(n) +#define wxON_BLOCK_EXIT3(f, p1, p2, p3) \ + wxON_BLOCK_EXIT3_IMPL(wxGuardName, f, p1, p2, p3) + +#define wxON_BLOCK_EXIT_OBJ3_IMPL(n, o, m, p1, p2, p3) \ + wxScopeGuard n = wxMakeObjGuard(o, m, p1, p2, p3); \ + wxPrivateUse(n) +#define wxON_BLOCK_EXIT_OBJ3(o, m, p1, p2, p3) \ + wxON_BLOCK_EXIT_OBJ3_IMPL(wxGuardName, o, &m, p1, p2, p3) + +#define wxON_BLOCK_EXIT_THIS3(m, p1, p2, p3) \ + wxON_BLOCK_EXIT_OBJ3(*this, m, p1, p2, p3) + + +#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_