/src/boost/boost/multi_index/detail/scope_guard.hpp
Line | Count | Source |
1 | | /* Copyright 2003-2020 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/core/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 | 0 | scope_guard_impl_base():dismissed_(false){} |
64 | 0 | void dismiss()const{dismissed_=true;} |
65 | | |
66 | | /* This helps prevent some "unused variable" warnings under, for instance, |
67 | | * GCC 3.2. |
68 | | */ |
69 | 0 | void touch()const{} |
70 | | |
71 | | protected: |
72 | 0 | ~scope_guard_impl_base(){} |
73 | | |
74 | | scope_guard_impl_base(const scope_guard_impl_base& other): |
75 | | dismissed_(other.dismissed_) |
76 | 0 | { |
77 | 0 | other.dismiss(); |
78 | 0 | } |
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 |