1 ////////////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2000 Andrei Alexandrescu
4 // Copyright (c) 2000 Petru Marginean
5 // Copyright (c) 2005 Joshua Lehrer
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.
14 ////////////////////////////////////////////////////////////////////////////////
15 #ifndef LOKI_SCOPEGUARD_INC_
16 #define LOKI_SCOPEGUARD_INC_
18 // $Id: ScopeGuard.h 799 2006-12-20 00:37:13Z rich_sposato $
21 #include <loki/RefToValue.h>
23 /// \defgroup ExceptionGroup Exception-safe code
28 ////////////////////////////////////////////////////////////////
30 /// \class ScopeGuardImplBase
31 /// \ingroup ExceptionGroup
33 /// Base class used by all ScopeGuard implementations. All commonly used
34 /// functions are in this class (e.g. - Dismiss and SafeExecute).
36 /// See Andrei's and Petru Marginean's CUJ article
37 /// http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/alexandr.htm
39 /// Changes to the original code by Joshua Lehrer:
40 /// http://www.lehrerfamily.com/scopeguard.html
41 ////////////////////////////////////////////////////////////////
43 class ScopeGuardImplBase
45 /// Copy-assignment operator is not implemented and private.
46 ScopeGuardImplBase &operator =(const ScopeGuardImplBase &);
53 /// Copy-constructor takes over responsibility from other ScopeGuard.
54 ScopeGuardImplBase(const ScopeGuardImplBase &other) throw()
55 : dismissed_(other.dismissed_)
61 static void SafeExecute(J &j) throw()
72 mutable bool dismissed_;
75 ScopeGuardImplBase() throw() : dismissed_(false)
78 void Dismiss() const throw()
84 ////////////////////////////////////////////////////////////////
86 /// \typedef typedef const ScopeGuardImplBase& ScopeGuard
87 /// \ingroup ExceptionGroup
89 ////////////////////////////////////////////////////////////////
91 typedef const ScopeGuardImplBase &ScopeGuard;
93 ////////////////////////////////////////////////////////////////
95 /// \class ScopeGuardImpl0
96 /// \ingroup ExceptionGroup
98 /// Implementation class for a standalone function or class static function
99 /// with no parameters. ScopeGuard ignores any value returned from the
100 /// call within the Execute function.
102 /// This class has a single standalone helper function, MakeGuard which
103 /// creates and returns a ScopeGuard.
105 ////////////////////////////////////////////////////////////////
107 template <typename F>
108 class ScopeGuardImpl0 : public ScopeGuardImplBase
111 static ScopeGuardImpl0<F> MakeGuard(F fun)
113 return ScopeGuardImpl0<F>(fun);
116 ~ScopeGuardImpl0() throw()
127 ScopeGuardImpl0(F fun) : fun_(fun)
133 template <typename F>
134 inline ScopeGuardImpl0<F> MakeGuard(F fun)
136 return ScopeGuardImpl0<F>::MakeGuard(fun);
139 ////////////////////////////////////////////////////////////////
141 /// \class ScopeGuardImpl1
142 /// \ingroup ExceptionGroup
144 /// Implementation class for a standalone function or class static function
145 /// with one parameter. Each parameter is copied by value - use
146 /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores
147 /// any value returned from the call within the Execute function.
149 /// This class has a single standalone helper function, MakeGuard which
150 /// creates and returns a ScopeGuard.
152 ////////////////////////////////////////////////////////////////
154 template <typename F, typename P1>
155 class ScopeGuardImpl1 : public ScopeGuardImplBase
158 static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
160 return ScopeGuardImpl1<F, P1>(fun, p1);
163 ~ScopeGuardImpl1() throw()
174 ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1)
181 template <typename F, typename P1>
182 inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
184 return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
187 ////////////////////////////////////////////////////////////////
189 /// \class ScopeGuardImpl2
190 /// \ingroup ExceptionGroup
192 /// Implementation class for a standalone function or class static function
193 /// with two parameters. Each parameter is copied by value - use
194 /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores
195 /// any value returned from the call within the Execute function.
197 /// This class has a single standalone helper function, MakeGuard which
198 /// creates and returns a ScopeGuard.
200 ////////////////////////////////////////////////////////////////
202 template <typename F, typename P1, typename P2>
203 class ScopeGuardImpl2: public ScopeGuardImplBase
206 static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
208 return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
211 ~ScopeGuardImpl2() throw()
222 ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2)
230 template <typename F, typename P1, typename P2>
231 inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
233 return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
236 ////////////////////////////////////////////////////////////////
238 /// \class ScopeGuardImpl3
239 /// \ingroup ExceptionGroup
241 /// Implementation class for a standalone function or class static function
242 /// with three parameters. Each parameter is copied by value - use
243 /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores
244 /// any value returned from the call within the Execute function.
246 /// This class has a single standalone helper function, MakeGuard which
247 /// creates and returns a ScopeGuard.
249 ////////////////////////////////////////////////////////////////
251 template <typename F, typename P1, typename P2, typename P3>
252 class ScopeGuardImpl3 : public ScopeGuardImplBase
255 static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
257 return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
260 ~ScopeGuardImpl3() throw()
271 ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3)
280 template <typename F, typename P1, typename P2, typename P3>
281 inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
283 return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3);
286 ////////////////////////////////////////////////////////////////
288 /// \class ScopeGuardImpl4
289 /// \ingroup ExceptionGroup
291 /// Implementation class for a standalone function or class static function
292 /// with four parameters. Each parameter is copied by value - use
293 /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores
294 /// any value returned from the call within the Execute function.
296 /// This class has a single standalone helper function, MakeGuard which
297 /// creates and returns a ScopeGuard.
299 ////////////////////////////////////////////////////////////////
301 template < typename F, typename P1, typename P2, typename P3, typename P4 >
302 class ScopeGuardImpl4 : public ScopeGuardImplBase
305 static ScopeGuardImpl4< F, P1, P2, P3, P4 > MakeGuard(
306 F fun, P1 p1, P2 p2, P3 p3, P4 p4 )
308 return ScopeGuardImpl4< F, P1, P2, P3, P4 >( fun, p1, p2, p3, p4 );
311 ~ScopeGuardImpl4() throw()
313 SafeExecute( *this );
318 fun_( p1_, p2_, p3_, p4_ );
322 ScopeGuardImpl4( F fun, P1 p1, P2 p2, P3 p3, P4 p4 ) :
323 fun_( fun ), p1_( p1 ), p2_( p2 ), p3_( p3 ), p4_( p4 )
333 template < typename F, typename P1, typename P2, typename P3, typename P4 >
334 inline ScopeGuardImpl4< F, P1, P2, P3, P4 > MakeGuard( F fun, P1 p1, P2 p2, P3 p3, P4 p4 )
336 return ScopeGuardImpl4< F, P1, P2, P3, P4 >::MakeGuard( fun, p1, p2, p3, p4 );
339 ////////////////////////////////////////////////////////////////
341 /// \class ScopeGuardImpl5
342 /// \ingroup ExceptionGroup
344 /// Implementation class for a standalone function or class static function
345 /// with five parameters. Each parameter is copied by value - use
346 /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores
347 /// any value returned from the call within the Execute function.
349 /// This class has a single standalone helper function, MakeGuard which
350 /// creates and returns a ScopeGuard.
352 ////////////////////////////////////////////////////////////////
354 template < typename F, typename P1, typename P2, typename P3, typename P4, typename P5 >
355 class ScopeGuardImpl5 : public ScopeGuardImplBase
358 static ScopeGuardImpl5< F, P1, P2, P3, P4, P5 > MakeGuard(
359 F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 )
361 return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >( fun, p1, p2, p3, p4, p5 );
364 ~ScopeGuardImpl5() throw()
366 SafeExecute( *this );
371 fun_( p1_, p2_, p3_, p4_, p5_ );
375 ScopeGuardImpl5( F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) :
376 fun_( fun ), p1_( p1 ), p2_( p2 ), p3_( p3 ), p4_( p4 ), p5_( p5 )
387 template < typename F, typename P1, typename P2, typename P3, typename P4, typename P5 >
388 inline ScopeGuardImpl5< F, P1, P2, P3, P4, P5 > MakeGuard( F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 )
390 return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >::MakeGuard( fun, p1, p2, p3, p4, p5 );
393 ////////////////////////////////////////////////////////////////
395 /// \class ObjScopeGuardImpl0
396 /// \ingroup ExceptionGroup
398 /// Implementation class for a class per-instance member function with no
399 /// parameters. ScopeGuard ignores any value returned from the call within
400 /// the Execute function.
402 /// This class has 3 standalone helper functions which create a ScopeGuard.
403 /// One is MakeObjGuard, which is deprecated but provided for older code.
404 /// The other two are MakeGuard overloads, one which takes a pointer to an
405 /// object, and the other which takes a reference.
407 ////////////////////////////////////////////////////////////////
409 template <class Obj, typename MemFun>
410 class ObjScopeGuardImpl0 : public ScopeGuardImplBase
413 static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj &obj, MemFun memFun)
415 return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
418 ~ObjScopeGuardImpl0() throw()
429 ObjScopeGuardImpl0(Obj &obj, MemFun memFun) : obj_(obj), memFun_(memFun)
436 template <class Obj, typename MemFun>
437 inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj &obj, MemFun memFun)
439 return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
442 template <typename Ret, class Obj1, class Obj2>
443 inline ObjScopeGuardImpl0<Obj1,Ret(Obj2:: *)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj)
445 return ObjScopeGuardImpl0<Obj1,Ret(Obj2:: *)()>::MakeObjGuard(obj,memFun);
448 template <typename Ret, class Obj1, class Obj2>
449 inline ObjScopeGuardImpl0<Obj1,Ret(Obj2:: *)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj)
451 return ObjScopeGuardImpl0<Obj1,Ret(Obj2:: *)()>::MakeObjGuard(*obj,memFun);
454 ////////////////////////////////////////////////////////////////
456 /// \class ObjScopeGuardImpl1
457 /// \ingroup ExceptionGroup
459 /// Implementation class for a class per-instance member function with one
460 /// parameter. The parameter is copied by value - use ::Loki::ByRef if you
461 /// must use a reference instead. ScopeGuard ignores any value returned
462 /// from the call within the Execute function.
464 /// This class has 3 standalone helper functions which create a ScopeGuard.
465 /// One is MakeObjGuard, which is deprecated but provided for older code.
466 /// The other two are MakeGuard overloads, one which takes a pointer to an
467 /// object, and the other which takes a reference.
469 ////////////////////////////////////////////////////////////////
471 template <class Obj, typename MemFun, typename P1>
472 class ObjScopeGuardImpl1 : public ScopeGuardImplBase
475 static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj &obj, MemFun memFun, P1 p1)
477 return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
480 ~ObjScopeGuardImpl1() throw()
487 (obj_.*memFun_)(p1_);
491 ObjScopeGuardImpl1(Obj &obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1)
499 template <class Obj, typename MemFun, typename P1>
500 inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj &obj, MemFun memFun, P1 p1)
502 return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
505 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
506 inline ObjScopeGuardImpl1<Obj1,Ret(Obj2:: *)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1)
508 return ObjScopeGuardImpl1<Obj1,Ret(Obj2:: *)(P1a),P1b>::MakeObjGuard(obj,memFun,p1);
511 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
512 inline ObjScopeGuardImpl1<Obj1,Ret(Obj2:: *)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1)
514 return ObjScopeGuardImpl1<Obj1,Ret(Obj2:: *)(P1a),P1b>::MakeObjGuard(*obj,memFun,p1);
517 ////////////////////////////////////////////////////////////////
519 /// \class ObjScopeGuardImpl2
520 /// \ingroup ExceptionGroup
522 /// Implementation class for a class per-instance member function with two
523 /// parameters. Each parameter is copied by value - use ::Loki::ByRef if you
524 /// must use a reference instead. ScopeGuard ignores any value returned
525 /// from the call within the Execute function.
527 /// This class has 3 standalone helper functions which create a ScopeGuard.
528 /// One is MakeObjGuard, which is deprecated but provided for older code.
529 /// The other two are MakeGuard overloads, one which takes a pointer to an
530 /// object, and the other which takes a reference.
532 ////////////////////////////////////////////////////////////////
534 template <class Obj, typename MemFun, typename P1, typename P2>
535 class ObjScopeGuardImpl2 : public ScopeGuardImplBase
538 static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj &obj, MemFun memFun, P1 p1, P2 p2)
540 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
543 ~ObjScopeGuardImpl2() throw()
550 (obj_.*memFun_)(p1_, p2_);
554 ObjScopeGuardImpl2(Obj &obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2)
563 template <class Obj, typename MemFun, typename P1, typename P2>
564 inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj &obj, MemFun memFun, P1 p1, P2 p2)
566 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2);
569 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
570 inline ObjScopeGuardImpl2<Obj1,Ret(Obj2:: *)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2)
572 return ObjScopeGuardImpl2<Obj1,Ret(Obj2:: *)(P1a,P2a),P1b,P2b>::MakeObjGuard(obj,memFun,p1,p2);
575 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
576 inline ObjScopeGuardImpl2<Obj1,Ret(Obj2:: *)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2)
578 return ObjScopeGuardImpl2<Obj1,Ret(Obj2:: *)(P1a,P2a),P1b,P2b>::MakeObjGuard(*obj,memFun,p1,p2);
581 ////////////////////////////////////////////////////////////////
583 /// \class ObjScopeGuardImpl3
584 /// \ingroup ExceptionGroup
586 /// Implementation class for a class per-instance member function with three
587 /// parameters. Each parameter is copied by value - use ::Loki::ByRef if you
588 /// must use a reference instead. ScopeGuard ignores any value returned
589 /// from the call within the Execute function.
591 /// This class has 3 standalone helper functions which create a ScopeGuard.
592 /// One is MakeObjGuard, which is deprecated but provided for older code.
593 /// The other two are MakeGuard overloads, one which takes a pointer to an
594 /// object, and the other which takes a reference.
596 ////////////////////////////////////////////////////////////////
598 template < class Obj, typename MemFun, typename P1, typename P2, typename P3 >
599 class ObjScopeGuardImpl3 : public ScopeGuardImplBase
602 static ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 > MakeObjGuard(
603 Obj &obj, MemFun memFun, P1 p1, P2 p2, P3 p3 )
605 return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >( obj, memFun, p1, p2, p3 );
608 ~ObjScopeGuardImpl3() throw()
610 SafeExecute( *this );
615 ( obj_.*memFun_ )( p1_, p2_, p3_ );
619 ObjScopeGuardImpl3( Obj &obj, MemFun memFun, P1 p1, P2 p2, P3 p3 ) :
620 obj_( obj ), memFun_( memFun ), p1_( p1 ), p2_( p2 ), p3_( p3 )
630 template < class Obj, typename MemFun, typename P1, typename P2, typename P3 >
631 inline ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 > MakeObjGuard(
632 Obj &obj, MemFun memFun, P1 p1, P2 p2, P3 p3 )
634 return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >::MakeObjGuard(
635 obj, memFun, p1, p2, p3 );
638 template < typename Ret, class Obj1, class Obj2, typename P1a, typename P1b,
639 typename P2a, typename P2b, typename P3a, typename P3b >
640 inline ObjScopeGuardImpl3< Obj1, Ret( Obj2:: * )( P1a, P2a, P3a ), P1b, P2b, P3b >
641 MakeGuard( Ret( Obj2::*memFun )( P1a, P2a, P3a ), Obj1 &obj, P1b p1, P2b p2, P3b p3 )
643 return ObjScopeGuardImpl3< Obj1, Ret( Obj2:: * )( P1a, P2a, P3a ), P1b, P2b, P3b >
644 ::MakeObjGuard( obj, memFun, p1, p2, p3 );
647 template < typename Ret, class Obj1, class Obj2, typename P1a, typename P1b,
648 typename P2a, typename P2b, typename P3a, typename P3b >
649 inline ObjScopeGuardImpl3< Obj1, Ret( Obj2:: * )( P1a, P2a, P3a ), P1b, P2b, P3b >
650 MakeGuard( Ret( Obj2::*memFun )( P1a, P2a, P3a ), Obj1 *obj, P1b p1, P2b p2, P3b p3 )
652 return ObjScopeGuardImpl3< Obj1, Ret( Obj2:: * )( P1a, P2a, P3a ), P1b, P2b, P3b >
653 ::MakeObjGuard( *obj, memFun, p1, p2, p3 );
658 #define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2
659 #define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2)
660 #define LOKI_ANONYMOUS_VARIABLE(str) LOKI_CONCATENATE(str, __LINE__)
662 #define LOKI_ON_BLOCK_EXIT ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeGuard
663 #define LOKI_ON_BLOCK_EXIT_OBJ ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeObjGuard
665 #endif // end file guardian