blocxx
|
00001 /******************************************************************************* 00002 * Copyright (C) 2005, Quest Software, Inc. All rights reserved. 00003 * Copyright (C) 2006, Novell, Inc. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of 00014 * Quest Software, Inc., 00015 * nor Novell, Inc., 00016 * nor the names of its contributors or employees may be used to 00017 * endorse or promote products derived from this software without 00018 * specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00030 * POSSIBILITY OF SUCH DAMAGE. 00031 *******************************************************************************/ 00032 00034 // The Loki Library 00035 // Copyright (c) 2000 Andrei Alexandrescu 00036 // Copyright (c) 2000 Petru Marginean 00037 // Copyright (c) 2005 Joshua Lehrer 00038 // 00039 // Permission to use, copy, modify, distribute and sell this software for any 00040 // purpose is hereby granted without fee, provided that the above copyright 00041 // notice appear in all copies and that both that copyright notice and this 00042 // permission notice appear in supporting documentation. 00043 // The author makes no representations about the 00044 // suitability of this software for any purpose. It is provided "as is" 00045 // without express or implied warranty. 00047 #ifndef BLOCXX_SCOPE_GUARD_HPP_INCLUDE_GUARD_ 00048 #define BLOCXX_SCOPE_GUARD_HPP_INCLUDE_GUARD_ 00049 00050 #include "blocxx/BLOCXX_config.h" 00051 #include "blocxx/RefToValue.hpp" 00052 00053 namespace BLOCXX_NAMESPACE 00054 { 00055 00056 class ScopeGuardImplBase 00057 { 00058 ScopeGuardImplBase& operator =(const ScopeGuardImplBase&); 00059 00060 protected: 00061 00062 ~ScopeGuardImplBase() 00063 {} 00064 00065 ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() 00066 : m_dismissed(other.m_dismissed) 00067 { 00068 other.dismiss(); 00069 } 00070 00071 template <typename J> 00072 static void safeExecute(J& j) throw() 00073 { 00074 if (!j.m_dismissed) 00075 try 00076 { 00077 j.execute(); 00078 } 00079 catch(...) 00080 {} 00081 } 00082 00083 mutable bool m_dismissed; 00084 00085 public: 00086 ScopeGuardImplBase() throw() : m_dismissed(false) 00087 {} 00088 00089 void dismiss() const throw() 00090 { 00091 m_dismissed = true; 00092 } 00093 }; 00094 00105 00106 typedef const ScopeGuardImplBase& ScopeGuard; 00107 00108 template <typename F> 00109 class ScopeGuardImpl0 : public ScopeGuardImplBase 00110 { 00111 public: 00112 static ScopeGuardImpl0<F> makeGuard(F fun) 00113 { 00114 return ScopeGuardImpl0<F>(fun); 00115 } 00116 00117 ~ScopeGuardImpl0() throw() 00118 { 00119 safeExecute(*this); 00120 } 00121 00122 void execute() 00123 { 00124 m_fun(); 00125 } 00126 00127 protected: 00128 ScopeGuardImpl0(F fun) : m_fun(fun) 00129 {} 00130 00131 F m_fun; 00132 }; 00133 00134 template <typename F> 00135 inline ScopeGuardImpl0<F> makeGuard(F fun) 00136 { 00137 return ScopeGuardImpl0<F>::makeGuard(fun); 00138 } 00139 00140 template <typename F, typename P1> 00141 class ScopeGuardImpl1 : public ScopeGuardImplBase 00142 { 00143 public: 00144 static ScopeGuardImpl1<F, P1> makeGuard(F fun, P1 p1) 00145 { 00146 return ScopeGuardImpl1<F, P1>(fun, p1); 00147 } 00148 00149 ~ScopeGuardImpl1() throw() 00150 { 00151 safeExecute(*this); 00152 } 00153 00154 void execute() 00155 { 00156 m_fun(m_p1); 00157 } 00158 00159 protected: 00160 ScopeGuardImpl1(F fun, P1 p1) : m_fun(fun), m_p1(p1) 00161 {} 00162 00163 F m_fun; 00164 const P1 m_p1; 00165 }; 00166 00167 template <typename F, typename P1> 00168 inline ScopeGuardImpl1<F, P1> makeGuard(F fun, P1 p1) 00169 { 00170 return ScopeGuardImpl1<F, P1>::makeGuard(fun, p1); 00171 } 00172 00173 template <typename F, typename P1, typename P2> 00174 class ScopeGuardImpl2: public ScopeGuardImplBase 00175 { 00176 public: 00177 static ScopeGuardImpl2<F, P1, P2> makeGuard(F fun, P1 p1, P2 p2) 00178 { 00179 return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2); 00180 } 00181 00182 ~ScopeGuardImpl2() throw() 00183 { 00184 safeExecute(*this); 00185 } 00186 00187 void execute() 00188 { 00189 m_fun(m_p1, m_p2); 00190 } 00191 00192 protected: 00193 ScopeGuardImpl2(F fun, P1 p1, P2 p2) : m_fun(fun), m_p1(p1), m_p2(p2) 00194 {} 00195 00196 F m_fun; 00197 const P1 m_p1; 00198 const P2 m_p2; 00199 }; 00200 00201 template <typename F, typename P1, typename P2> 00202 inline ScopeGuardImpl2<F, P1, P2> makeGuard(F fun, P1 p1, P2 p2) 00203 { 00204 return ScopeGuardImpl2<F, P1, P2>::makeGuard(fun, p1, p2); 00205 } 00206 00207 template <typename F, typename P1, typename P2, typename P3> 00208 class ScopeGuardImpl3 : public ScopeGuardImplBase 00209 { 00210 public: 00211 static ScopeGuardImpl3<F, P1, P2, P3> makeGuard(F fun, P1 p1, P2 p2, P3 p3) 00212 { 00213 return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3); 00214 } 00215 00216 ~ScopeGuardImpl3() throw() 00217 { 00218 safeExecute(*this); 00219 } 00220 00221 void execute() 00222 { 00223 m_fun(m_p1, m_p2, m_p3); 00224 } 00225 00226 protected: 00227 ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : m_fun(fun), m_p1(p1), m_p2(p2), m_p3(p3) 00228 {} 00229 00230 F m_fun; 00231 const P1 m_p1; 00232 const P2 m_p2; 00233 const P3 m_p3; 00234 }; 00235 00236 template <typename F, typename P1, typename P2, typename P3> 00237 inline ScopeGuardImpl3<F, P1, P2, P3> makeGuard(F fun, P1 p1, P2 p2, P3 p3) 00238 { 00239 return ScopeGuardImpl3<F, P1, P2, P3>::makeGuard(fun, p1, p2, p3); 00240 } 00241 00242 //************************************************************ 00243 00244 template <class Obj, typename MemFun> 00245 class ObjScopeGuardImpl0 : public ScopeGuardImplBase 00246 { 00247 public: 00248 static ObjScopeGuardImpl0<Obj, MemFun> makeObjGuard(Obj& obj, MemFun memFun) 00249 { 00250 return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun); 00251 } 00252 00253 ~ObjScopeGuardImpl0() throw() 00254 { 00255 safeExecute(*this); 00256 } 00257 00258 void execute() 00259 { 00260 (m_obj.*m_memFun)(); 00261 } 00262 00263 protected: 00264 ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : m_obj(obj), m_memFun(memFun) 00265 {} 00266 00267 Obj& m_obj; 00268 MemFun m_memFun; 00269 }; 00270 00271 template <class Obj, typename MemFun> 00272 inline ObjScopeGuardImpl0<Obj, MemFun> makeObjGuard(Obj& obj, MemFun memFun) 00273 { 00274 return ObjScopeGuardImpl0<Obj, MemFun>::makeObjGuard(obj, memFun); 00275 } 00276 00277 template <typename Ret, class Obj1, class Obj2> 00278 inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> makeGuard(Ret(Obj2::*memFun)(), Obj1 &obj) 00279 { 00280 return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::makeObjGuard(obj,memFun); 00281 } 00282 00283 template <typename Ret, class Obj1, class Obj2> 00284 inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> makeGuard(Ret(Obj2::*memFun)(), Obj1 *obj) 00285 { 00286 return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::makeObjGuard(*obj,memFun); 00287 } 00288 00289 template <class Obj, typename MemFun, typename P1> 00290 class ObjScopeGuardImpl1 : public ScopeGuardImplBase 00291 { 00292 public: 00293 static ObjScopeGuardImpl1<Obj, MemFun, P1> makeObjGuard(Obj& obj, MemFun memFun, P1 p1) 00294 { 00295 return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1); 00296 } 00297 00298 ~ObjScopeGuardImpl1() throw() 00299 { 00300 safeExecute(*this); 00301 } 00302 00303 void execute() 00304 { 00305 (m_obj.*m_memFun)(m_p1); 00306 } 00307 00308 protected: 00309 ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : m_obj(obj), m_memFun(memFun), m_p1(p1) 00310 {} 00311 00312 Obj& m_obj; 00313 MemFun m_memFun; 00314 const P1 m_p1; 00315 }; 00316 00317 template <class Obj, typename MemFun, typename P1> 00318 inline ObjScopeGuardImpl1<Obj, MemFun, P1> makeObjGuard(Obj& obj, MemFun memFun, P1 p1) 00319 { 00320 return ObjScopeGuardImpl1<Obj, MemFun, P1>::makeObjGuard(obj, memFun, p1); 00321 } 00322 00323 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b> 00324 inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> makeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1) 00325 { 00326 return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::makeObjGuard(obj,memFun,p1); 00327 } 00328 00329 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b> 00330 inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> makeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1) 00331 { 00332 return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::makeObjGuard(*obj,memFun,p1); 00333 } 00334 00335 template <class Obj, typename MemFun, typename P1, typename P2> 00336 class ObjScopeGuardImpl2 : public ScopeGuardImplBase 00337 { 00338 public: 00339 static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> makeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) 00340 { 00341 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2); 00342 } 00343 00344 ~ObjScopeGuardImpl2() throw() 00345 { 00346 safeExecute(*this); 00347 } 00348 00349 void execute() 00350 { 00351 (m_obj.*m_memFun)(m_p1, m_p2); 00352 } 00353 00354 protected: 00355 ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : m_obj(obj), m_memFun(memFun), m_p1(p1), m_p2(p2) 00356 {} 00357 00358 Obj& m_obj; 00359 MemFun m_memFun; 00360 const P1 m_p1; 00361 const P2 m_p2; 00362 }; 00363 00364 template <class Obj, typename MemFun, typename P1, typename P2> 00365 inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> makeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) 00366 { 00367 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::makeObjGuard(obj, memFun, p1, p2); 00368 } 00369 00370 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b> 00371 inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> makeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2) 00372 { 00373 return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::makeObjGuard(obj,memFun,p1,p2); 00374 } 00375 00376 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b> 00377 inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> makeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2) 00378 { 00379 return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::makeObjGuard(*obj,memFun,p1,p2); 00380 } 00381 00382 } // namespace BLOCXX_NAMESPACE 00383 00384 #define BLOCXX_CONCATENATE_DIRECT(s1, s2) s1##s2 00385 #define BLOCXX_CONCATENATE(s1, s2) BLOCXX_CONCATENATE_DIRECT(s1, s2) 00386 #define BLOCXX_ANONYMOUS_VARIABLE(str) BLOCXX_CONCATENATE(str, __LINE__) 00387 00388 #define BLOCXX_ON_BLOCK_EXIT blocxx::ScopeGuard BLOCXX_ANONYMOUS_VARIABLE(scopeGuard) = blocxx::makeGuard 00389 #define BLOCXX_ON_BLOCK_EXIT_OBJ blocxx::ScopeGuard BLOCXX_ANONYMOUS_VARIABLE(scopeGuard) = blocxx::makeObjGuard 00390 00391 #endif 00392