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