]> git.saurik.com Git - wxWidgets.git/blame - include/wx/scopeguard.h
using Run of base class
[wxWidgets.git] / include / wx / scopeguard.h
CommitLineData
c66cca2a
VZ
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
77ffb593 7// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwidgets.org>
65571936 8// Licence: wxWindows licence
c66cca2a
VZ
9///////////////////////////////////////////////////////////////////////////////
10
11/*
12 Acknowledgements: this header is heavily based on (well, almost the exact
822fc19e 13 copy of) ScopeGuard.h by Andrei Alexandrescu and Petru Marginean published
c66cca2a 14 in December 2000 issue of C/C++ Users Journal.
822fc19e 15 http://www.cuj.com/documents/cujcexp1812alexandr/
c66cca2a
VZ
16 */
17
18#ifndef _WX_SCOPEGUARD_H_
19#define _WX_SCOPEGUARD_H_
20
21#include "wx/defs.h"
22
5800b5be
VZ
23#include "wx/except.h"
24
c66cca2a
VZ
25// ----------------------------------------------------------------------------
26// helpers
27// ----------------------------------------------------------------------------
28
822fc19e
WS
29#ifdef __WATCOMC__
30
31// WATCOM-FIXME: C++ of Open Watcom 1.3 doesn't like OnScopeExit() created
32// through template so it must be workarounded with dedicated inlined macro.
33// For compatibility with Watcom compilers wxPrivate::OnScopeExit must be
34// replaced with wxPrivateOnScopeExit but in user code (for everyone who
35// doesn't care about OW compatibility) wxPrivate::OnScopeExit still works.
36
37#define wxPrivateOnScopeExit(guard) \
38 { \
39 if ( !(guard).WasDismissed() ) \
40 { \
41 wxTRY \
42 { \
43 (guard).Execute(); \
44 } \
45 wxCATCH_ALL(;) \
46 } \
47 }
48
49#define wxPrivateUse(n) wxUnusedVar(n)
50
51#else
52
c66cca2a
VZ
53namespace wxPrivate
54{
55 // in the original implementation this was a member template function of
56 // ScopeGuardImplBase but gcc 2.8 which is still used for OS/2 doesn't
57 // support member templates and so we must make it global
17e22c50 58 template <class ScopeGuardImpl>
d775fa82 59 void OnScopeExit(ScopeGuardImpl& guard)
c66cca2a
VZ
60 {
61 if ( !guard.WasDismissed() )
62 {
63 // we're called from ScopeGuardImpl dtor and so we must not throw
5800b5be 64 wxTRY
c66cca2a
VZ
65 {
66 guard.Execute();
67 }
f0658b1e 68 wxCATCH_ALL(;) // do nothing, just eat the exception
c66cca2a
VZ
69 }
70 }
71
72 // just to avoid the warning about unused variables
17e22c50 73 template <class T>
c66cca2a
VZ
74 void Use(const T& WXUNUSED(t))
75 {
76 }
77} // namespace wxPrivate
d775fa82 78
822fc19e
WS
79#define wxPrivateOnScopeExit(n) wxPrivate::OnScopeExit(n)
80#define wxPrivateUse(n) wxPrivate::Use(n)
81
82#endif
83
c66cca2a
VZ
84// ============================================================================
85// wxScopeGuard for functions and functors
86// ============================================================================
87
88// ----------------------------------------------------------------------------
89// wxScopeGuardImplBase: used by wxScopeGuardImpl[0..N] below
90// ----------------------------------------------------------------------------
91
92class wxScopeGuardImplBase
93{
94public:
95 wxScopeGuardImplBase() : m_wasDismissed(false) { }
96
f7e81ed1
VZ
97 wxScopeGuardImplBase(const wxScopeGuardImplBase& other)
98 : m_wasDismissed(other.m_wasDismissed)
99 {
100 other.Dismiss();
101 }
102
c66cca2a
VZ
103 void Dismiss() const { m_wasDismissed = true; }
104
426a63a3 105 // for OnScopeExit() only (we can't make it friend, unfortunately)!
c66cca2a
VZ
106 bool WasDismissed() const { return m_wasDismissed; }
107
108protected:
109 ~wxScopeGuardImplBase() { }
110
c66cca2a
VZ
111 // must be mutable for copy ctor to work
112 mutable bool m_wasDismissed;
113
114private:
115 wxScopeGuardImplBase& operator=(const wxScopeGuardImplBase&);
116};
117
d2a48d5c
VZ
118// wxScopeGuard is just a reference, see the explanation in CUJ article
119typedef const wxScopeGuardImplBase& wxScopeGuard;
120
c66cca2a
VZ
121// ----------------------------------------------------------------------------
122// wxScopeGuardImpl0: scope guard for actions without parameters
123// ----------------------------------------------------------------------------
124
17e22c50 125template <class F>
c66cca2a
VZ
126class wxScopeGuardImpl0 : public wxScopeGuardImplBase
127{
128public:
129 static wxScopeGuardImpl0<F> MakeGuard(F fun)
130 {
131 return wxScopeGuardImpl0<F>(fun);
132 }
133
822fc19e 134 ~wxScopeGuardImpl0() { wxPrivateOnScopeExit(*this); }
c66cca2a
VZ
135
136 void Execute() { m_fun(); }
137
138protected:
139 wxScopeGuardImpl0(F fun) : m_fun(fun) { }
140
141 F m_fun;
142
143 wxScopeGuardImpl0& operator=(const wxScopeGuardImpl0&);
144};
145
17e22c50 146template <class F>
c66cca2a
VZ
147inline wxScopeGuardImpl0<F> wxMakeGuard(F fun)
148{
149 return wxScopeGuardImpl0<F>::MakeGuard(fun);
150}
151
152// ----------------------------------------------------------------------------
153// wxScopeGuardImpl1: scope guard for actions with 1 parameter
154// ----------------------------------------------------------------------------
155
17e22c50 156template <class F, class P1>
c66cca2a
VZ
157class wxScopeGuardImpl1 : public wxScopeGuardImplBase
158{
159public:
160 static wxScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
161 {
162 return wxScopeGuardImpl1<F, P1>(fun, p1);
163 }
164
822fc19e 165 ~wxScopeGuardImpl1() { wxPrivateOnScopeExit(* this); }
c66cca2a
VZ
166
167 void Execute() { m_fun(m_p1); }
168
169protected:
170 wxScopeGuardImpl1(F fun, P1 p1) : m_fun(fun), m_p1(p1) { }
171
172 F m_fun;
173 const P1 m_p1;
174
175 wxScopeGuardImpl1& operator=(const wxScopeGuardImpl1&);
176};
177
17e22c50 178template <class F, class P1>
c66cca2a
VZ
179inline wxScopeGuardImpl1<F, P1> wxMakeGuard(F fun, P1 p1)
180{
181 return wxScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
182}
183
184// ----------------------------------------------------------------------------
185// wxScopeGuardImpl2: scope guard for actions with 2 parameters
186// ----------------------------------------------------------------------------
187
17e22c50 188template <class F, class P1, class P2>
c66cca2a
VZ
189class wxScopeGuardImpl2 : public wxScopeGuardImplBase
190{
191public:
192 static wxScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
193 {
194 return wxScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
195 }
196
822fc19e 197 ~wxScopeGuardImpl2() { wxPrivateOnScopeExit(*this); }
c66cca2a
VZ
198
199 void Execute() { m_fun(m_p1, m_p2); }
200
201protected:
202 wxScopeGuardImpl2(F fun, P1 p1, P2 p2) : m_fun(fun), m_p1(p1), m_p2(p2) { }
203
204 F m_fun;
205 const P1 m_p1;
206 const P2 m_p2;
207
208 wxScopeGuardImpl2& operator=(const wxScopeGuardImpl2&);
209};
210
17e22c50 211template <class F, class P1, class P2>
c66cca2a
VZ
212inline wxScopeGuardImpl2<F, P1, P2> wxMakeGuard(F fun, P1 p1, P2 p2)
213{
214 return wxScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
215}
216
bcffb4d1
VZ
217// ----------------------------------------------------------------------------
218// wxScopeGuardImpl3: scope guard for actions with 3 parameters
219// ----------------------------------------------------------------------------
220
221template <class F, class P1, class P2, class P3>
222class wxScopeGuardImpl3 : public wxScopeGuardImplBase
223{
224public:
225 static wxScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
226 {
227 return wxScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
228 }
229
230 ~wxScopeGuardImpl3() { wxPrivateOnScopeExit(*this); }
231
232 void Execute() { m_fun(m_p1, m_p2, m_p3); }
233
234protected:
235 wxScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3)
236 : m_fun(fun), m_p1(p1), m_p2(p2), m_p3(p3) { }
237
238 F m_fun;
239 const P1 m_p1;
240 const P2 m_p2;
241 const P3 m_p3;
242
243 wxScopeGuardImpl3& operator=(const wxScopeGuardImpl3&);
244};
245
246template <class F, class P1, class P2, class P3>
247inline wxScopeGuardImpl3<F, P1, P2, P3> wxMakeGuard(F fun, P1 p1, P2 p2, P3 p3)
248{
249 return wxScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3);
250}
251
c66cca2a
VZ
252// ============================================================================
253// wxScopeGuards for object methods
254// ============================================================================
255
256// ----------------------------------------------------------------------------
257// wxObjScopeGuardImpl0
258// ----------------------------------------------------------------------------
259
17e22c50 260template <class Obj, class MemFun>
c66cca2a
VZ
261class wxObjScopeGuardImpl0 : public wxScopeGuardImplBase
262{
263public:
264 static wxObjScopeGuardImpl0<Obj, MemFun>
265 MakeObjGuard(Obj& obj, MemFun memFun)
266 {
267 return wxObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
268 }
269
822fc19e 270 ~wxObjScopeGuardImpl0() { wxPrivateOnScopeExit(*this); }
c66cca2a
VZ
271
272 void Execute() { (m_obj.*m_memfun)(); }
273
274protected:
275 wxObjScopeGuardImpl0(Obj& obj, MemFun memFun)
276 : m_obj(obj), m_memfun(memFun) { }
277
278 Obj& m_obj;
279 MemFun m_memfun;
280};
281
17e22c50 282template <class Obj, class MemFun>
c66cca2a
VZ
283inline wxObjScopeGuardImpl0<Obj, MemFun> wxMakeObjGuard(Obj& obj, MemFun memFun)
284{
285 return wxObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
286}
287
17e22c50 288template <class Obj, class MemFun, class P1>
c66cca2a
VZ
289class wxObjScopeGuardImpl1 : public wxScopeGuardImplBase
290{
291public:
292 static wxObjScopeGuardImpl1<Obj, MemFun, P1>
293 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
294 {
295 return wxObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
296 }
297
822fc19e 298 ~wxObjScopeGuardImpl1() { wxPrivateOnScopeExit(*this); }
c66cca2a
VZ
299
300 void Execute() { (m_obj.*m_memfun)(m_p1); }
301
302protected:
d775fa82 303 wxObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1)
c66cca2a
VZ
304 : m_obj(obj), m_memfun(memFun), m_p1(p1) { }
305
306 Obj& m_obj;
307 MemFun m_memfun;
308 const P1 m_p1;
309};
310
17e22c50 311template <class Obj, class MemFun, class P1>
c66cca2a
VZ
312inline wxObjScopeGuardImpl1<Obj, MemFun, P1>
313wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
314{
315 return wxObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
316}
317
17e22c50 318template <class Obj, class MemFun, class P1, class P2>
c66cca2a
VZ
319class wxObjScopeGuardImpl2 : public wxScopeGuardImplBase
320{
321public:
322 static wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>
323 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
324 {
325 return wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
326 }
327
822fc19e 328 ~wxObjScopeGuardImpl2() { wxPrivateOnScopeExit(*this); }
c66cca2a
VZ
329
330 void Execute() { (m_obj.*m_memfun)(m_p1, m_p2); }
331
332protected:
d775fa82 333 wxObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2)
c66cca2a
VZ
334 : m_obj(obj), m_memfun(memFun), m_p1(p1), m_p2(p2) { }
335
336 Obj& m_obj;
337 MemFun m_memfun;
338 const P1 m_p1;
339 const P2 m_p2;
340};
341
17e22c50 342template <class Obj, class MemFun, class P1, class P2>
c66cca2a
VZ
343inline wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>
344wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
345{
346 return wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>::
347 MakeObjGuard(obj, memFun, p1, p2);
348}
349
bcffb4d1
VZ
350template <class Obj, class MemFun, class P1, class P2, class P3>
351class wxObjScopeGuardImpl3 : public wxScopeGuardImplBase
352{
353public:
354 static wxObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3>
355 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2, P3 p3)
356 {
22c5cac6 357 return wxObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3>(obj, memFun, p1, p2, p3);
bcffb4d1
VZ
358 }
359
360 ~wxObjScopeGuardImpl3() { wxPrivateOnScopeExit(*this); }
361
362 void Execute() { (m_obj.*m_memfun)(m_p1, m_p2, m_p3); }
363
364protected:
365 wxObjScopeGuardImpl3(Obj& obj, MemFun memFun, P1 p1, P2 p2, P3 p3)
366 : m_obj(obj), m_memfun(memFun), m_p1(p1), m_p2(p2), m_p3(p3) { }
367
368 Obj& m_obj;
369 MemFun m_memfun;
370 const P1 m_p1;
371 const P2 m_p2;
372 const P3 m_p3;
373};
374
375template <class Obj, class MemFun, class P1, class P2, class P3>
376inline wxObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3>
377wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2, P3 p3)
378{
379 return wxObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3>::
380 MakeObjGuard(obj, memFun, p1, p2, p3);
381}
382
d2a48d5c
VZ
383// ----------------------------------------------------------------------------
384// wxVariableSetter: use the same technique as for wxScopeGuard to allow
385// setting a variable to some value on block exit
386// ----------------------------------------------------------------------------
387
d2a48d5c
VZ
388namespace wxPrivate
389{
390
391// empty class just to be able to define a reference to it
aef081f4 392class VariableSetterBase : public wxScopeGuardImplBase { };
d2a48d5c
VZ
393
394typedef const VariableSetterBase& VariableSetter;
395
396template <typename T, typename U>
397class VariableSetterImpl : public VariableSetterBase
398{
399public:
e196e523 400 VariableSetterImpl(T& var, U value)
d2a48d5c
VZ
401 : m_var(var),
402 m_value(value)
403 {
404 }
405
aef081f4
VS
406 ~VariableSetterImpl() { wxPrivateOnScopeExit(*this); }
407
408 void Execute() { m_var = m_value; }
d2a48d5c
VZ
409
410private:
411 T& m_var;
e196e523 412 const U m_value;
d2a48d5c
VZ
413
414 // suppress the warning about assignment operator not being generated
415 VariableSetterImpl<T, U>& operator=(const VariableSetterImpl<T, U>&);
416};
417
418template <typename T>
419class VariableNullerImpl : public VariableSetterBase
420{
421public:
422 VariableNullerImpl(T& var)
423 : m_var(var)
424 {
425 }
426
aef081f4
VS
427 ~VariableNullerImpl() { wxPrivateOnScopeExit(*this); }
428
429 void Execute() { m_var = NULL; }
d2a48d5c
VZ
430
431private:
432 T& m_var;
433
434 VariableNullerImpl<T>& operator=(const VariableNullerImpl<T>&);
435};
436
437} // namespace wxPrivate
438
439template <typename T, typename U>
440inline
e196e523 441wxPrivate::VariableSetterImpl<T, U> wxMakeVarSetter(T& var, U value)
d2a48d5c
VZ
442{
443 return wxPrivate::VariableSetterImpl<T, U>(var, value);
444}
445
446// calling wxMakeVarSetter(ptr, NULL) doesn't work because U is deduced to be
447// "int" and subsequent assignment of "U" to "T *" fails, so provide a special
448// function for this special case
449template <typename T>
450inline
451wxPrivate::VariableNullerImpl<T> wxMakeVarNuller(T& var)
452{
453 return wxPrivate::VariableNullerImpl<T>(var);
454}
455
c66cca2a 456// ============================================================================
d2a48d5c 457// macros for declaring unnamed scoped guards (which can't be dismissed)
c66cca2a
VZ
458// ============================================================================
459
c66cca2a
VZ
460// NB: the original code has a single (and much nicer) ON_BLOCK_EXIT macro
461// but this results in compiler warnings about unused variables and I
462// didn't find a way to work around this other than by having different
d2a48d5c
VZ
463// macros with different names or using a less natural syntax for passing
464// the arguments (e.g. as Boost preprocessor sequences, which would mean
465// having to write wxON_BLOCK_EXIT(fwrite, (buf)(size)(n)(fp)) instead of
466// wxON_BLOCK_EXIT4(fwrite, buf, size, n, fp)).
426a63a3 467
d2a48d5c 468#define wxGuardName wxMAKE_UNIQUE_NAME(wxScopeGuard)
426a63a3
VZ
469
470#define wxON_BLOCK_EXIT0_IMPL(n, f) \
471 wxScopeGuard n = wxMakeGuard(f); \
822fc19e 472 wxPrivateUse(n)
5800b5be 473#define wxON_BLOCK_EXIT0(f) \
426a63a3 474 wxON_BLOCK_EXIT0_IMPL(wxGuardName, f)
c66cca2a 475
426a63a3
VZ
476#define wxON_BLOCK_EXIT_OBJ0_IMPL(n, o, m) \
477 wxScopeGuard n = wxMakeObjGuard(o, m); \
822fc19e 478 wxPrivateUse(n)
5800b5be 479#define wxON_BLOCK_EXIT_OBJ0(o, m) \
2bb3c0c0 480 wxON_BLOCK_EXIT_OBJ0_IMPL(wxGuardName, o, &m)
c66cca2a 481
51c679d5
VZ
482#define wxON_BLOCK_EXIT_THIS0(m) \
483 wxON_BLOCK_EXIT_OBJ0(*this, m)
484
485
426a63a3
VZ
486#define wxON_BLOCK_EXIT1_IMPL(n, f, p1) \
487 wxScopeGuard n = wxMakeGuard(f, p1); \
822fc19e 488 wxPrivateUse(n)
5800b5be 489#define wxON_BLOCK_EXIT1(f, p1) \
426a63a3 490 wxON_BLOCK_EXIT1_IMPL(wxGuardName, f, p1)
c66cca2a 491
426a63a3
VZ
492#define wxON_BLOCK_EXIT_OBJ1_IMPL(n, o, m, p1) \
493 wxScopeGuard n = wxMakeObjGuard(o, m, p1); \
822fc19e 494 wxPrivateUse(n)
5800b5be 495#define wxON_BLOCK_EXIT_OBJ1(o, m, p1) \
2bb3c0c0 496 wxON_BLOCK_EXIT_OBJ1_IMPL(wxGuardName, o, &m, p1)
c66cca2a 497
51c679d5
VZ
498#define wxON_BLOCK_EXIT_THIS1(m, p1) \
499 wxON_BLOCK_EXIT_OBJ1(*this, m, p1)
500
501
426a63a3
VZ
502#define wxON_BLOCK_EXIT2_IMPL(n, f, p1, p2) \
503 wxScopeGuard n = wxMakeGuard(f, p1, p2); \
822fc19e 504 wxPrivateUse(n)
5800b5be 505#define wxON_BLOCK_EXIT2(f, p1, p2) \
426a63a3 506 wxON_BLOCK_EXIT2_IMPL(wxGuardName, f, p1, p2)
c66cca2a 507
426a63a3
VZ
508#define wxON_BLOCK_EXIT_OBJ2_IMPL(n, o, m, p1, p2) \
509 wxScopeGuard n = wxMakeObjGuard(o, m, p1, p2); \
822fc19e 510 wxPrivateUse(n)
5800b5be 511#define wxON_BLOCK_EXIT_OBJ2(o, m, p1, p2) \
2bb3c0c0 512 wxON_BLOCK_EXIT_OBJ2_IMPL(wxGuardName, o, &m, p1, p2)
c66cca2a 513
51c679d5
VZ
514#define wxON_BLOCK_EXIT_THIS2(m, p1, p2) \
515 wxON_BLOCK_EXIT_OBJ2(*this, m, p1, p2)
516
d2a48d5c 517
bcffb4d1
VZ
518#define wxON_BLOCK_EXIT3_IMPL(n, f, p1, p2, p3) \
519 wxScopeGuard n = wxMakeGuard(f, p1, p2, p3); \
520 wxPrivateUse(n)
521#define wxON_BLOCK_EXIT3(f, p1, p2, p3) \
522 wxON_BLOCK_EXIT3_IMPL(wxGuardName, f, p1, p2, p3)
523
524#define wxON_BLOCK_EXIT_OBJ3_IMPL(n, o, m, p1, p2, p3) \
525 wxScopeGuard n = wxMakeObjGuard(o, m, p1, p2, p3); \
526 wxPrivateUse(n)
527#define wxON_BLOCK_EXIT_OBJ3(o, m, p1, p2, p3) \
528 wxON_BLOCK_EXIT_OBJ3_IMPL(wxGuardName, o, &m, p1, p2, p3)
529
530#define wxON_BLOCK_EXIT_THIS3(m, p1, p2, p3) \
531 wxON_BLOCK_EXIT_OBJ3(*this, m, p1, p2, p3)
532
533
d2a48d5c
VZ
534#define wxSetterName wxMAKE_UNIQUE_NAME(wxVarSetter)
535
536#define wxON_BLOCK_EXIT_SET_IMPL(n, var, value) \
537 wxPrivate::VariableSetter n = wxMakeVarSetter(var, value); \
538 wxPrivateUse(n)
539
540#define wxON_BLOCK_EXIT_SET(var, value) \
541 wxON_BLOCK_EXIT_SET_IMPL(wxSetterName, var, value)
542
543#define wxON_BLOCK_EXIT_NULL_IMPL(n, var) \
544 wxPrivate::VariableSetter n = wxMakeVarNuller(var); \
545 wxPrivateUse(n)
546
547#define wxON_BLOCK_EXIT_NULL(ptr) \
548 wxON_BLOCK_EXIT_NULL_IMPL(wxSetterName, ptr)
549
c66cca2a 550#endif // _WX_SCOPEGUARD_H_