MongoDB  2.6.0
scopeguard.h
1 // The Loki Library
3 // Copyright (c) 2000 Andrei Alexandrescu
4 // Copyright (c) 2000 Petru Marginean
5 // Copyright (c) 2005 Joshua Lehrer
6 //
7 // Permission to use, copy, modify, distribute and sell this software for any
8 // purpose is hereby granted without fee, provided that the above copyright
9 // notice appear in all copies and that both that copyright notice and this
10 // permission notice appear in supporting documentation.
11 // The author makes no representations about the
12 // suitability of this software for any purpose. It is provided "as is"
13 // without express or implied warranty.
15 #ifndef LOKI_SCOPEGUARD_H_
16 #define LOKI_SCOPEGUARD_H_
17 
18 #include "mongo/platform/compiler.h"
19 
20 namespace mongo
21 {
22 
29 
30  template <class T>
31  class RefToValue
32  {
33  public:
34 
35  RefToValue(T& ref) : ref_(ref)
36  {}
37 
38  RefToValue(const RefToValue& rhs) : ref_(rhs.ref_)
39  {}
40 
41  operator T& () const
42  {
43  return ref_;
44  }
45 
46  private:
47  // Disable - not implemented
48  RefToValue();
49  RefToValue& operator=(const RefToValue&);
50 
51  T& ref_;
52  };
53 
54 
58 
59  template <class T>
60  inline RefToValue<T> ByRef(T& t)
61  {
62  return RefToValue<T>(t);
63  }
64 
65 
66 
67 
70  /*
71  Trivial example for use:
72 
73  FILE* f = fopen("myfile.txt", "w+");
74  if (!f)
75  return error;
76  ON_BLOCK_EXIT(fclose, f);
77 
78 
79  More complicated example:
80 
81  ScopeGuard guard = MakeGuard(my_rollback_func, myparam);
82  ...
83  if (successful) {
84  guard.Dismiss();
85  return;
86  }
87  // guard is still active here and will fire at scope exit
88  ...
89 
90 
91  */
92 
93 
95  {
96  ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
97 
98  protected:
99 
101  {}
102 
103  ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
104  : dismissed_(other.dismissed_)
105  {
106  other.Dismiss();
107  }
108 
109  template <typename J>
110  static void SafeExecute(J& j) throw()
111  {
112  if (!j.dismissed_)
113  try
114  {
115  j.Execute();
116  }
117  catch(...)
118  {}
119  }
120 
121  mutable bool dismissed_;
122 
123  public:
124  ScopeGuardImplBase() throw() : dismissed_(false)
125  {}
126 
127  void Dismiss() const throw()
128  {
129  dismissed_ = true;
130  }
131  };
132 
143 
145 
146  template <typename F>
148  {
149  public:
150  static ScopeGuardImpl0<F> MakeGuard(F fun)
151  {
152  return ScopeGuardImpl0<F>(fun);
153  }
154 
155  ~ScopeGuardImpl0() throw()
156  {
157  SafeExecute(*this);
158  }
159 
160  void Execute()
161  {
162  fun_();
163  }
164 
165  protected:
166  ScopeGuardImpl0(F fun) : fun_(fun)
167  {}
168 
169  F fun_;
170  };
171 
172  template <typename F>
173  inline ScopeGuardImpl0<F> MakeGuard(F fun)
174  {
175  return ScopeGuardImpl0<F>::MakeGuard(fun);
176  }
177 
178  template <typename F, typename P1>
180  {
181  public:
182  static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
183  {
184  return ScopeGuardImpl1<F, P1>(fun, p1);
185  }
186 
187  ~ScopeGuardImpl1() throw()
188  {
189  SafeExecute(*this);
190  }
191 
192  void Execute()
193  {
194  fun_(p1_);
195  }
196 
197  protected:
198  ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1)
199  {}
200 
201  F fun_;
202  const P1 p1_;
203  };
204 
205  template <typename F, typename P1>
206  inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
207  {
208  return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
209  }
210 
211  template <typename F, typename P1, typename P2>
213  {
214  public:
215  static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
216  {
217  return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
218  }
219 
220  ~ScopeGuardImpl2() throw()
221  {
222  SafeExecute(*this);
223  }
224 
225  void Execute()
226  {
227  fun_(p1_, p2_);
228  }
229 
230  protected:
231  ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2)
232  {}
233 
234  F fun_;
235  const P1 p1_;
236  const P2 p2_;
237  };
238 
239  template <typename F, typename P1, typename P2>
240  inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
241  {
242  return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
243  }
244 
245  template <typename F, typename P1, typename P2, typename P3>
247  {
248  public:
249  static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
250  {
251  return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
252  }
253 
254  ~ScopeGuardImpl3() throw()
255  {
256  SafeExecute(*this);
257  }
258 
259  void Execute()
260  {
261  fun_(p1_, p2_, p3_);
262  }
263 
264  protected:
265  ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3)
266  {}
267 
268  F fun_;
269  const P1 p1_;
270  const P2 p2_;
271  const P3 p3_;
272  };
273 
274  template <typename F, typename P1, typename P2, typename P3>
275  inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
276  {
277  return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3);
278  }
279 
280  //************************************************************
281 
282  template <class Obj, typename MemFun>
284  {
285  public:
286  static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
287  {
288  return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
289  }
290 
291  ~ObjScopeGuardImpl0() throw()
292  {
293  SafeExecute(*this);
294  }
295 
296  void Execute()
297  {
298  (obj_.*memFun_)();
299  }
300 
301  protected:
302  ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun)
303  {}
304 
305  Obj& obj_;
306  MemFun memFun_;
307  };
308 
309  template <class Obj, typename MemFun>
310  inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
311  {
313  }
314 
315  template <typename Ret, class Obj1, class Obj2>
316  inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj)
317  {
318  return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(obj,memFun);
319  }
320 
321  template <typename Ret, class Obj1, class Obj2>
322  inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj)
323  {
324  return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(*obj,memFun);
325  }
326 
327  template <class Obj, typename MemFun, typename P1>
329  {
330  public:
331  static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
332  {
333  return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
334  }
335 
336  ~ObjScopeGuardImpl1() throw()
337  {
338  SafeExecute(*this);
339  }
340 
341  void Execute()
342  {
343  (obj_.*memFun_)(p1_);
344  }
345 
346  protected:
347  ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1)
348  {}
349 
350  Obj& obj_;
351  MemFun memFun_;
352  const P1 p1_;
353  };
354 
355  template <class Obj, typename MemFun, typename P1>
356  inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
357  {
359  }
360 
361  template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
362  inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1)
363  {
364  return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(obj,memFun,p1);
365  }
366 
367  template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
368  inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1)
369  {
370  return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(*obj,memFun,p1);
371  }
372 
373  template <class Obj, typename MemFun, typename P1, typename P2>
375  {
376  public:
377  static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
378  {
379  return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
380  }
381 
382  ~ObjScopeGuardImpl2() throw()
383  {
384  SafeExecute(*this);
385  }
386 
387  void Execute()
388  {
389  (obj_.*memFun_)(p1_, p2_);
390  }
391 
392  protected:
393  ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2)
394  {}
395 
396  Obj& obj_;
397  MemFun memFun_;
398  const P1 p1_;
399  const P2 p2_;
400  };
401 
402  template <class Obj, typename MemFun, typename P1, typename P2>
403  inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
404  {
405  return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2);
406  }
407 
408  template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
409  inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2)
410  {
411  return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(obj,memFun,p1,p2);
412  }
413 
414  template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
415  inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2)
416  {
417  return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(*obj,memFun,p1,p2);
418  }
419 
420 } // namespace Loki
421 
422 #define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2
423 #define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2)
424 #define LOKI_ANONYMOUS_VARIABLE(str) LOKI_CONCATENATE(str, __LINE__)
425 
426 #define ON_BLOCK_EXIT \
427  MONGO_COMPILER_VARIABLE_UNUSED ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard
428 #define ON_BLOCK_EXIT_OBJ \
429  MONGO_COMPILER_VARIABLE_UNUSED ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuard
430 
431 #endif //LOKI_SCOPEGUARD_H_
Definition: scopeguard.h:212
Definition: scopeguard.h:374
RefToValue< T > ByRef(T &t)
RefToValue creator.
Definition: scopeguard.h:60
Definition: scopeguard.h:246
Definition: scopeguard.h:179
const ScopeGuardImplBase & ScopeGuard
See Andrei&#39;s and Petru Marginean&#39;s CUJ article http://www.cuj.com/documents/s=8000/cujcexp1812alexand...
Definition: scopeguard.h:144
Definition: scopeguard.h:283
Definition: scopeguard.h:147
Transports a reference as a value Serves to implement the Colvin/Gibbons trick for SmartPtr/ScopeGuar...
Definition: scopeguard.h:31
ScopeGuard.
Definition: scopeguard.h:94
Definition: scopeguard.h:328