]> git.saurik.com Git - wxWidgets.git/blame_incremental - include/wx/scopeguard.h
As small as possible reorganization within wxDateTime to please PCH in DLL build...
[wxWidgets.git] / include / wx / scopeguard.h
... / ...
CommitLineData
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$
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) wxScopeGuard.h by Andrei Alexandrescu and Petru Marginean published
15 in December 2000 issue of C/C++ Users Journal.
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
29namespace wxPrivate
30{
31 // in the original implementation this was a member template function of
32 // ScopeGuardImplBase but gcc 2.8 which is still used for OS/2 doesn't
33 // support member templates and so we must make it global
34 template <typename ScopeGuardImpl>
35 void OnScopeExit(ScopeGuardImpl& guard)
36 {
37 if ( !guard.WasDismissed() )
38 {
39 // we're called from ScopeGuardImpl dtor and so we must not throw
40 wxTRY
41 {
42 guard.Execute();
43 }
44 wxCATCH_ALL(;) // do nothing, just eat the exception
45 }
46 }
47
48 // just to avoid the warning about unused variables
49 template <typename T>
50 void Use(const T& WXUNUSED(t))
51 {
52 }
53} // namespace wxPrivate
54
55// ============================================================================
56// wxScopeGuard for functions and functors
57// ============================================================================
58
59// ----------------------------------------------------------------------------
60// wxScopeGuardImplBase: used by wxScopeGuardImpl[0..N] below
61// ----------------------------------------------------------------------------
62
63class wxScopeGuardImplBase
64{
65public:
66 wxScopeGuardImplBase() : m_wasDismissed(false) { }
67
68 void Dismiss() const { m_wasDismissed = true; }
69
70 // for OnScopeExit() only we can't make it friend, unfortunately)!
71 bool WasDismissed() const { return m_wasDismissed; }
72
73protected:
74 ~wxScopeGuardImplBase() { }
75
76 wxScopeGuardImplBase(const wxScopeGuardImplBase& other)
77 : m_wasDismissed(other.m_wasDismissed)
78 {
79 other.Dismiss();
80 }
81
82 // must be mutable for copy ctor to work
83 mutable bool m_wasDismissed;
84
85private:
86 wxScopeGuardImplBase& operator=(const wxScopeGuardImplBase&);
87};
88
89// ----------------------------------------------------------------------------
90// wxScopeGuardImpl0: scope guard for actions without parameters
91// ----------------------------------------------------------------------------
92
93template <typename F>
94class wxScopeGuardImpl0 : public wxScopeGuardImplBase
95{
96public:
97 static wxScopeGuardImpl0<F> MakeGuard(F fun)
98 {
99 return wxScopeGuardImpl0<F>(fun);
100 }
101
102 ~wxScopeGuardImpl0() { wxPrivate::OnScopeExit(*this); }
103
104 void Execute() { m_fun(); }
105
106protected:
107 wxScopeGuardImpl0(F fun) : m_fun(fun) { }
108
109 F m_fun;
110
111 wxScopeGuardImpl0& operator=(const wxScopeGuardImpl0&);
112};
113
114template <typename F>
115inline wxScopeGuardImpl0<F> wxMakeGuard(F fun)
116{
117 return wxScopeGuardImpl0<F>::MakeGuard(fun);
118}
119
120// ----------------------------------------------------------------------------
121// wxScopeGuardImpl1: scope guard for actions with 1 parameter
122// ----------------------------------------------------------------------------
123
124template <typename F, typename P1>
125class wxScopeGuardImpl1 : public wxScopeGuardImplBase
126{
127public:
128 static wxScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
129 {
130 return wxScopeGuardImpl1<F, P1>(fun, p1);
131 }
132
133 ~wxScopeGuardImpl1() { wxPrivate::OnScopeExit(*this); }
134
135 void Execute() { m_fun(m_p1); }
136
137protected:
138 wxScopeGuardImpl1(F fun, P1 p1) : m_fun(fun), m_p1(p1) { }
139
140 F m_fun;
141 const P1 m_p1;
142
143 wxScopeGuardImpl1& operator=(const wxScopeGuardImpl1&);
144};
145
146template <typename F, typename P1>
147inline wxScopeGuardImpl1<F, P1> wxMakeGuard(F fun, P1 p1)
148{
149 return wxScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
150}
151
152// ----------------------------------------------------------------------------
153// wxScopeGuardImpl2: scope guard for actions with 2 parameters
154// ----------------------------------------------------------------------------
155
156template <typename F, typename P1, typename P2>
157class wxScopeGuardImpl2 : public wxScopeGuardImplBase
158{
159public:
160 static wxScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
161 {
162 return wxScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
163 }
164
165 ~wxScopeGuardImpl2() { wxPrivate::OnScopeExit(*this); }
166
167 void Execute() { m_fun(m_p1, m_p2); }
168
169protected:
170 wxScopeGuardImpl2(F fun, P1 p1, P2 p2) : m_fun(fun), m_p1(p1), m_p2(p2) { }
171
172 F m_fun;
173 const P1 m_p1;
174 const P2 m_p2;
175
176 wxScopeGuardImpl2& operator=(const wxScopeGuardImpl2&);
177};
178
179template <typename F, typename P1, typename P2>
180inline wxScopeGuardImpl2<F, P1, P2> wxMakeGuard(F fun, P1 p1, P2 p2)
181{
182 return wxScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
183}
184
185// ============================================================================
186// wxScopeGuards for object methods
187// ============================================================================
188
189// ----------------------------------------------------------------------------
190// wxObjScopeGuardImpl0
191// ----------------------------------------------------------------------------
192
193template <class Obj, typename MemFun>
194class wxObjScopeGuardImpl0 : public wxScopeGuardImplBase
195{
196public:
197 static wxObjScopeGuardImpl0<Obj, MemFun>
198 MakeObjGuard(Obj& obj, MemFun memFun)
199 {
200 return wxObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
201 }
202
203 ~wxObjScopeGuardImpl0() { wxPrivate::OnScopeExit(*this); }
204
205 void Execute() { (m_obj.*m_memfun)(); }
206
207protected:
208 wxObjScopeGuardImpl0(Obj& obj, MemFun memFun)
209 : m_obj(obj), m_memfun(memFun) { }
210
211 Obj& m_obj;
212 MemFun m_memfun;
213};
214
215template <class Obj, typename MemFun>
216inline wxObjScopeGuardImpl0<Obj, MemFun> wxMakeObjGuard(Obj& obj, MemFun memFun)
217{
218 return wxObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
219}
220
221template <class Obj, typename MemFun, typename P1>
222class wxObjScopeGuardImpl1 : public wxScopeGuardImplBase
223{
224public:
225 static wxObjScopeGuardImpl1<Obj, MemFun, P1>
226 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
227 {
228 return wxObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
229 }
230
231 ~wxObjScopeGuardImpl1() { wxPrivate::OnScopeExit(*this); }
232
233 void Execute() { (m_obj.*m_memfun)(m_p1); }
234
235protected:
236 wxObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1)
237 : m_obj(obj), m_memfun(memFun), m_p1(p1) { }
238
239 Obj& m_obj;
240 MemFun m_memfun;
241 const P1 m_p1;
242};
243
244template <class Obj, typename MemFun, typename P1>
245inline wxObjScopeGuardImpl1<Obj, MemFun, P1>
246wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
247{
248 return wxObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
249}
250
251template <class Obj, typename MemFun, typename P1, typename P2>
252class wxObjScopeGuardImpl2 : public wxScopeGuardImplBase
253{
254public:
255 static wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>
256 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
257 {
258 return wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
259 }
260
261 ~wxObjScopeGuardImpl2() { wxPrivate::OnScopeExit(*this); }
262
263 void Execute() { (m_obj.*m_memfun)(m_p1, m_p2); }
264
265protected:
266 wxObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2)
267 : m_obj(obj), m_memfun(memFun), m_p1(p1), m_p2(p2) { }
268
269 Obj& m_obj;
270 MemFun m_memfun;
271 const P1 m_p1;
272 const P2 m_p2;
273};
274
275template <class Obj, typename MemFun, typename P1, typename P2>
276inline wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>
277wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
278{
279 return wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>::
280 MakeObjGuard(obj, memFun, p1, p2);
281}
282
283// ============================================================================
284// public stuff
285// ============================================================================
286
287// wxScopeGuard is just a reference, see the explanation in CUJ article
288typedef const wxScopeGuardImplBase& wxScopeGuard;
289
290// when an unnamed scope guard is needed, the macros below may be used
291//
292// NB: the original code has a single (and much nicer) ON_BLOCK_EXIT macro
293// but this results in compiler warnings about unused variables and I
294// didn't find a way to work around this other than by having different
295// macros with different names
296#define wxON_BLOCK_EXIT0(f) \
297 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeGuard(f); \
298 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
299
300#define wxON_BLOCK_EXIT_OBJ0(o, m) \
301 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeObjGuard(o, m); \
302 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
303
304#define wxON_BLOCK_EXIT1(f, p1) \
305 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeGuard(f, p1); \
306 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
307
308#define wxON_BLOCK_EXIT_OBJ1(o, m, p1) \
309 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeObjGuard(o, m, p1); \
310 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
311
312#define wxON_BLOCK_EXIT2(f, p1, p2) \
313 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeGuard(f, p1, p2); \
314 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
315
316#define wxON_BLOCK_EXIT_OBJ2(o, m, p1, p2) \
317 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeObjGuard(o, m, p1, p2); \
318 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
319
320#endif // _WX_SCOPEGUARD_H_
321