scope_guard.h

Go to the documentation of this file.
00001 00008 /* 00009 * Copyright © 2001 Sofus Mortensen 00010 * 00011 * This material is provided "as is", with absolutely no warranty 00012 * expressed or implied. Any use is at your own risk. Permission to 00013 * use or copy this software for any purpose is hereby granted without 00014 * fee, provided the above notices are retained on all copies. 00015 * Permission to modify the code and to distribute modified code is 00016 * granted, provided the above notices are retained, and a notice that 00017 * the code was modified is included with the above copyright notice. 00018 * 00019 * This header is part of comet. 00020 * http://www.lambdasoft.dk/comet 00021 */ 00022 00023 00024 #ifndef COMET_SCOPE_GUARD_H 00025 #define COMET_SCOPE_GUARD_H 00026 00027 #include <comet/config.h> 00028 00029 namespace comet { 00030 00034 namespace impl { 00035 00038 class scope_guard_impl_base 00039 { 00040 scope_guard_impl_base& operator =(const scope_guard_impl_base&); 00041 protected: 00042 ~scope_guard_impl_base() 00043 { 00044 } 00045 scope_guard_impl_base(const scope_guard_impl_base& other) throw() 00046 : dismissed_(other.dismissed_) 00047 { 00048 other.dismiss(); 00049 } 00050 template <typename J> static void safe_execute(J& j) throw() 00051 { 00052 if (!j.dismissed_) 00053 try 00054 { 00055 j.execute(); 00056 } 00057 catch(...) 00058 { 00059 } 00060 } 00061 00062 mutable bool dismissed_; 00063 public: 00064 scope_guard_impl_base() throw() : dismissed_(false) 00065 { 00066 } 00067 void dismiss() const throw() 00068 { 00069 dismissed_ = true; 00070 } 00071 }; 00072 00076 template <typename F> class scope_guard_impl_0 : public scope_guard_impl_base 00077 { 00078 public: 00079 ~scope_guard_impl_0() throw() 00080 { 00081 safe_execute(*this); 00082 } 00083 00084 void execute() 00085 { 00086 fun_(); 00087 } 00088 00089 scope_guard_impl_0(F fun) : fun_(fun) 00090 {} 00091 00092 private: 00093 F fun_; 00094 }; 00095 00099 template <typename F, typename P1> class scope_guard_impl_1 : public scope_guard_impl_base 00100 { 00101 public: 00102 ~scope_guard_impl_1() throw() 00103 { 00104 safe_execute(*this); 00105 } 00106 00107 void execute() 00108 { 00109 fun_(p1_); 00110 } 00111 00112 scope_guard_impl_1(F fun, P1 p1) : fun_(fun), p1_(p1) 00113 {} 00114 00115 private: 00116 F fun_; 00117 const P1 p1_; 00118 }; 00119 00123 template <typename F, typename P1, typename P2> class scope_guard_impl_2: public scope_guard_impl_base 00124 { 00125 public: 00126 ~scope_guard_impl_2() throw() 00127 { 00128 safe_execute(*this); 00129 } 00130 00131 void execute() 00132 { 00133 fun_(p1_, p2_); 00134 } 00135 00136 scope_guard_impl_2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) 00137 {} 00138 00139 private: 00140 F fun_; 00141 const P1 p1_; 00142 const P2 p2_; 00143 }; 00144 00148 template <typename F, typename P1, typename P2, typename P3> class scope_guard_impl_3 : public scope_guard_impl_base 00149 { 00150 public: 00151 ~scope_guard_impl_3() throw() 00152 { 00153 safe_execute(*this); 00154 } 00155 00156 void execute() 00157 { 00158 fun_(p1_, p2_, p3_); 00159 } 00160 00161 scope_guard_impl_3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3) 00162 {} 00163 00164 private: 00165 F fun_; 00166 const P1 p1_; 00167 const P2 p2_; 00168 const P3 p3_; 00169 }; 00170 00174 template <class Obj, typename MemFun> class obj_scope_guard_impl_0 : public scope_guard_impl_base 00175 { 00176 public: 00177 ~obj_scope_guard_impl_0() throw() 00178 { 00179 safe_execute(*this); 00180 } 00181 00182 void execute() 00183 { 00184 (obj_.*memFun_)(); 00185 } 00186 00187 obj_scope_guard_impl_0(Obj& obj, MemFun memFun) 00188 : obj_(obj), memFun_(memFun) {} 00189 00190 private: 00191 Obj& obj_; 00192 MemFun memFun_; 00193 }; 00194 00198 template <class Obj, typename MemFun, typename P1> class obj_scope_guard_impl_1 : public scope_guard_impl_base 00199 { 00200 public: 00201 ~obj_scope_guard_impl_1() throw() 00202 { 00203 safe_execute(*this); 00204 } 00205 00206 void execute() 00207 { 00208 (obj_.*memFun_)(p1_); 00209 } 00210 00211 obj_scope_guard_impl_1(Obj& obj, MemFun memFun, P1 p1) 00212 : obj_(obj), memFun_(memFun), p1_(p1) {} 00213 00214 private: 00215 Obj& obj_; 00216 MemFun memFun_; 00217 const P1 p1_; 00218 }; 00219 00223 template <class Obj, typename MemFun, typename P1, typename P2> class obj_scope_guard_impl_2 : public scope_guard_impl_base 00224 { 00225 public: 00226 ~obj_scope_guard_impl_2() throw() 00227 { 00228 safe_execute(*this); 00229 } 00230 00231 void execute() 00232 { 00233 (obj_.*memFun_)(p1_, p2_); 00234 } 00235 00236 obj_scope_guard_impl_2(Obj& obj, MemFun memFun, P1 p1, P2 p2) 00237 : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) {} 00238 00239 private: 00240 Obj& obj_; 00241 MemFun memFun_; 00242 const P1 p1_; 00243 const P2 p2_; 00244 }; 00245 00250 template <class T> class ref_holder 00251 { 00252 T& ref_; 00253 public: 00254 ref_holder(T& ref) : ref_(ref) {} 00255 operator T& () const 00256 { 00257 return ref_; 00258 } 00259 private: 00260 // Disable assignment - not implemented 00261 ref_holder& operator=(const ref_holder&); 00262 }; 00263 00264 } 00265 00273 template <class T> inline impl::ref_holder<T> by_ref(T& t) 00274 { 00275 return impl::ref_holder<T>(t); 00276 } 00277 00283 template <typename F> inline impl::scope_guard_impl_0<F> make_guard(F fun) 00284 { 00285 return impl::scope_guard_impl_0<F>(fun); 00286 } 00287 00294 template <typename F, typename P1> inline impl::scope_guard_impl_1<F, P1> make_guard(F fun, P1 p1) 00295 { 00296 return impl::scope_guard_impl_1<F, P1>(fun, p1); 00297 } 00298 00305 template <typename F, typename P1, typename P2> inline impl::scope_guard_impl_2<F, P1, P2> make_guard(F fun, P1 p1, P2 p2) 00306 { 00307 return impl::scope_guard_impl_2<F, P1, P2>(fun, p1, p2); 00308 } 00309 00316 template <typename F, typename P1, typename P2, typename P3> inline impl::scope_guard_impl_3<F, P1, P2, P3> make_guard(F fun, P1 p1, P2 p2, P3 p3) 00317 { 00318 return impl::scope_guard_impl_3<F, P1, P2, P3>(fun, p1, p2, p3); 00319 } 00320 00325 template <class Obj, typename MemFun> inline impl::obj_scope_guard_impl_0<Obj, MemFun> make_obj_guard(Obj& obj, MemFun memFun) 00326 { 00327 return impl::obj_scope_guard_impl_0<Obj, MemFun>(obj, memFun); 00328 } 00329 00336 template <class Obj, typename MemFun, typename P1> inline impl::obj_scope_guard_impl_1<Obj, MemFun, P1> make_obj_guard(Obj& obj, MemFun memFun, P1 p1) 00337 { 00338 return impl::obj_scope_guard_impl_1<Obj, MemFun, P1>(obj, memFun, p1); 00339 } 00340 00347 template <class Obj, typename MemFun, typename P1, typename P2> inline impl::obj_scope_guard_impl_2<Obj, MemFun, P1, P2> make_obj_guard(Obj& obj, MemFun memFun, P1 p1, P2 p2) 00348 { 00349 return impl::obj_scope_guard_impl_2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2); 00350 } 00351 00357 typedef const impl::scope_guard_impl_base& scope_guard; 00358 00360 00361 } // namespace 00362 00363 #endif