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 
53 namespace BLOCXX_NAMESPACE
54 {
55 
57  {
59 
60  protected:
61 
63  {}
64 
65  ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
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 
117  ~ScopeGuardImpl0() throw()
118  {
119  safeExecute(*this);
120  }
121 
122  void execute()
123  {
124  m_fun();
125  }
126 
127  protected:
128  ScopeGuardImpl0(F fun) : m_fun(fun)
129  {}
130 
132  };
133 
134  template <typename F>
136  {
137  return ScopeGuardImpl0<F>::makeGuard(fun);
138  }
139 
140  template <typename F, typename P1>
142  {
143  public:
144  static ScopeGuardImpl1<F, P1> makeGuard(F fun, P1 p1)
145  {
146  return ScopeGuardImpl1<F, P1>(fun, p1);
147  }
148 
149  ~ScopeGuardImpl1() throw()
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>
168  inline ScopeGuardImpl1<F, P1> makeGuard(F fun, P1 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 
182  ~ScopeGuardImpl2() throw()
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 
216  ~ScopeGuardImpl3() throw()
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  {
281  }
282 
283  template <typename Ret, class Obj1, class Obj2>
284  inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> makeGuard(Ret(Obj2::*memFun)(), Obj1 *obj)
285  {
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  {
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  {
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  {
367  return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::makeObjGuard(obj, memFun, p1, p2);
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  {
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  {
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