blocxx
ScopeGuard.hpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Quest Software, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Quest Software, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
34// The Loki Library
35// Copyright (c) 2000 Andrei Alexandrescu
36// Copyright (c) 2000 Petru Marginean
37// Copyright (c) 2005 Joshua Lehrer
38//
39// Permission to use, copy, modify, distribute and sell this software for any
40// purpose is hereby granted without fee, provided that the above copyright
41// notice appear in all copies and that both that copyright notice and this
42// permission notice appear in supporting documentation.
43// The author makes no representations about the
44// suitability of this software for any purpose. It is provided "as is"
45// without express or implied warranty.
47#ifndef BLOCXX_SCOPE_GUARD_HPP_INCLUDE_GUARD_
48#define BLOCXX_SCOPE_GUARD_HPP_INCLUDE_GUARD_
49
50#include "blocxx/BLOCXX_config.h"
51#include "blocxx/RefToValue.hpp"
52
53namespace BLOCXX_NAMESPACE
54{
55
57 {
59
60 protected:
61
64
66 : m_dismissed(other.m_dismissed)
67 {
68 other.dismiss();
69 }
70
71 template <typename J>
72 static void safeExecute(J& j) throw()
73 {
74 if (!j.m_dismissed)
75 try
76 {
77 j.execute();
78 }
79 catch(...)
80 {}
81 }
82
83 mutable bool m_dismissed;
84
85 public:
86 ScopeGuardImplBase() throw() : m_dismissed(false)
87 {}
88
89 void dismiss() const throw()
90 {
91 m_dismissed = true;
92 }
93 };
94
105
107
108 template <typename F>
110 {
111 public:
113 {
114 return ScopeGuardImpl0<F>(fun);
115 }
116
118 {
119 safeExecute(*this);
120 }
121
122 void execute()
123 {
124 m_fun();
125 }
126
127 protected:
129 {}
130
132 };
133
134 template <typename F>
136 {
138 }
139
140 template <typename F, typename P1>
142 {
143 public:
145 {
146 return ScopeGuardImpl1<F, P1>(fun, p1);
147 }
148
150 {
151 safeExecute(*this);
152 }
153
154 void execute()
155 {
156 m_fun(m_p1);
157 }
158
159 protected:
160 ScopeGuardImpl1(F fun, P1 p1) : m_fun(fun), m_p1(p1)
161 {}
162
164 const P1 m_p1;
165 };
166
167 template <typename F, typename P1>
169 {
170 return ScopeGuardImpl1<F, P1>::makeGuard(fun, p1);
171 }
172
173 template <typename F, typename P1, typename P2>
175 {
176 public:
177 static ScopeGuardImpl2<F, P1, P2> makeGuard(F fun, P1 p1, P2 p2)
178 {
179 return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
180 }
181
183 {
184 safeExecute(*this);
185 }
186
187 void execute()
188 {
189 m_fun(m_p1, m_p2);
190 }
191
192 protected:
193 ScopeGuardImpl2(F fun, P1 p1, P2 p2) : m_fun(fun), m_p1(p1), m_p2(p2)
194 {}
195
197 const P1 m_p1;
198 const P2 m_p2;
199 };
200
201 template <typename F, typename P1, typename P2>
202 inline ScopeGuardImpl2<F, P1, P2> makeGuard(F fun, P1 p1, P2 p2)
203 {
204 return ScopeGuardImpl2<F, P1, P2>::makeGuard(fun, p1, p2);
205 }
206
207 template <typename F, typename P1, typename P2, typename P3>
209 {
210 public:
211 static ScopeGuardImpl3<F, P1, P2, P3> makeGuard(F fun, P1 p1, P2 p2, P3 p3)
212 {
213 return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
214 }
215
217 {
218 safeExecute(*this);
219 }
220
221 void execute()
222 {
223 m_fun(m_p1, m_p2, m_p3);
224 }
225
226 protected:
227 ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : m_fun(fun), m_p1(p1), m_p2(p2), m_p3(p3)
228 {}
229
231 const P1 m_p1;
232 const P2 m_p2;
233 const P3 m_p3;
234 };
235
236 template <typename F, typename P1, typename P2, typename P3>
237 inline ScopeGuardImpl3<F, P1, P2, P3> makeGuard(F fun, P1 p1, P2 p2, P3 p3)
238 {
239 return ScopeGuardImpl3<F, P1, P2, P3>::makeGuard(fun, p1, p2, p3);
240 }
241
242 //************************************************************
243
244 template <class Obj, typename MemFun>
246 {
247 public:
248 static ObjScopeGuardImpl0<Obj, MemFun> makeObjGuard(Obj& obj, MemFun memFun)
249 {
250 return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
251 }
252
254 {
255 safeExecute(*this);
256 }
257
258 void execute()
259 {
260 (m_obj.*m_memFun)();
261 }
262
263 protected:
264 ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : m_obj(obj), m_memFun(memFun)
265 {}
266
267 Obj& m_obj;
268 MemFun m_memFun;
269 };
270
271 template <class Obj, typename MemFun>
272 inline ObjScopeGuardImpl0<Obj, MemFun> makeObjGuard(Obj& obj, MemFun memFun)
273 {
275 }
276
277 template <typename Ret, class Obj1, class Obj2>
278 inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> makeGuard(Ret(Obj2::*memFun)(), Obj1 &obj)
279 {
280 return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::makeObjGuard(obj,memFun);
281 }
282
283 template <typename Ret, class Obj1, class Obj2>
284 inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> makeGuard(Ret(Obj2::*memFun)(), Obj1 *obj)
285 {
286 return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::makeObjGuard(*obj,memFun);
287 }
288
289 template <class Obj, typename MemFun, typename P1>
291 {
292 public:
293 static ObjScopeGuardImpl1<Obj, MemFun, P1> makeObjGuard(Obj& obj, MemFun memFun, P1 p1)
294 {
295 return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
296 }
297
299 {
300 safeExecute(*this);
301 }
302
303 void execute()
304 {
305 (m_obj.*m_memFun)(m_p1);
306 }
307
308 protected:
309 ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : m_obj(obj), m_memFun(memFun), m_p1(p1)
310 {}
311
312 Obj& m_obj;
313 MemFun m_memFun;
314 const P1 m_p1;
315 };
316
317 template <class Obj, typename MemFun, typename P1>
318 inline ObjScopeGuardImpl1<Obj, MemFun, P1> makeObjGuard(Obj& obj, MemFun memFun, P1 p1)
319 {
321 }
322
323 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
324 inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> makeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1)
325 {
326 return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::makeObjGuard(obj,memFun,p1);
327 }
328
329 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
330 inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> makeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1)
331 {
332 return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::makeObjGuard(*obj,memFun,p1);
333 }
334
335 template <class Obj, typename MemFun, typename P1, typename P2>
337 {
338 public:
339 static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> makeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
340 {
341 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
342 }
343
345 {
346 safeExecute(*this);
347 }
348
349 void execute()
350 {
351 (m_obj.*m_memFun)(m_p1, m_p2);
352 }
353
354 protected:
355 ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : m_obj(obj), m_memFun(memFun), m_p1(p1), m_p2(p2)
356 {}
357
358 Obj& m_obj;
359 MemFun m_memFun;
360 const P1 m_p1;
361 const P2 m_p2;
362 };
363
364 template <class Obj, typename MemFun, typename P1, typename P2>
365 inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> makeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
366 {
368 }
369
370 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
371 inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> makeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2)
372 {
373 return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::makeObjGuard(obj,memFun,p1,p2);
374 }
375
376 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
377 inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> makeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2)
378 {
379 return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::makeObjGuard(*obj,memFun,p1,p2);
380 }
381
382} // namespace BLOCXX_NAMESPACE
383
384#define BLOCXX_CONCATENATE_DIRECT(s1, s2) s1##s2
385#define BLOCXX_CONCATENATE(s1, s2) BLOCXX_CONCATENATE_DIRECT(s1, s2)
386#define BLOCXX_ANONYMOUS_VARIABLE(str) BLOCXX_CONCATENATE(str, __LINE__)
387
388#define BLOCXX_ON_BLOCK_EXIT blocxx::ScopeGuard BLOCXX_ANONYMOUS_VARIABLE(scopeGuard) = blocxx::makeGuard
389#define BLOCXX_ON_BLOCK_EXIT_OBJ blocxx::ScopeGuard BLOCXX_ANONYMOUS_VARIABLE(scopeGuard) = blocxx::makeObjGuard
390
391#endif
392
#define F(x, y, z)
Definition MD5.cpp:209
ObjScopeGuardImpl0(Obj &obj, MemFun memFun)
static ObjScopeGuardImpl0< Obj, MemFun > makeObjGuard(Obj &obj, MemFun memFun)
ObjScopeGuardImpl1(Obj &obj, MemFun memFun, P1 p1)
static ObjScopeGuardImpl1< Obj, MemFun, P1 > makeObjGuard(Obj &obj, MemFun memFun, P1 p1)
static ObjScopeGuardImpl2< Obj, MemFun, P1, P2 > makeObjGuard(Obj &obj, MemFun memFun, P1 p1, P2 p2)
ObjScopeGuardImpl2(Obj &obj, MemFun memFun, P1 p1, P2 p2)
static ScopeGuardImpl0< F > makeGuard(F fun)
static ScopeGuardImpl1< F, P1 > makeGuard(F fun, P1 p1)
ScopeGuardImpl2(F fun, P1 p1, P2 p2)
static ScopeGuardImpl2< F, P1, P2 > makeGuard(F fun, P1 p1, P2 p2)
ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3)
static ScopeGuardImpl3< F, P1, P2, P3 > makeGuard(F fun, P1 p1, P2 p2, P3 p3)
ScopeGuardImplBase & operator=(const ScopeGuardImplBase &)
ScopeGuardImplBase(const ScopeGuardImplBase &other)
Taken from RFC 1321.
ScopeGuardImpl0< F > makeGuard(F fun)
ObjScopeGuardImpl0< Obj, MemFun > makeObjGuard(Obj &obj, MemFun memFun)
const ScopeGuardImplBase & ScopeGuard
See Andrei's and Petru Marginean's CUJ article http://www.cuj.com/documents/s=8000/cujcexp1812alexand...