1/////////////////////////////////////////////////////////////////////////////// 2// Name: wx/scopeguard.h 3// Purpose: declares wxwxScopeGuard and related macros 4// Author: Vadim Zeitlin 5// Modified by: 6// Created: 03.07.2003 7// RCS-ID: $Id: scopeguard.h 44111 2007-01-07 13:28:16Z SN $ 8// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwidgets.org> 9// Licence: wxWindows licence 10/////////////////////////////////////////////////////////////////////////////// 11 12/* 13 Acknowledgements: this header is heavily based on (well, almost the exact 14 copy of) ScopeGuard.h by Andrei Alexandrescu and Petru Marginean published 15 in December 2000 issue of C/C++ Users Journal. 16 http://www.cuj.com/documents/cujcexp1812alexandr/ 17 */ 18 19#ifndef _WX_SCOPEGUARD_H_ 20#define _WX_SCOPEGUARD_H_ 21 22#include "wx/defs.h" 23 24#include "wx/except.h" 25 26// ---------------------------------------------------------------------------- 27// helpers 28// ---------------------------------------------------------------------------- 29 30#ifdef __WATCOMC__ 31 32// WATCOM-FIXME: C++ of Open Watcom 1.3 doesn't like OnScopeExit() created 33// through template so it must be workarounded with dedicated inlined macro. 34// For compatibility with Watcom compilers wxPrivate::OnScopeExit must be 35// replaced with wxPrivateOnScopeExit but in user code (for everyone who 36// doesn't care about OW compatibility) wxPrivate::OnScopeExit still works. 37 38#define wxPrivateOnScopeExit(guard) \ 39 { \ 40 if ( !(guard).WasDismissed() ) \ 41 { \ 42 wxTRY \ 43 { \ 44 (guard).Execute(); \ 45 } \ 46 wxCATCH_ALL(;) \ 47 } \ 48 } 49 50#define wxPrivateUse(n) wxUnusedVar(n) 51 52#else 53 54#if !defined(__GNUC__) || wxCHECK_GCC_VERSION(2, 95) 55// namespace support was first implemented in gcc-2.95, 56// so avoid using it for older versions. 57namespace wxPrivate 58{ 59#else 60#define wxPrivate 61#endif 62 // in the original implementation this was a member template function of 63 // ScopeGuardImplBase but gcc 2.8 which is still used for OS/2 doesn't 64 // support member templates and so we must make it global 65 template <class ScopeGuardImpl> 66 void OnScopeExit(ScopeGuardImpl& guard) 67 { 68 if ( !guard.WasDismissed() ) 69 { 70 // we're called from ScopeGuardImpl dtor and so we must not throw 71 wxTRY 72 { 73 guard.Execute(); 74 } 75 wxCATCH_ALL(;) // do nothing, just eat the exception 76 } 77 } 78 79 // just to avoid the warning about unused variables 80 template <class T> 81 void Use(const T& WXUNUSED(t)) 82 { 83 } 84#if !defined(__GNUC__) || wxCHECK_GCC_VERSION(2, 95) 85} // namespace wxPrivate 86#endif 87 88#define wxPrivateOnScopeExit(n) wxPrivate::OnScopeExit(n) 89#define wxPrivateUse(n) wxPrivate::Use(n) 90 91#endif 92 93// ============================================================================ 94// wxScopeGuard for functions and functors 95// ============================================================================ 96 97// ---------------------------------------------------------------------------- 98// wxScopeGuardImplBase: used by wxScopeGuardImpl[0..N] below 99// ---------------------------------------------------------------------------- 100 101class wxScopeGuardImplBase 102{ 103public: 104 wxScopeGuardImplBase() : m_wasDismissed(false) { } 105 106 void Dismiss() const { m_wasDismissed = true; } 107 108 // for OnScopeExit() only (we can't make it friend, unfortunately)! 109 bool WasDismissed() const { return m_wasDismissed; } 110 111protected: 112 ~wxScopeGuardImplBase() { } 113 114 wxScopeGuardImplBase(const wxScopeGuardImplBase& other) 115 : m_wasDismissed(other.m_wasDismissed) 116 { 117 other.Dismiss(); 118 } 119 120 // must be mutable for copy ctor to work 121 mutable bool m_wasDismissed; 122 123private: 124 wxScopeGuardImplBase& operator=(const wxScopeGuardImplBase&); 125}; 126 127// ---------------------------------------------------------------------------- 128// wxScopeGuardImpl0: scope guard for actions without parameters 129// ---------------------------------------------------------------------------- 130 131template <class F> 132class wxScopeGuardImpl0 : public wxScopeGuardImplBase 133{ 134public: 135 static wxScopeGuardImpl0<F> MakeGuard(F fun) 136 { 137 return wxScopeGuardImpl0<F>(fun); 138 } 139 140 ~wxScopeGuardImpl0() { wxPrivateOnScopeExit(*this); } 141 142 void Execute() { m_fun(); } 143 144protected: 145 wxScopeGuardImpl0(F fun) : m_fun(fun) { } 146 147 F m_fun; 148 149 wxScopeGuardImpl0& operator=(const wxScopeGuardImpl0&); 150}; 151 152template <class F> 153inline wxScopeGuardImpl0<F> wxMakeGuard(F fun) 154{ 155 return wxScopeGuardImpl0<F>::MakeGuard(fun); 156} 157 158// ---------------------------------------------------------------------------- 159// wxScopeGuardImpl1: scope guard for actions with 1 parameter 160// ---------------------------------------------------------------------------- 161 162template <class F, class P1> 163class wxScopeGuardImpl1 : public wxScopeGuardImplBase 164{ 165public: 166 static wxScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1) 167 { 168 return wxScopeGuardImpl1<F, P1>(fun, p1); 169 } 170 171 ~wxScopeGuardImpl1() { wxPrivateOnScopeExit(* this); } 172 173 void Execute() { m_fun(m_p1); } 174 175protected: 176 wxScopeGuardImpl1(F fun, P1 p1) : m_fun(fun), m_p1(p1) { } 177 178 F m_fun; 179 const P1 m_p1; 180 181 wxScopeGuardImpl1& operator=(const wxScopeGuardImpl1&); 182}; 183 184template <class F, class P1> 185inline wxScopeGuardImpl1<F, P1> wxMakeGuard(F fun, P1 p1) 186{ 187 return wxScopeGuardImpl1<F, P1>::MakeGuard(fun, p1); 188} 189 190// ---------------------------------------------------------------------------- 191// wxScopeGuardImpl2: scope guard for actions with 2 parameters 192// ---------------------------------------------------------------------------- 193 194template <class F, class P1, class P2> 195class wxScopeGuardImpl2 : public wxScopeGuardImplBase 196{ 197public: 198 static wxScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2) 199 { 200 return wxScopeGuardImpl2<F, P1, P2>(fun, p1, p2); 201 } 202 203 ~wxScopeGuardImpl2() { wxPrivateOnScopeExit(*this); } 204 205 void Execute() { m_fun(m_p1, m_p2); } 206 207protected: 208 wxScopeGuardImpl2(F fun, P1 p1, P2 p2) : m_fun(fun), m_p1(p1), m_p2(p2) { } 209 210 F m_fun; 211 const P1 m_p1; 212 const P2 m_p2; 213 214 wxScopeGuardImpl2& operator=(const wxScopeGuardImpl2&); 215}; 216 217template <class F, class P1, class P2> 218inline wxScopeGuardImpl2<F, P1, P2> wxMakeGuard(F fun, P1 p1, P2 p2) 219{ 220 return wxScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2); 221} 222 223// ============================================================================ 224// wxScopeGuards for object methods 225// ============================================================================ 226 227// ---------------------------------------------------------------------------- 228// wxObjScopeGuardImpl0 229// ---------------------------------------------------------------------------- 230 231template <class Obj, class MemFun> 232class wxObjScopeGuardImpl0 : public wxScopeGuardImplBase 233{ 234public: 235 static wxObjScopeGuardImpl0<Obj, MemFun> 236 MakeObjGuard(Obj& obj, MemFun memFun) 237 { 238 return wxObjScopeGuardImpl0<Obj, MemFun>(obj, memFun); 239 } 240 241 ~wxObjScopeGuardImpl0() { wxPrivateOnScopeExit(*this); } 242 243 void Execute() { (m_obj.*m_memfun)(); } 244 245protected: 246 wxObjScopeGuardImpl0(Obj& obj, MemFun memFun) 247 : m_obj(obj), m_memfun(memFun) { } 248 249 Obj& m_obj; 250 MemFun m_memfun; 251}; 252 253template <class Obj, class MemFun> 254inline wxObjScopeGuardImpl0<Obj, MemFun> wxMakeObjGuard(Obj& obj, MemFun memFun) 255{ 256 return wxObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun); 257} 258 259template <class Obj, class MemFun, class P1> 260class wxObjScopeGuardImpl1 : public wxScopeGuardImplBase 261{ 262public: 263 static wxObjScopeGuardImpl1<Obj, MemFun, P1> 264 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1) 265 { 266 return wxObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1); 267 } 268 269 ~wxObjScopeGuardImpl1() { wxPrivateOnScopeExit(*this); } 270 271 void Execute() { (m_obj.*m_memfun)(m_p1); } 272 273protected: 274 wxObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) 275 : m_obj(obj), m_memfun(memFun), m_p1(p1) { } 276 277 Obj& m_obj; 278 MemFun m_memfun; 279 const P1 m_p1; 280}; 281 282template <class Obj, class MemFun, class P1> 283inline wxObjScopeGuardImpl1<Obj, MemFun, P1> 284wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1) 285{ 286 return wxObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1); 287} 288 289template <class Obj, class MemFun, class P1, class P2> 290class wxObjScopeGuardImpl2 : public wxScopeGuardImplBase 291{ 292public: 293 static wxObjScopeGuardImpl2<Obj, MemFun, P1, P2> 294 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) 295 { 296 return wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2); 297 } 298 299 ~wxObjScopeGuardImpl2() { wxPrivateOnScopeExit(*this); } 300 301 void Execute() { (m_obj.*m_memfun)(m_p1, m_p2); } 302 303protected: 304 wxObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) 305 : m_obj(obj), m_memfun(memFun), m_p1(p1), m_p2(p2) { } 306 307 Obj& m_obj; 308 MemFun m_memfun; 309 const P1 m_p1; 310 const P2 m_p2; 311}; 312 313template <class Obj, class MemFun, class P1, class P2> 314inline wxObjScopeGuardImpl2<Obj, MemFun, P1, P2> 315wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) 316{ 317 return wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>:: 318 MakeObjGuard(obj, memFun, p1, p2); 319} 320 321// ============================================================================ 322// public stuff 323// ============================================================================ 324 325// wxScopeGuard is just a reference, see the explanation in CUJ article 326typedef const wxScopeGuardImplBase& wxScopeGuard; 327 328// when an unnamed scope guard is needed, the macros below may be used 329// 330// NB: the original code has a single (and much nicer) ON_BLOCK_EXIT macro 331// but this results in compiler warnings about unused variables and I 332// didn't find a way to work around this other than by having different 333// macros with different names 334 335#define wxGuardName wxMAKE_UNIQUE_NAME(scopeGuard) 336 337#define wxON_BLOCK_EXIT0_IMPL(n, f) \ 338 wxScopeGuard n = wxMakeGuard(f); \ 339 wxPrivateUse(n) 340#define wxON_BLOCK_EXIT0(f) \ 341 wxON_BLOCK_EXIT0_IMPL(wxGuardName, f) 342 343#define wxON_BLOCK_EXIT_OBJ0_IMPL(n, o, m) \ 344 wxScopeGuard n = wxMakeObjGuard(o, m); \ 345 wxPrivateUse(n) 346#define wxON_BLOCK_EXIT_OBJ0(o, m) \ 347 wxON_BLOCK_EXIT_OBJ0_IMPL(wxGuardName, o, &m) 348 349#define wxON_BLOCK_EXIT1_IMPL(n, f, p1) \ 350 wxScopeGuard n = wxMakeGuard(f, p1); \ 351 wxPrivateUse(n) 352#define wxON_BLOCK_EXIT1(f, p1) \ 353 wxON_BLOCK_EXIT1_IMPL(wxGuardName, f, p1) 354 355#define wxON_BLOCK_EXIT_OBJ1_IMPL(n, o, m, p1) \ 356 wxScopeGuard n = wxMakeObjGuard(o, m, p1); \ 357 wxPrivateUse(n) 358#define wxON_BLOCK_EXIT_OBJ1(o, m, p1) \ 359 wxON_BLOCK_EXIT_OBJ1_IMPL(wxGuardName, o, &m, p1) 360 361#define wxON_BLOCK_EXIT2_IMPL(n, f, p1, p2) \ 362 wxScopeGuard n = wxMakeGuard(f, p1, p2); \ 363 wxPrivateUse(n) 364#define wxON_BLOCK_EXIT2(f, p1, p2) \ 365 wxON_BLOCK_EXIT2_IMPL(wxGuardName, f, p1, p2) 366 367#define wxON_BLOCK_EXIT_OBJ2_IMPL(n, o, m, p1, p2) \ 368 wxScopeGuard n = wxMakeObjGuard(o, m, p1, p2); \ 369 wxPrivateUse(n) 370#define wxON_BLOCK_EXIT_OBJ2(o, m, p1, p2) \ 371 wxON_BLOCK_EXIT_OBJ2_IMPL(wxGuardName, o, &m, p1, p2) 372 373#endif // _WX_SCOPEGUARD_H_ 374