blocxx

ScopeGuard.hpp

Go to the documentation of this file.
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