1 | /* Copyright 2003-2013 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) |
5 | * |
6 | * See http://www.boost.org/libs/multi_index for library home page. |
7 | */ |
8 | |
9 | #ifndef BOOST_MULTI_INDEX_DETAIL_SCOPE_GUARD_HPP |
10 | #define BOOST_MULTI_INDEX_DETAIL_SCOPE_GUARD_HPP |
11 | |
12 | #if defined(_MSC_VER) |
13 | #pragma once |
14 | #endif |
15 | |
16 | #include <boost/detail/no_exceptions_support.hpp> |
17 | #include <boost/mpl/if.hpp> |
18 | |
19 | namespace boost{ |
20 | |
21 | namespace multi_index{ |
22 | |
23 | namespace detail{ |
24 | |
25 | /* Until some official version of the ScopeGuard idiom makes it into Boost, |
26 | * we locally define our own. This is a merely reformated version of |
27 | * ScopeGuard.h as defined in: |
28 | * Alexandrescu, A., Marginean, P.:"Generic<Programming>: Change the Way You |
29 | * Write Exception-Safe Code - Forever", C/C++ Users Jornal, Dec 2000, |
30 | * http://www.drdobbs.com/184403758 |
31 | * with the following modifications: |
32 | * - General pretty formatting (pretty to my taste at least.) |
33 | * - Naming style changed to standard C++ library requirements. |
34 | * - Added scope_guard_impl4 and obj_scope_guard_impl3, (Boost.MultiIndex |
35 | * needs them). A better design would provide guards for many more |
36 | * arguments through the Boost Preprocessor Library. |
37 | * - Added scope_guard_impl_base::touch (see below.) |
38 | * - Removed RefHolder and ByRef, whose functionality is provided |
39 | * already by Boost.Ref. |
40 | * - Removed static make_guard's and make_obj_guard's, so that the code |
41 | * will work even if BOOST_NO_MEMBER_TEMPLATES is defined. This forces |
42 | * us to move some private ctors to public, though. |
43 | * |
44 | * NB: CodeWarrior Pro 8 seems to have problems looking up safe_execute |
45 | * without an explicit qualification. |
46 | * |
47 | * We also define the following variants of the idiom: |
48 | * |
49 | * - make_guard_if_c<bool>( ... ) |
50 | * - make_guard_if<IntegralConstant>( ... ) |
51 | * - make_obj_guard_if_c<bool>( ... ) |
52 | * - make_obj_guard_if<IntegralConstant>( ... ) |
53 | * which may be used with a compile-time constant to yield |
54 | * a "null_guard" if the boolean compile-time parameter is false, |
55 | * or conversely, the guard is only constructed if the constant is true. |
56 | * This is useful to avoid extra tagging, because the returned |
57 | * null_guard can be optimzed comlpetely away by the compiler. |
58 | */ |
59 | |
60 | class scope_guard_impl_base |
61 | { |
62 | public: |
63 | scope_guard_impl_base():dismissed_(false){} |
64 | void dismiss()const{dismissed_=true;} |
65 | |
66 | /* This helps prevent some "unused variable" warnings under, for instance, |
67 | * GCC 3.2. |
68 | */ |
69 | void touch()const{} |
70 | |
71 | protected: |
72 | ~scope_guard_impl_base(){} |
73 | |
74 | scope_guard_impl_base(const scope_guard_impl_base& other): |
75 | dismissed_(other.dismissed_) |
76 | { |
77 | other.dismiss(); |
78 | } |
79 | |
80 | template<typename J> |
81 | static void safe_execute(J& j){ |
82 | BOOST_TRY{ |
83 | if(!j.dismissed_)j.execute(); |
84 | } |
85 | BOOST_CATCH(...){} |
86 | BOOST_CATCH_END |
87 | } |
88 | |
89 | mutable bool dismissed_; |
90 | |
91 | private: |
92 | scope_guard_impl_base& operator=(const scope_guard_impl_base&); |
93 | }; |
94 | |
95 | typedef const scope_guard_impl_base& scope_guard; |
96 | |
97 | struct null_guard : public scope_guard_impl_base |
98 | { |
99 | template< class T1 > |
100 | null_guard( const T1& ) |
101 | { } |
102 | |
103 | template< class T1, class T2 > |
104 | null_guard( const T1&, const T2& ) |
105 | { } |
106 | |
107 | template< class T1, class T2, class T3 > |
108 | null_guard( const T1&, const T2&, const T3& ) |
109 | { } |
110 | |
111 | template< class T1, class T2, class T3, class T4 > |
112 | null_guard( const T1&, const T2&, const T3&, const T4& ) |
113 | { } |
114 | |
115 | template< class T1, class T2, class T3, class T4, class T5 > |
116 | null_guard( const T1&, const T2&, const T3&, const T4&, const T5& ) |
117 | { } |
118 | }; |
119 | |
120 | template< bool cond, class T > |
121 | struct null_guard_return |
122 | { |
123 | typedef typename boost::mpl::if_c<cond,T,null_guard>::type type; |
124 | }; |
125 | |
126 | template<typename F> |
127 | class scope_guard_impl0:public scope_guard_impl_base |
128 | { |
129 | public: |
130 | scope_guard_impl0(F fun):fun_(fun){} |
131 | ~scope_guard_impl0(){scope_guard_impl_base::safe_execute(*this);} |
132 | void execute(){fun_();} |
133 | |
134 | protected: |
135 | |
136 | F fun_; |
137 | }; |
138 | |
139 | template<typename F> |
140 | inline scope_guard_impl0<F> make_guard(F fun) |
141 | { |
142 | return scope_guard_impl0<F>(fun); |
143 | } |
144 | |
145 | template<bool cond, typename F> |
146 | inline typename null_guard_return<cond,scope_guard_impl0<F> >::type |
147 | make_guard_if_c(F fun) |
148 | { |
149 | return typename null_guard_return<cond,scope_guard_impl0<F> >::type(fun); |
150 | } |
151 | |
152 | template<typename C, typename F> |
153 | inline typename null_guard_return<C::value,scope_guard_impl0<F> >::type |
154 | make_guard_if(F fun) |
155 | { |
156 | return make_guard_if<C::value>(fun); |
157 | } |
158 | |
159 | template<typename F,typename P1> |
160 | class scope_guard_impl1:public scope_guard_impl_base |
161 | { |
162 | public: |
163 | scope_guard_impl1(F fun,P1 p1):fun_(fun),p1_(p1){} |
164 | ~scope_guard_impl1(){scope_guard_impl_base::safe_execute(*this);} |
165 | void execute(){fun_(p1_);} |
166 | |
167 | protected: |
168 | F fun_; |
169 | const P1 p1_; |
170 | }; |
171 | |
172 | template<typename F,typename P1> |
173 | inline scope_guard_impl1<F,P1> make_guard(F fun,P1 p1) |
174 | { |
175 | return scope_guard_impl1<F,P1>(fun,p1); |
176 | } |
177 | |
178 | template<bool cond, typename F,typename P1> |
179 | inline typename null_guard_return<cond,scope_guard_impl1<F,P1> >::type |
180 | make_guard_if_c(F fun,P1 p1) |
181 | { |
182 | return typename null_guard_return<cond,scope_guard_impl1<F,P1> >::type(fun,p1); |
183 | } |
184 | |
185 | template<typename C, typename F,typename P1> |
186 | inline typename null_guard_return<C::value,scope_guard_impl1<F,P1> >::type |
187 | make_guard_if(F fun,P1 p1) |
188 | { |
189 | return make_guard_if_c<C::value>(fun,p1); |
190 | } |
191 | |
192 | template<typename F,typename P1,typename P2> |
193 | class scope_guard_impl2:public scope_guard_impl_base |
194 | { |
195 | public: |
196 | scope_guard_impl2(F fun,P1 p1,P2 p2):fun_(fun),p1_(p1),p2_(p2){} |
197 | ~scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);} |
198 | void execute(){fun_(p1_,p2_);} |
199 | |
200 | protected: |
201 | F fun_; |
202 | const P1 p1_; |
203 | const P2 p2_; |
204 | }; |
205 | |
206 | template<typename F,typename P1,typename P2> |
207 | inline scope_guard_impl2<F,P1,P2> make_guard(F fun,P1 p1,P2 p2) |
208 | { |
209 | return scope_guard_impl2<F,P1,P2>(fun,p1,p2); |
210 | } |
211 | |
212 | template<bool cond, typename F,typename P1,typename P2> |
213 | inline typename null_guard_return<cond,scope_guard_impl2<F,P1,P2> >::type |
214 | make_guard_if_c(F fun,P1 p1,P2 p2) |
215 | { |
216 | return typename null_guard_return<cond,scope_guard_impl2<F,P1,P2> >::type(fun,p1,p2); |
217 | } |
218 | |
219 | template<typename C, typename F,typename P1,typename P2> |
220 | inline typename null_guard_return<C::value,scope_guard_impl2<F,P1,P2> >::type |
221 | make_guard_if(F fun,P1 p1,P2 p2) |
222 | { |
223 | return make_guard_if_c<C::value>(fun,p1,p2); |
224 | } |
225 | |
226 | template<typename F,typename P1,typename P2,typename P3> |
227 | class scope_guard_impl3:public scope_guard_impl_base |
228 | { |
229 | public: |
230 | scope_guard_impl3(F fun,P1 p1,P2 p2,P3 p3):fun_(fun),p1_(p1),p2_(p2),p3_(p3){} |
231 | ~scope_guard_impl3(){scope_guard_impl_base::safe_execute(*this);} |
232 | void execute(){fun_(p1_,p2_,p3_);} |
233 | |
234 | protected: |
235 | F fun_; |
236 | const P1 p1_; |
237 | const P2 p2_; |
238 | const P3 p3_; |
239 | }; |
240 | |
241 | template<typename F,typename P1,typename P2,typename P3> |
242 | inline scope_guard_impl3<F,P1,P2,P3> make_guard(F fun,P1 p1,P2 p2,P3 p3) |
243 | { |
244 | return scope_guard_impl3<F,P1,P2,P3>(fun,p1,p2,p3); |
245 | } |
246 | |
247 | template<bool cond,typename F,typename P1,typename P2,typename P3> |
248 | inline typename null_guard_return<cond,scope_guard_impl3<F,P1,P2,P3> >::type |
249 | make_guard_if_c(F fun,P1 p1,P2 p2,P3 p3) |
250 | { |
251 | return typename null_guard_return<cond,scope_guard_impl3<F,P1,P2,P3> >::type(fun,p1,p2,p3); |
252 | } |
253 | |
254 | template<typename C,typename F,typename P1,typename P2,typename P3> |
255 | inline typename null_guard_return< C::value,scope_guard_impl3<F,P1,P2,P3> >::type |
256 | make_guard_if(F fun,P1 p1,P2 p2,P3 p3) |
257 | { |
258 | return make_guard_if_c<C::value>(fun,p1,p2,p3); |
259 | } |
260 | |
261 | template<typename F,typename P1,typename P2,typename P3,typename P4> |
262 | class scope_guard_impl4:public scope_guard_impl_base |
263 | { |
264 | public: |
265 | scope_guard_impl4(F fun,P1 p1,P2 p2,P3 p3,P4 p4): |
266 | fun_(fun),p1_(p1),p2_(p2),p3_(p3),p4_(p4){} |
267 | ~scope_guard_impl4(){scope_guard_impl_base::safe_execute(*this);} |
268 | void execute(){fun_(p1_,p2_,p3_,p4_);} |
269 | |
270 | protected: |
271 | F fun_; |
272 | const P1 p1_; |
273 | const P2 p2_; |
274 | const P3 p3_; |
275 | const P4 p4_; |
276 | }; |
277 | |
278 | template<typename F,typename P1,typename P2,typename P3,typename P4> |
279 | inline scope_guard_impl4<F,P1,P2,P3,P4> make_guard( |
280 | F fun,P1 p1,P2 p2,P3 p3,P4 p4) |
281 | { |
282 | return scope_guard_impl4<F,P1,P2,P3,P4>(fun,p1,p2,p3,p4); |
283 | } |
284 | |
285 | template<bool cond, typename F,typename P1,typename P2,typename P3,typename P4> |
286 | inline typename null_guard_return<cond,scope_guard_impl4<F,P1,P2,P3,P4> >::type |
287 | make_guard_if_c( |
288 | F fun,P1 p1,P2 p2,P3 p3,P4 p4) |
289 | { |
290 | return typename null_guard_return<cond,scope_guard_impl4<F,P1,P2,P3,P4> >::type(fun,p1,p2,p3,p4); |
291 | } |
292 | |
293 | template<typename C, typename F,typename P1,typename P2,typename P3,typename P4> |
294 | inline typename null_guard_return<C::value,scope_guard_impl4<F,P1,P2,P3,P4> >::type |
295 | make_guard_if( |
296 | F fun,P1 p1,P2 p2,P3 p3,P4 p4) |
297 | { |
298 | return make_guard_if_c<C::value>(fun,p1,p2,p3,p4); |
299 | } |
300 | |
301 | template<class Obj,typename MemFun> |
302 | class obj_scope_guard_impl0:public scope_guard_impl_base |
303 | { |
304 | public: |
305 | obj_scope_guard_impl0(Obj& obj,MemFun mem_fun):obj_(obj),mem_fun_(mem_fun){} |
306 | ~obj_scope_guard_impl0(){scope_guard_impl_base::safe_execute(*this);} |
307 | void execute(){(obj_.*mem_fun_)();} |
308 | |
309 | protected: |
310 | Obj& obj_; |
311 | MemFun mem_fun_; |
312 | }; |
313 | |
314 | template<class Obj,typename MemFun> |
315 | inline obj_scope_guard_impl0<Obj,MemFun> make_obj_guard(Obj& obj,MemFun mem_fun) |
316 | { |
317 | return obj_scope_guard_impl0<Obj,MemFun>(obj,mem_fun); |
318 | } |
319 | |
320 | template<bool cond, class Obj,typename MemFun> |
321 | inline typename null_guard_return<cond,obj_scope_guard_impl0<Obj,MemFun> >::type |
322 | make_obj_guard_if_c(Obj& obj,MemFun mem_fun) |
323 | { |
324 | return typename null_guard_return<cond,obj_scope_guard_impl0<Obj,MemFun> >::type(obj,mem_fun); |
325 | } |
326 | |
327 | template<typename C, class Obj,typename MemFun> |
328 | inline typename null_guard_return<C::value,obj_scope_guard_impl0<Obj,MemFun> >::type |
329 | make_obj_guard_if(Obj& obj,MemFun mem_fun) |
330 | { |
331 | return make_obj_guard_if_c<C::value>(obj,mem_fun); |
332 | } |
333 | |
334 | template<class Obj,typename MemFun,typename P1> |
335 | class obj_scope_guard_impl1:public scope_guard_impl_base |
336 | { |
337 | public: |
338 | obj_scope_guard_impl1(Obj& obj,MemFun mem_fun,P1 p1): |
339 | obj_(obj),mem_fun_(mem_fun),p1_(p1){} |
340 | ~obj_scope_guard_impl1(){scope_guard_impl_base::safe_execute(*this);} |
341 | void execute(){(obj_.*mem_fun_)(p1_);} |
342 | |
343 | protected: |
344 | Obj& obj_; |
345 | MemFun mem_fun_; |
346 | const P1 p1_; |
347 | }; |
348 | |
349 | template<class Obj,typename MemFun,typename P1> |
350 | inline obj_scope_guard_impl1<Obj,MemFun,P1> make_obj_guard( |
351 | Obj& obj,MemFun mem_fun,P1 p1) |
352 | { |
353 | return obj_scope_guard_impl1<Obj,MemFun,P1>(obj,mem_fun,p1); |
354 | } |
355 | |
356 | template<bool cond, class Obj,typename MemFun,typename P1> |
357 | inline typename null_guard_return<cond,obj_scope_guard_impl1<Obj,MemFun,P1> >::type |
358 | make_obj_guard_if_c( Obj& obj,MemFun mem_fun,P1 p1) |
359 | { |
360 | return typename null_guard_return<cond,obj_scope_guard_impl1<Obj,MemFun,P1> >::type(obj,mem_fun,p1); |
361 | } |
362 | |
363 | template<typename C, class Obj,typename MemFun,typename P1> |
364 | inline typename null_guard_return<C::value,obj_scope_guard_impl1<Obj,MemFun,P1> >::type |
365 | make_obj_guard_if( Obj& obj,MemFun mem_fun,P1 p1) |
366 | { |
367 | return make_obj_guard_if_c<C::value>(obj,mem_fun,p1); |
368 | } |
369 | |
370 | template<class Obj,typename MemFun,typename P1,typename P2> |
371 | class obj_scope_guard_impl2:public scope_guard_impl_base |
372 | { |
373 | public: |
374 | obj_scope_guard_impl2(Obj& obj,MemFun mem_fun,P1 p1,P2 p2): |
375 | obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2) |
376 | {} |
377 | ~obj_scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);} |
378 | void execute(){(obj_.*mem_fun_)(p1_,p2_);} |
379 | |
380 | protected: |
381 | Obj& obj_; |
382 | MemFun mem_fun_; |
383 | const P1 p1_; |
384 | const P2 p2_; |
385 | }; |
386 | |
387 | template<class Obj,typename MemFun,typename P1,typename P2> |
388 | inline obj_scope_guard_impl2<Obj,MemFun,P1,P2> |
389 | make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2) |
390 | { |
391 | return obj_scope_guard_impl2<Obj,MemFun,P1,P2>(obj,mem_fun,p1,p2); |
392 | } |
393 | |
394 | template<bool cond, class Obj,typename MemFun,typename P1,typename P2> |
395 | inline typename null_guard_return<cond,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type |
396 | make_obj_guard_if_c(Obj& obj,MemFun mem_fun,P1 p1,P2 p2) |
397 | { |
398 | return typename null_guard_return<cond,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type(obj,mem_fun,p1,p2); |
399 | } |
400 | |
401 | template<typename C, class Obj,typename MemFun,typename P1,typename P2> |
402 | inline typename null_guard_return<C::value,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type |
403 | make_obj_guard_if(Obj& obj,MemFun mem_fun,P1 p1,P2 p2) |
404 | { |
405 | return make_obj_guard_if_c<C::value>(obj,mem_fun,p1,p2); |
406 | } |
407 | |
408 | template<class Obj,typename MemFun,typename P1,typename P2,typename P3> |
409 | class obj_scope_guard_impl3:public scope_guard_impl_base |
410 | { |
411 | public: |
412 | obj_scope_guard_impl3(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3): |
413 | obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2),p3_(p3) |
414 | {} |
415 | ~obj_scope_guard_impl3(){scope_guard_impl_base::safe_execute(*this);} |
416 | void execute(){(obj_.*mem_fun_)(p1_,p2_,p3_);} |
417 | |
418 | protected: |
419 | Obj& obj_; |
420 | MemFun mem_fun_; |
421 | const P1 p1_; |
422 | const P2 p2_; |
423 | const P3 p3_; |
424 | }; |
425 | |
426 | template<class Obj,typename MemFun,typename P1,typename P2,typename P3> |
427 | inline obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> |
428 | make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3) |
429 | { |
430 | return obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3>(obj,mem_fun,p1,p2,p3); |
431 | } |
432 | |
433 | template<bool cond, class Obj,typename MemFun,typename P1,typename P2,typename P3> |
434 | inline typename null_guard_return<cond,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type |
435 | make_obj_guard_if_c(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3) |
436 | { |
437 | return typename null_guard_return<cond,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type(obj,mem_fun,p1,p2,p3); |
438 | } |
439 | |
440 | template<typename C, class Obj,typename MemFun,typename P1,typename P2,typename P3> |
441 | inline typename null_guard_return<C::value,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type |
442 | make_obj_guard_if(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3) |
443 | { |
444 | return make_obj_guard_if_c<C::value>(obj,mem_fun,p1,p2,p3); |
445 | } |
446 | |
447 | } /* namespace multi_index::detail */ |
448 | |
449 | } /* namespace multi_index */ |
450 | |
451 | } /* namespace boost */ |
452 | |
453 | #endif |
454 | |