1 /* Copyright 2003-2011 Joaquin M Lopez Munoz.
2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
6 * See http://www.boost.org/libs/multi_index for library home page.
9 #ifndef BOOST_MULTI_INDEX_DETAIL_SCOPE_GUARD_HPP
10 #define BOOST_MULTI_INDEX_DETAIL_SCOPE_GUARD_HPP
12 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
16 #include <boost/detail/no_exceptions_support.hpp>
20 namespace multi_index
{
24 /* Until some official version of the ScopeGuard idiom makes it into Boost,
25 * we locally define our own. This is a merely reformated version of
26 * ScopeGuard.h as defined in:
27 * Alexandrescu, A., Marginean, P.:"Generic<Programming>: Change the Way You
28 * Write Exception-Safe Code - Forever", C/C++ Users Jornal, Dec 2000,
29 * http://www.drdobbs.com/184403758
30 * with the following modifications:
31 * - General pretty formatting (pretty to my taste at least.)
32 * - Naming style changed to standard C++ library requirements.
33 * - Added scope_guard_impl4 and obj_scope_guard_impl3, (Boost.MultiIndex
34 * needs them). A better design would provide guards for many more
35 * arguments through the Boost Preprocessor Library.
36 * - Added scope_guard_impl_base::touch (see below.)
37 * - Removed RefHolder and ByRef, whose functionality is provided
38 * already by Boost.Ref.
39 * - Removed static make_guard's and make_obj_guard's, so that the code
40 * will work even if BOOST_NO_MEMBER_TEMPLATES is defined. This forces
41 * us to move some private ctors to public, though.
43 * NB: CodeWarrior Pro 8 seems to have problems looking up safe_execute
44 * without an explicit qualification.
46 * We also define the following variants of the idiom:
48 * - make_guard_if_c<bool>( ... )
49 * - make_guard_if<IntegralConstant>( ... )
50 * - make_obj_guard_if_c<bool>( ... )
51 * - make_obj_guard_if<IntegralConstant>( ... )
52 * which may be used with a compile-time constant to yield
53 * a "null_guard" if the boolean compile-time parameter is false,
54 * or conversely, the guard is only constructed if the constant is true.
55 * This is useful to avoid extra tagging, because the returned
56 * null_guard can be optimzed comlpetely away by the compiler.
59 class scope_guard_impl_base
62 scope_guard_impl_base():dismissed_(false){}
63 void dismiss()const{dismissed_
=true;}
65 /* This helps prevent some "unused variable" warnings under, for instance,
71 ~scope_guard_impl_base(){}
73 scope_guard_impl_base(const scope_guard_impl_base
& other
):
74 dismissed_(other
.dismissed_
)
80 static void safe_execute(J
& j
){
82 if(!j
.dismissed_
)j
.execute();
88 mutable bool dismissed_
;
91 scope_guard_impl_base
& operator=(const scope_guard_impl_base
&);
94 typedef const scope_guard_impl_base
& scope_guard
;
96 struct null_guard
: public scope_guard_impl_base
99 null_guard( const T1
& )
102 template< class T1
, class T2
>
103 null_guard( const T1
&, const T2
& )
106 template< class T1
, class T2
, class T3
>
107 null_guard( const T1
&, const T2
&, const T3
& )
110 template< class T1
, class T2
, class T3
, class T4
>
111 null_guard( const T1
&, const T2
&, const T3
&, const T4
& )
114 template< class T1
, class T2
, class T3
, class T4
, class T5
>
115 null_guard( const T1
&, const T2
&, const T3
&, const T4
&, const T5
& )
119 template< bool cond
, class T
>
120 struct null_guard_return
122 typedef typename
boost::mpl::if_c
<cond
,T
,null_guard
>::type type
;
126 class scope_guard_impl0
:public scope_guard_impl_base
129 scope_guard_impl0(F fun
):fun_(fun
){}
130 ~scope_guard_impl0(){scope_guard_impl_base::safe_execute(*this);}
131 void execute(){fun_();}
139 inline scope_guard_impl0
<F
> make_guard(F fun
)
141 return scope_guard_impl0
<F
>(fun
);
144 template<bool cond
, typename F
>
145 inline typename null_guard_return
<cond
,scope_guard_impl0
<F
> >::type
146 make_guard_if_c(F fun
)
148 return typename null_guard_return
<cond
,scope_guard_impl0
<F
> >::type(fun
);
151 template<typename C
, typename F
>
152 inline typename null_guard_return
<C::value
,scope_guard_impl0
<F
> >::type
155 return make_guard_if
<C::value
>(fun
);
158 template<typename F
,typename P1
>
159 class scope_guard_impl1
:public scope_guard_impl_base
162 scope_guard_impl1(F fun
,P1 p1
):fun_(fun
),p1_(p1
){}
163 ~scope_guard_impl1(){scope_guard_impl_base::safe_execute(*this);}
164 void execute(){fun_(p1_
);}
171 template<typename F
,typename P1
>
172 inline scope_guard_impl1
<F
,P1
> make_guard(F fun
,P1 p1
)
174 return scope_guard_impl1
<F
,P1
>(fun
,p1
);
177 template<bool cond
, typename F
,typename P1
>
178 inline typename null_guard_return
<cond
,scope_guard_impl1
<F
,P1
> >::type
179 make_guard_if_c(F fun
,P1 p1
)
181 return typename null_guard_return
<cond
,scope_guard_impl1
<F
,P1
> >::type(fun
,p1
);
184 template<typename C
, typename F
,typename P1
>
185 inline typename null_guard_return
<C::value
,scope_guard_impl1
<F
,P1
> >::type
186 make_guard_if(F fun
,P1 p1
)
188 return make_guard_if_c
<C::value
>(fun
,p1
);
191 template<typename F
,typename P1
,typename P2
>
192 class scope_guard_impl2
:public scope_guard_impl_base
195 scope_guard_impl2(F fun
,P1 p1
,P2 p2
):fun_(fun
),p1_(p1
),p2_(p2
){}
196 ~scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);}
197 void execute(){fun_(p1_
,p2_
);}
205 template<typename F
,typename P1
,typename P2
>
206 inline scope_guard_impl2
<F
,P1
,P2
> make_guard(F fun
,P1 p1
,P2 p2
)
208 return scope_guard_impl2
<F
,P1
,P2
>(fun
,p1
,p2
);
211 template<bool cond
, typename F
,typename P1
,typename P2
>
212 inline typename null_guard_return
<cond
,scope_guard_impl2
<F
,P1
,P2
> >::type
213 make_guard_if_c(F fun
,P1 p1
,P2 p2
)
215 return typename null_guard_return
<cond
,scope_guard_impl2
<F
,P1
,P2
> >::type(fun
,p1
,p2
);
218 template<typename C
, typename F
,typename P1
,typename P2
>
219 inline typename null_guard_return
<C::value
,scope_guard_impl2
<F
,P1
,P2
> >::type
220 make_guard_if(F fun
,P1 p1
,P2 p2
)
222 return make_guard_if_c
<C::value
>(fun
,p1
,p2
);
225 template<typename F
,typename P1
,typename P2
,typename P3
>
226 class scope_guard_impl3
:public scope_guard_impl_base
229 scope_guard_impl3(F fun
,P1 p1
,P2 p2
,P3 p3
):fun_(fun
),p1_(p1
),p2_(p2
),p3_(p3
){}
230 ~scope_guard_impl3(){scope_guard_impl_base::safe_execute(*this);}
231 void execute(){fun_(p1_
,p2_
,p3_
);}
240 template<typename F
,typename P1
,typename P2
,typename P3
>
241 inline scope_guard_impl3
<F
,P1
,P2
,P3
> make_guard(F fun
,P1 p1
,P2 p2
,P3 p3
)
243 return scope_guard_impl3
<F
,P1
,P2
,P3
>(fun
,p1
,p2
,p3
);
246 template<bool cond
,typename F
,typename P1
,typename P2
,typename P3
>
247 inline typename null_guard_return
<cond
,scope_guard_impl3
<F
,P1
,P2
,P3
> >::type
248 make_guard_if_c(F fun
,P1 p1
,P2 p2
,P3 p3
)
250 return typename null_guard_return
<cond
,scope_guard_impl3
<F
,P1
,P2
,P3
> >::type(fun
,p1
,p2
,p3
);
253 template<typename C
,typename F
,typename P1
,typename P2
,typename P3
>
254 inline typename null_guard_return
< C::value
,scope_guard_impl3
<F
,P1
,P2
,P3
> >::type
255 make_guard_if(F fun
,P1 p1
,P2 p2
,P3 p3
)
257 return make_guard_if_c
<C::value
>(fun
,p1
,p2
,p3
);
260 template<typename F
,typename P1
,typename P2
,typename P3
,typename P4
>
261 class scope_guard_impl4
:public scope_guard_impl_base
264 scope_guard_impl4(F fun
,P1 p1
,P2 p2
,P3 p3
,P4 p4
):
265 fun_(fun
),p1_(p1
),p2_(p2
),p3_(p3
),p4_(p4
){}
266 ~scope_guard_impl4(){scope_guard_impl_base::safe_execute(*this);}
267 void execute(){fun_(p1_
,p2_
,p3_
,p4_
);}
277 template<typename F
,typename P1
,typename P2
,typename P3
,typename P4
>
278 inline scope_guard_impl4
<F
,P1
,P2
,P3
,P4
> make_guard(
279 F fun
,P1 p1
,P2 p2
,P3 p3
,P4 p4
)
281 return scope_guard_impl4
<F
,P1
,P2
,P3
,P4
>(fun
,p1
,p2
,p3
,p4
);
284 template<bool cond
, typename F
,typename P1
,typename P2
,typename P3
,typename P4
>
285 inline typename null_guard_return
<cond
,scope_guard_impl4
<F
,P1
,P2
,P3
,P4
> >::type
287 F fun
,P1 p1
,P2 p2
,P3 p3
,P4 p4
)
289 return typename null_guard_return
<cond
,scope_guard_impl4
<F
,P1
,P2
,P3
,P4
> >::type(fun
,p1
,p2
,p3
,p4
);
292 template<typename C
, typename F
,typename P1
,typename P2
,typename P3
,typename P4
>
293 inline typename null_guard_return
<C::value
,scope_guard_impl4
<F
,P1
,P2
,P3
,P4
> >::type
295 F fun
,P1 p1
,P2 p2
,P3 p3
,P4 p4
)
297 return make_guard_if_c
<C::value
>(fun
,p1
,p2
,p3
,p4
);
300 template<class Obj
,typename MemFun
>
301 class obj_scope_guard_impl0
:public scope_guard_impl_base
304 obj_scope_guard_impl0(Obj
& obj
,MemFun mem_fun
):obj_(obj
),mem_fun_(mem_fun
){}
305 ~obj_scope_guard_impl0(){scope_guard_impl_base::safe_execute(*this);}
306 void execute(){(obj_
.*mem_fun_
)();}
313 template<class Obj
,typename MemFun
>
314 inline obj_scope_guard_impl0
<Obj
,MemFun
> make_obj_guard(Obj
& obj
,MemFun mem_fun
)
316 return obj_scope_guard_impl0
<Obj
,MemFun
>(obj
,mem_fun
);
319 template<bool cond
, class Obj
,typename MemFun
>
320 inline typename null_guard_return
<cond
,obj_scope_guard_impl0
<Obj
,MemFun
> >::type
321 make_obj_guard_if_c(Obj
& obj
,MemFun mem_fun
)
323 return typename null_guard_return
<cond
,obj_scope_guard_impl0
<Obj
,MemFun
> >::type(obj
,mem_fun
);
326 template<typename C
, class Obj
,typename MemFun
>
327 inline typename null_guard_return
<C::value
,obj_scope_guard_impl0
<Obj
,MemFun
> >::type
328 make_obj_guard_if(Obj
& obj
,MemFun mem_fun
)
330 return make_obj_guard_if_c
<C::value
>(obj
,mem_fun
);
333 template<class Obj
,typename MemFun
,typename P1
>
334 class obj_scope_guard_impl1
:public scope_guard_impl_base
337 obj_scope_guard_impl1(Obj
& obj
,MemFun mem_fun
,P1 p1
):
338 obj_(obj
),mem_fun_(mem_fun
),p1_(p1
){}
339 ~obj_scope_guard_impl1(){scope_guard_impl_base::safe_execute(*this);}
340 void execute(){(obj_
.*mem_fun_
)(p1_
);}
348 template<class Obj
,typename MemFun
,typename P1
>
349 inline obj_scope_guard_impl1
<Obj
,MemFun
,P1
> make_obj_guard(
350 Obj
& obj
,MemFun mem_fun
,P1 p1
)
352 return obj_scope_guard_impl1
<Obj
,MemFun
,P1
>(obj
,mem_fun
,p1
);
355 template<bool cond
, class Obj
,typename MemFun
,typename P1
>
356 inline typename null_guard_return
<cond
,obj_scope_guard_impl1
<Obj
,MemFun
,P1
> >::type
357 make_obj_guard_if_c( Obj
& obj
,MemFun mem_fun
,P1 p1
)
359 return typename null_guard_return
<cond
,obj_scope_guard_impl1
<Obj
,MemFun
,P1
> >::type(obj
,mem_fun
,p1
);
362 template<typename C
, class Obj
,typename MemFun
,typename P1
>
363 inline typename null_guard_return
<C::value
,obj_scope_guard_impl1
<Obj
,MemFun
,P1
> >::type
364 make_obj_guard_if( Obj
& obj
,MemFun mem_fun
,P1 p1
)
366 return make_obj_guard_if_c
<C::value
>(obj
,mem_fun
,p1
);
369 template<class Obj
,typename MemFun
,typename P1
,typename P2
>
370 class obj_scope_guard_impl2
:public scope_guard_impl_base
373 obj_scope_guard_impl2(Obj
& obj
,MemFun mem_fun
,P1 p1
,P2 p2
):
374 obj_(obj
),mem_fun_(mem_fun
),p1_(p1
),p2_(p2
)
376 ~obj_scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);}
377 void execute(){(obj_
.*mem_fun_
)(p1_
,p2_
);}
386 template<class Obj
,typename MemFun
,typename P1
,typename P2
>
387 inline obj_scope_guard_impl2
<Obj
,MemFun
,P1
,P2
>
388 make_obj_guard(Obj
& obj
,MemFun mem_fun
,P1 p1
,P2 p2
)
390 return obj_scope_guard_impl2
<Obj
,MemFun
,P1
,P2
>(obj
,mem_fun
,p1
,p2
);
393 template<bool cond
, class Obj
,typename MemFun
,typename P1
,typename P2
>
394 inline typename null_guard_return
<cond
,obj_scope_guard_impl2
<Obj
,MemFun
,P1
,P2
> >::type
395 make_obj_guard_if_c(Obj
& obj
,MemFun mem_fun
,P1 p1
,P2 p2
)
397 return typename null_guard_return
<cond
,obj_scope_guard_impl2
<Obj
,MemFun
,P1
,P2
> >::type(obj
,mem_fun
,p1
,p2
);
400 template<typename C
, class Obj
,typename MemFun
,typename P1
,typename P2
>
401 inline typename null_guard_return
<C::value
,obj_scope_guard_impl2
<Obj
,MemFun
,P1
,P2
> >::type
402 make_obj_guard_if(Obj
& obj
,MemFun mem_fun
,P1 p1
,P2 p2
)
404 return make_obj_guard_if_c
<C::value
>(obj
,mem_fun
,p1
,p2
);
407 template<class Obj
,typename MemFun
,typename P1
,typename P2
,typename P3
>
408 class obj_scope_guard_impl3
:public scope_guard_impl_base
411 obj_scope_guard_impl3(Obj
& obj
,MemFun mem_fun
,P1 p1
,P2 p2
,P3 p3
):
412 obj_(obj
),mem_fun_(mem_fun
),p1_(p1
),p2_(p2
),p3_(p3
)
414 ~obj_scope_guard_impl3(){scope_guard_impl_base::safe_execute(*this);}
415 void execute(){(obj_
.*mem_fun_
)(p1_
,p2_
,p3_
);}
425 template<class Obj
,typename MemFun
,typename P1
,typename P2
,typename P3
>
426 inline obj_scope_guard_impl3
<Obj
,MemFun
,P1
,P2
,P3
>
427 make_obj_guard(Obj
& obj
,MemFun mem_fun
,P1 p1
,P2 p2
,P3 p3
)
429 return obj_scope_guard_impl3
<Obj
,MemFun
,P1
,P2
,P3
>(obj
,mem_fun
,p1
,p2
,p3
);
432 template<bool cond
, class Obj
,typename MemFun
,typename P1
,typename P2
,typename P3
>
433 inline typename null_guard_return
<cond
,obj_scope_guard_impl3
<Obj
,MemFun
,P1
,P2
,P3
> >::type
434 make_obj_guard_if_c(Obj
& obj
,MemFun mem_fun
,P1 p1
,P2 p2
,P3 p3
)
436 return typename null_guard_return
<cond
,obj_scope_guard_impl3
<Obj
,MemFun
,P1
,P2
,P3
> >::type(obj
,mem_fun
,p1
,p2
,p3
);
439 template<typename C
, class Obj
,typename MemFun
,typename P1
,typename P2
,typename P3
>
440 inline typename null_guard_return
<C::value
,obj_scope_guard_impl3
<Obj
,MemFun
,P1
,P2
,P3
> >::type
441 make_obj_guard_if(Obj
& obj
,MemFun mem_fun
,P1 p1
,P2 p2
,P3 p3
)
443 return make_obj_guard_if_c
<C::value
>(obj
,mem_fun
,p1
,p2
,p3
);
446 } /* namespace multi_index::detail */
448 } /* namespace multi_index */
450 } /* namespace boost */