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