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.
57 namespace 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>
OnScopeExit(ScopeGuardImpl & guard)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>
Use(const T & WXUNUSED (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 
101 class wxScopeGuardImplBase
102 {
103 public:
wxScopeGuardImplBase()104     wxScopeGuardImplBase() : m_wasDismissed(false) { }
105 
Dismiss()106     void Dismiss() const { m_wasDismissed = true; }
107 
108     // for OnScopeExit() only (we can't make it friend, unfortunately)!
WasDismissed()109     bool WasDismissed() const { return m_wasDismissed; }
110 
111 protected:
~wxScopeGuardImplBase()112     ~wxScopeGuardImplBase() { }
113 
wxScopeGuardImplBase(const wxScopeGuardImplBase & other)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 
123 private:
124     wxScopeGuardImplBase& operator=(const wxScopeGuardImplBase&);
125 };
126 
127 // ----------------------------------------------------------------------------
128 // wxScopeGuardImpl0: scope guard for actions without parameters
129 // ----------------------------------------------------------------------------
130 
131 template <class F>
132 class wxScopeGuardImpl0 : public wxScopeGuardImplBase
133 {
134 public:
MakeGuard(F fun)135     static wxScopeGuardImpl0<F> MakeGuard(F fun)
136     {
137         return wxScopeGuardImpl0<F>(fun);
138     }
139 
~wxScopeGuardImpl0()140     ~wxScopeGuardImpl0() { wxPrivateOnScopeExit(*this); }
141 
Execute()142     void Execute() { m_fun(); }
143 
144 protected:
wxScopeGuardImpl0(F fun)145     wxScopeGuardImpl0(F fun) : m_fun(fun) { }
146 
147     F m_fun;
148 
149     wxScopeGuardImpl0& operator=(const wxScopeGuardImpl0&);
150 };
151 
152 template <class F>
wxMakeGuard(F fun)153 inline 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 
162 template <class F, class P1>
163 class wxScopeGuardImpl1 : public wxScopeGuardImplBase
164 {
165 public:
MakeGuard(F fun,P1 p1)166     static wxScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
167     {
168         return wxScopeGuardImpl1<F, P1>(fun, p1);
169     }
170 
~wxScopeGuardImpl1()171     ~wxScopeGuardImpl1() { wxPrivateOnScopeExit(* this); }
172 
Execute()173     void Execute() { m_fun(m_p1); }
174 
175 protected:
wxScopeGuardImpl1(F fun,P1 p1)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 
184 template <class F, class P1>
wxMakeGuard(F fun,P1 p1)185 inline 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 
194 template <class F, class P1, class P2>
195 class wxScopeGuardImpl2 : public wxScopeGuardImplBase
196 {
197 public:
MakeGuard(F fun,P1 p1,P2 p2)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 
~wxScopeGuardImpl2()203     ~wxScopeGuardImpl2() { wxPrivateOnScopeExit(*this); }
204 
Execute()205     void Execute() { m_fun(m_p1, m_p2); }
206 
207 protected:
wxScopeGuardImpl2(F fun,P1 p1,P2 p2)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 
217 template <class F, class P1, class P2>
wxMakeGuard(F fun,P1 p1,P2 p2)218 inline 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 
231 template <class Obj, class MemFun>
232 class wxObjScopeGuardImpl0 : public wxScopeGuardImplBase
233 {
234 public:
235     static wxObjScopeGuardImpl0<Obj, MemFun>
MakeObjGuard(Obj & obj,MemFun memFun)236         MakeObjGuard(Obj& obj, MemFun memFun)
237     {
238         return wxObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
239     }
240 
~wxObjScopeGuardImpl0()241     ~wxObjScopeGuardImpl0() { wxPrivateOnScopeExit(*this); }
242 
Execute()243     void Execute() { (m_obj.*m_memfun)(); }
244 
245 protected:
wxObjScopeGuardImpl0(Obj & obj,MemFun memFun)246     wxObjScopeGuardImpl0(Obj& obj, MemFun memFun)
247         : m_obj(obj), m_memfun(memFun) { }
248 
249     Obj& m_obj;
250     MemFun m_memfun;
251 };
252 
253 template <class Obj, class MemFun>
wxMakeObjGuard(Obj & obj,MemFun memFun)254 inline wxObjScopeGuardImpl0<Obj, MemFun> wxMakeObjGuard(Obj& obj, MemFun memFun)
255 {
256     return wxObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
257 }
258 
259 template <class Obj, class MemFun, class P1>
260 class wxObjScopeGuardImpl1 : public wxScopeGuardImplBase
261 {
262 public:
263     static wxObjScopeGuardImpl1<Obj, MemFun, P1>
MakeObjGuard(Obj & obj,MemFun memFun,P1 p1)264         MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
265     {
266         return wxObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
267     }
268 
~wxObjScopeGuardImpl1()269     ~wxObjScopeGuardImpl1() { wxPrivateOnScopeExit(*this); }
270 
Execute()271     void Execute() { (m_obj.*m_memfun)(m_p1); }
272 
273 protected:
wxObjScopeGuardImpl1(Obj & obj,MemFun memFun,P1 p1)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 
282 template <class Obj, class MemFun, class P1>
283 inline wxObjScopeGuardImpl1<Obj, MemFun, P1>
wxMakeObjGuard(Obj & obj,MemFun memFun,P1 p1)284 wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
285 {
286     return wxObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
287 }
288 
289 template <class Obj, class MemFun, class P1, class P2>
290 class wxObjScopeGuardImpl2 : public wxScopeGuardImplBase
291 {
292 public:
293     static wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>
MakeObjGuard(Obj & obj,MemFun memFun,P1 p1,P2 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 
~wxObjScopeGuardImpl2()299     ~wxObjScopeGuardImpl2() { wxPrivateOnScopeExit(*this); }
300 
Execute()301     void Execute() { (m_obj.*m_memfun)(m_p1, m_p2); }
302 
303 protected:
wxObjScopeGuardImpl2(Obj & obj,MemFun memFun,P1 p1,P2 p2)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 
313 template <class Obj, class MemFun, class P1, class P2>
314 inline wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>
wxMakeObjGuard(Obj & obj,MemFun memFun,P1 p1,P2 p2)315 wxMakeObjGuard(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
326 typedef 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