]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |