]> git.saurik.com Git - wxWidgets.git/blob - include/wx/scopeguard.h
Comment-only update
[wxWidgets.git] / include / wx / scopeguard.h
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 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 /*
12 Acknowledgements: this header is heavily based on (well, almost the exact
13 copy of) ScopeGuard.h by Andrei Alexandrescu and Petru Marginean published
14 in December 2000 issue of C/C++ Users Journal.
15 http://www.cuj.com/documents/cujcexp1812alexandr/
16 */
17
18 #ifndef _WX_SCOPEGUARD_H_
19 #define _WX_SCOPEGUARD_H_
20
21 #include "wx/defs.h"
22
23 #include "wx/except.h"
24
25 // ----------------------------------------------------------------------------
26 // helpers
27 // ----------------------------------------------------------------------------
28
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
53 namespace 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
58 template <class ScopeGuardImpl>
59 void OnScopeExit(ScopeGuardImpl& guard)
60 {
61 if ( !guard.WasDismissed() )
62 {
63 // we're called from ScopeGuardImpl dtor and so we must not throw
64 wxTRY
65 {
66 guard.Execute();
67 }
68 wxCATCH_ALL(;) // do nothing, just eat the exception
69 }
70 }
71
72 // just to avoid the warning about unused variables
73 template <class T>
74 void Use(const T& WXUNUSED(t))
75 {
76 }
77 } // namespace wxPrivate
78
79 #define wxPrivateOnScopeExit(n) wxPrivate::OnScopeExit(n)
80 #define wxPrivateUse(n) wxPrivate::Use(n)
81
82 #endif
83
84 // ============================================================================
85 // wxScopeGuard for functions and functors
86 // ============================================================================
87
88 // ----------------------------------------------------------------------------
89 // wxScopeGuardImplBase: used by wxScopeGuardImpl[0..N] below
90 // ----------------------------------------------------------------------------
91
92 class wxScopeGuardImplBase
93 {
94 public:
95 wxScopeGuardImplBase() : m_wasDismissed(false) { }
96
97 wxScopeGuardImplBase(const wxScopeGuardImplBase& other)
98 : m_wasDismissed(other.m_wasDismissed)
99 {
100 other.Dismiss();
101 }
102
103 void Dismiss() const { m_wasDismissed = true; }
104
105 // for OnScopeExit() only (we can't make it friend, unfortunately)!
106 bool WasDismissed() const { return m_wasDismissed; }
107
108 protected:
109 ~wxScopeGuardImplBase() { }
110
111 // must be mutable for copy ctor to work
112 mutable bool m_wasDismissed;
113
114 private:
115 wxScopeGuardImplBase& operator=(const wxScopeGuardImplBase&);
116 };
117
118 // wxScopeGuard is just a reference, see the explanation in CUJ article
119 typedef const wxScopeGuardImplBase& wxScopeGuard;
120
121 // ----------------------------------------------------------------------------
122 // wxScopeGuardImpl0: scope guard for actions without parameters
123 // ----------------------------------------------------------------------------
124
125 template <class F>
126 class wxScopeGuardImpl0 : public wxScopeGuardImplBase
127 {
128 public:
129 static wxScopeGuardImpl0<F> MakeGuard(F fun)
130 {
131 return wxScopeGuardImpl0<F>(fun);
132 }
133
134 ~wxScopeGuardImpl0() { wxPrivateOnScopeExit(*this); }
135
136 void Execute() { m_fun(); }
137
138 protected:
139 wxScopeGuardImpl0(F fun) : m_fun(fun) { }
140
141 F m_fun;
142
143 wxScopeGuardImpl0& operator=(const wxScopeGuardImpl0&);
144 };
145
146 template <class F>
147 inline 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
156 template <class F, class P1>
157 class wxScopeGuardImpl1 : public wxScopeGuardImplBase
158 {
159 public:
160 static wxScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
161 {
162 return wxScopeGuardImpl1<F, P1>(fun, p1);
163 }
164
165 ~wxScopeGuardImpl1() { wxPrivateOnScopeExit(* this); }
166
167 void Execute() { m_fun(m_p1); }
168
169 protected:
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
178 template <class F, class P1>
179 inline 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
188 template <class F, class P1, class P2>
189 class wxScopeGuardImpl2 : public wxScopeGuardImplBase
190 {
191 public:
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
197 ~wxScopeGuardImpl2() { wxPrivateOnScopeExit(*this); }
198
199 void Execute() { m_fun(m_p1, m_p2); }
200
201 protected:
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
211 template <class F, class P1, class P2>
212 inline wxScopeGuardImpl2<F, P1, P2> wxMakeGuard(F fun, P1 p1, P2 p2)
213 {
214 return wxScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
215 }
216
217 // ----------------------------------------------------------------------------
218 // wxScopeGuardImpl3: scope guard for actions with 3 parameters
219 // ----------------------------------------------------------------------------
220
221 template <class F, class P1, class P2, class P3>
222 class wxScopeGuardImpl3 : public wxScopeGuardImplBase
223 {
224 public:
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
234 protected:
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
246 template <class F, class P1, class P2, class P3>
247 inline 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
252 // ============================================================================
253 // wxScopeGuards for object methods
254 // ============================================================================
255
256 // ----------------------------------------------------------------------------
257 // wxObjScopeGuardImpl0
258 // ----------------------------------------------------------------------------
259
260 template <class Obj, class MemFun>
261 class wxObjScopeGuardImpl0 : public wxScopeGuardImplBase
262 {
263 public:
264 static wxObjScopeGuardImpl0<Obj, MemFun>
265 MakeObjGuard(Obj& obj, MemFun memFun)
266 {
267 return wxObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
268 }
269
270 ~wxObjScopeGuardImpl0() { wxPrivateOnScopeExit(*this); }
271
272 void Execute() { (m_obj.*m_memfun)(); }
273
274 protected:
275 wxObjScopeGuardImpl0(Obj& obj, MemFun memFun)
276 : m_obj(obj), m_memfun(memFun) { }
277
278 Obj& m_obj;
279 MemFun m_memfun;
280 };
281
282 template <class Obj, class MemFun>
283 inline wxObjScopeGuardImpl0<Obj, MemFun> wxMakeObjGuard(Obj& obj, MemFun memFun)
284 {
285 return wxObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
286 }
287
288 template <class Obj, class MemFun, class P1>
289 class wxObjScopeGuardImpl1 : public wxScopeGuardImplBase
290 {
291 public:
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
298 ~wxObjScopeGuardImpl1() { wxPrivateOnScopeExit(*this); }
299
300 void Execute() { (m_obj.*m_memfun)(m_p1); }
301
302 protected:
303 wxObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1)
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
311 template <class Obj, class MemFun, class P1>
312 inline wxObjScopeGuardImpl1<Obj, MemFun, P1>
313 wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
314 {
315 return wxObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
316 }
317
318 template <class Obj, class MemFun, class P1, class P2>
319 class wxObjScopeGuardImpl2 : public wxScopeGuardImplBase
320 {
321 public:
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
328 ~wxObjScopeGuardImpl2() { wxPrivateOnScopeExit(*this); }
329
330 void Execute() { (m_obj.*m_memfun)(m_p1, m_p2); }
331
332 protected:
333 wxObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2)
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
342 template <class Obj, class MemFun, class P1, class P2>
343 inline wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>
344 wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
345 {
346 return wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>::
347 MakeObjGuard(obj, memFun, p1, p2);
348 }
349
350 template <class Obj, class MemFun, class P1, class P2, class P3>
351 class wxObjScopeGuardImpl3 : public wxScopeGuardImplBase
352 {
353 public:
354 static wxObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3>
355 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2, P3 p3)
356 {
357 return wxObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3>(obj, memFun, p1, p2, p3);
358 }
359
360 ~wxObjScopeGuardImpl3() { wxPrivateOnScopeExit(*this); }
361
362 void Execute() { (m_obj.*m_memfun)(m_p1, m_p2, m_p3); }
363
364 protected:
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
375 template <class Obj, class MemFun, class P1, class P2, class P3>
376 inline wxObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3>
377 wxMakeObjGuard(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
383 // ----------------------------------------------------------------------------
384 // wxVariableSetter: use the same technique as for wxScopeGuard to allow
385 // setting a variable to some value on block exit
386 // ----------------------------------------------------------------------------
387
388 namespace wxPrivate
389 {
390
391 // empty class just to be able to define a reference to it
392 class VariableSetterBase : public wxScopeGuardImplBase { };
393
394 typedef const VariableSetterBase& VariableSetter;
395
396 template <typename T, typename U>
397 class VariableSetterImpl : public VariableSetterBase
398 {
399 public:
400 VariableSetterImpl(T& var, U value)
401 : m_var(var),
402 m_value(value)
403 {
404 }
405
406 ~VariableSetterImpl() { wxPrivateOnScopeExit(*this); }
407
408 void Execute() { m_var = m_value; }
409
410 private:
411 T& m_var;
412 const U m_value;
413
414 // suppress the warning about assignment operator not being generated
415 VariableSetterImpl<T, U>& operator=(const VariableSetterImpl<T, U>&);
416 };
417
418 template <typename T>
419 class VariableNullerImpl : public VariableSetterBase
420 {
421 public:
422 VariableNullerImpl(T& var)
423 : m_var(var)
424 {
425 }
426
427 ~VariableNullerImpl() { wxPrivateOnScopeExit(*this); }
428
429 void Execute() { m_var = NULL; }
430
431 private:
432 T& m_var;
433
434 VariableNullerImpl<T>& operator=(const VariableNullerImpl<T>&);
435 };
436
437 } // namespace wxPrivate
438
439 template <typename T, typename U>
440 inline
441 wxPrivate::VariableSetterImpl<T, U> wxMakeVarSetter(T& var, U value)
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
449 template <typename T>
450 inline
451 wxPrivate::VariableNullerImpl<T> wxMakeVarNuller(T& var)
452 {
453 return wxPrivate::VariableNullerImpl<T>(var);
454 }
455
456 // ============================================================================
457 // macros for declaring unnamed scoped guards (which can't be dismissed)
458 // ============================================================================
459
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
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)).
467
468 #define wxGuardName wxMAKE_UNIQUE_NAME(wxScopeGuard)
469
470 #define wxON_BLOCK_EXIT0_IMPL(n, f) \
471 wxScopeGuard n = wxMakeGuard(f); \
472 wxPrivateUse(n)
473 #define wxON_BLOCK_EXIT0(f) \
474 wxON_BLOCK_EXIT0_IMPL(wxGuardName, f)
475
476 #define wxON_BLOCK_EXIT_OBJ0_IMPL(n, o, m) \
477 wxScopeGuard n = wxMakeObjGuard(o, m); \
478 wxPrivateUse(n)
479 #define wxON_BLOCK_EXIT_OBJ0(o, m) \
480 wxON_BLOCK_EXIT_OBJ0_IMPL(wxGuardName, o, &m)
481
482 #define wxON_BLOCK_EXIT_THIS0(m) \
483 wxON_BLOCK_EXIT_OBJ0(*this, m)
484
485
486 #define wxON_BLOCK_EXIT1_IMPL(n, f, p1) \
487 wxScopeGuard n = wxMakeGuard(f, p1); \
488 wxPrivateUse(n)
489 #define wxON_BLOCK_EXIT1(f, p1) \
490 wxON_BLOCK_EXIT1_IMPL(wxGuardName, f, p1)
491
492 #define wxON_BLOCK_EXIT_OBJ1_IMPL(n, o, m, p1) \
493 wxScopeGuard n = wxMakeObjGuard(o, m, p1); \
494 wxPrivateUse(n)
495 #define wxON_BLOCK_EXIT_OBJ1(o, m, p1) \
496 wxON_BLOCK_EXIT_OBJ1_IMPL(wxGuardName, o, &m, p1)
497
498 #define wxON_BLOCK_EXIT_THIS1(m, p1) \
499 wxON_BLOCK_EXIT_OBJ1(*this, m, p1)
500
501
502 #define wxON_BLOCK_EXIT2_IMPL(n, f, p1, p2) \
503 wxScopeGuard n = wxMakeGuard(f, p1, p2); \
504 wxPrivateUse(n)
505 #define wxON_BLOCK_EXIT2(f, p1, p2) \
506 wxON_BLOCK_EXIT2_IMPL(wxGuardName, f, p1, p2)
507
508 #define wxON_BLOCK_EXIT_OBJ2_IMPL(n, o, m, p1, p2) \
509 wxScopeGuard n = wxMakeObjGuard(o, m, p1, p2); \
510 wxPrivateUse(n)
511 #define wxON_BLOCK_EXIT_OBJ2(o, m, p1, p2) \
512 wxON_BLOCK_EXIT_OBJ2_IMPL(wxGuardName, o, &m, p1, p2)
513
514 #define wxON_BLOCK_EXIT_THIS2(m, p1, p2) \
515 wxON_BLOCK_EXIT_OBJ2(*this, m, p1, p2)
516
517
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
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
550 #endif // _WX_SCOPEGUARD_H_