ScopeGuard.hpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2005 Novell, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Novell, Inc., nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Novell, Inc., OR THE 
00022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00025 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00027 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00028 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00031 /*
00032     Acknowledgements: this header is heavily based on ScopeGuard.h by Andrei 
00033    Alexandrescu and Petru Marginean publishedin December 2000 issue of C/C++ 
00034    Users Journal:
00035    http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/alexandr.htm
00036 
00037    The only modification from the original form are the following:
00038    - Inclusion in the BLOCXX_NAMESPACE
00039    - function/method/member variable renaming to comply with the blocxx
00040      coding guidelines.
00041 */
00042 
00043 #ifndef BLOCXX_SCOPEGUARD_HPP_
00044 #define BLOCXX_SCOPEGUARD_HPP_
00045 
00046 namespace BLOCXX_NAMESPACE
00047 {
00048 
00050 template <class T>
00051 class RefHolder
00052 {
00053    T& ref_;
00054 public:
00055    RefHolder(T& ref) : ref_(ref) {}
00056    operator T& () const 
00057    {
00058       return ref_;
00059    }
00060 private:
00061     // Disable assignment - not implemented
00062     RefHolder& operator=(const RefHolder&);
00063 };
00064 
00065 template <class T>
00066 inline RefHolder<T> 
00067 byRef(T& t)
00068 {
00069    return RefHolder<T>(t);
00070 }
00071 
00073 class ScopeGuardImplBase
00074 {
00075    ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
00076 protected:
00077    ~ScopeGuardImplBase()
00078    {
00079    }
00080    ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() 
00081       : m_dismissed(other.m_dismissed)
00082    {
00083       other.dismiss();
00084    }
00085    template <typename J>
00086    static void safeExecute(J& j) throw() 
00087    {
00088       if (!j.m_dismissed)
00089          try
00090          {
00091             j.execute();
00092          }
00093          catch(...)
00094          {
00095          }
00096    }
00097    
00098    mutable bool m_dismissed;
00099 public:
00100    ScopeGuardImplBase() throw() : m_dismissed(false) 
00101    {
00102    }
00103    void dismiss() const throw() 
00104    {
00105       m_dismissed = true;
00106    }
00107 };
00108 
00109 typedef const ScopeGuardImplBase& ScopeGuard;
00110 
00112 template <typename F>
00113 class ScopeGuardImpl0 : public ScopeGuardImplBase
00114 {
00115 public:
00116    static ScopeGuardImpl0<F> makeGuard(F fun)
00117    {
00118       return ScopeGuardImpl0<F>(fun);
00119    }
00120    ~ScopeGuardImpl0() throw() 
00121    {
00122       safeExecute(*this);
00123    }
00124    void execute() 
00125    {
00126       fun_();
00127    }
00128 protected:
00129    ScopeGuardImpl0(F fun) : fun_(fun) 
00130    {
00131    }
00132    F fun_;
00133 };
00134 
00135 template <typename F> 
00136 inline ScopeGuardImpl0<F> 
00137 makeGuard(F fun)
00138 {
00139    return ScopeGuardImpl0<F>::makeGuard(fun);
00140 }
00141 
00143 template <typename F, typename P1>
00144 class ScopeGuardImpl1 : public ScopeGuardImplBase
00145 {
00146 public:
00147    static ScopeGuardImpl1<F, P1> makeGuard(F fun, P1 p1)
00148    {
00149       return ScopeGuardImpl1<F, P1>(fun, p1);
00150    }
00151    ~ScopeGuardImpl1() throw() 
00152    {
00153       safeExecute(*this);
00154    }
00155    void execute()
00156    {
00157       fun_(m_p1);
00158    }
00159 protected:
00160    ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), m_p1(p1) 
00161    {
00162    }
00163    F fun_;
00164    const P1 m_p1;
00165 };
00166 
00167 template <typename F, typename P1> 
00168 inline ScopeGuardImpl1<F, P1> 
00169 makeGuard(F fun, P1 p1)
00170 {
00171    return ScopeGuardImpl1<F, P1>::makeGuard(fun, p1);
00172 }
00173 
00175 template <typename F, typename P1, typename P2>
00176 class ScopeGuardImpl2: public ScopeGuardImplBase
00177 {
00178 public:
00179    static ScopeGuardImpl2<F, P1, P2> makeGuard(F fun, P1 p1, P2 p2)
00180    {
00181       return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
00182    }
00183    ~ScopeGuardImpl2() throw() 
00184    {
00185       safeExecute(*this);
00186    }
00187    void execute()
00188    {
00189       fun_(m_p1, m_p2);
00190    }
00191 protected:
00192    ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), m_p1(p1), m_p2(p2) 
00193    {
00194    }
00195    F fun_;
00196    const P1 m_p1;
00197    const P2 m_p2;
00198 };
00199 
00200 template <typename F, typename P1, typename P2>
00201 inline ScopeGuardImpl2<F, P1, P2> 
00202 makeGuard(F fun, P1 p1, P2 p2)
00203 {
00204    return ScopeGuardImpl2<F, P1, P2>::makeGuard(fun, p1, p2);
00205 }
00206 
00208 template <typename F, typename P1, typename P2, typename P3>
00209 class ScopeGuardImpl3 : public ScopeGuardImplBase
00210 {
00211 public:
00212    static ScopeGuardImpl3<F, P1, P2, P3> makeGuard(F fun, P1 p1, P2 p2, P3 p3)
00213    {
00214       return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
00215    }
00216    ~ScopeGuardImpl3() throw() 
00217    {
00218       safeExecute(*this);
00219    }
00220    void execute()
00221    {
00222       fun_(m_p1, m_p2, m_p3);
00223    }
00224 protected:
00225    ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), m_p1(p1), m_p2(p2), m_p3(p3) 
00226    {
00227    }
00228    F fun_;
00229    const P1 m_p1;
00230    const P2 m_p2;
00231    const P3 m_p3;
00232 };
00233 
00234 template <typename F, typename P1, typename P2, typename P3>
00235 inline ScopeGuardImpl3<F, P1, P2, P3> 
00236 makeGuard(F fun, P1 p1, P2 p2, P3 p3)
00237 {
00238    return ScopeGuardImpl3<F, P1, P2, P3>::makeGuard(fun, p1, p2, p3);
00239 }
00240 
00242 template <class Obj, typename MemFun>
00243 class ObjScopeGuardImpl0 : public ScopeGuardImplBase
00244 {
00245 public:
00246    static ObjScopeGuardImpl0<Obj, MemFun> makeObjGuard(Obj& obj, MemFun memFun)
00247    {
00248       return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
00249    }
00250    ~ObjScopeGuardImpl0() throw() 
00251    {
00252       safeExecute(*this);
00253    }
00254    void execute() 
00255    {
00256       (m_obj.*m_memFun)();
00257    }
00258 protected:
00259    ObjScopeGuardImpl0(Obj& obj, MemFun memFun) 
00260       : m_obj(obj), m_memFun(memFun) {}
00261    Obj& m_obj;
00262    MemFun m_memFun;
00263 };
00264 
00265 template <class Obj, typename MemFun>
00266 inline ObjScopeGuardImpl0<Obj, MemFun> 
00267 makeObjGuard(Obj& obj, MemFun memFun)
00268 {
00269    return ObjScopeGuardImpl0<Obj, MemFun>::makeObjGuard(obj, memFun);
00270 }
00271 
00273 template <class Obj, typename MemFun, typename P1>
00274 class ObjScopeGuardImpl1 : public ScopeGuardImplBase
00275 {
00276 public:
00277    static ObjScopeGuardImpl1<Obj, MemFun, P1> makeObjGuard(Obj& obj, MemFun memFun, P1 p1)
00278    {
00279       return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
00280    }
00281    ~ObjScopeGuardImpl1() throw() 
00282    {
00283       safeExecute(*this);
00284    }
00285    void execute() 
00286    {
00287       (m_obj.*m_memFun)(m_p1);
00288    }
00289 protected:
00290    ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) 
00291       : m_obj(obj), m_memFun(memFun), m_p1(p1) {}
00292    Obj& m_obj;
00293    MemFun m_memFun;
00294    const P1 m_p1;
00295 };
00296 
00297 template <class Obj, typename MemFun, typename P1>
00298 inline ObjScopeGuardImpl1<Obj, MemFun, P1> 
00299 makeObjGuard(Obj& obj, MemFun memFun, P1 p1)
00300 {
00301    return ObjScopeGuardImpl1<Obj, MemFun, P1>::makeObjGuard(obj, memFun, p1);
00302 }
00303 
00305 template <class Obj, typename MemFun, typename P1, typename P2>
00306 class ObjScopeGuardImpl2 : public ScopeGuardImplBase
00307 {
00308 public:
00309    static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> makeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00310    {
00311       return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
00312    }
00313    ~ObjScopeGuardImpl2() throw() 
00314    {
00315       safeExecute(*this);
00316    }
00317    void execute() 
00318    {
00319       (m_obj.*m_memFun)(m_p1, m_p2);
00320    }
00321 protected:
00322    ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) 
00323       : m_obj(obj), m_memFun(memFun), m_p1(p1), m_p2(p2) {}
00324    Obj& m_obj;
00325    MemFun m_memFun;
00326    const P1 m_p1;
00327    const P2 m_p2;
00328 };
00329 
00330 template <class Obj, typename MemFun, typename P1, typename P2>
00331 inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> 
00332 makeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00333 {
00334    return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::makeObjGuard(obj, memFun, p1, p2);
00335 }
00336 
00337 #define CONCATENATE_DIRECT(s1, s2) s1##s2
00338 #define CONCATENATE(s1, s2) CONCATENATE_DIRECT(s1, s2)
00339 #define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__)
00340 
00341 #define ON_BLOCK_EXIT ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = makeGuard
00342 #define ON_BLOCK_EXIT_OBJ ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = makeObjGuard
00343 
00344 }  // End of BLOCXX_NAMESPACE
00345 
00346 #endif //SCOPEGUARD_H_

Generated on Fri Jun 16 15:39:08 2006 for blocxx by  doxygen 1.4.6