lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
scope_guard.h
00001 /*****************************************************/
00002 /* lean Smart                   (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_SMART_SCOPE_GUARD
00006 #define LEAN_SMART_SCOPE_GUARD
00007 
00008 #include "../lean.h"
00009 #include "../tags/noncopyable.h"
00010 #include "../functional/callable.h"
00011 
00012 namespace lean
00013 {
00014 namespace smart
00015 {
00016 
00018 class scope_annex_base : public nonassignable
00019 {
00020 private:
00021     mutable bool m_valid;
00022 
00023 protected:
00025     LEAN_INLINE scope_annex_base()
00026         : m_valid(true) { }
00028     LEAN_INLINE scope_annex_base(const scope_annex_base &right)
00029         : m_valid(true)
00030     {
00031         right.m_valid = false;
00032     }
00033     LEAN_INLINE ~scope_annex_base() throw() { }
00034 
00036     LEAN_INLINE bool valid() const { return m_valid; }
00037 };
00038 
00040 template <class Callable>
00041 class scope_annex_impl : public scope_annex_base
00042 {
00043 private:
00044     Callable m_callable;
00045 
00046 public:
00048     LEAN_INLINE explicit scope_annex_impl(const Callable &callable)
00049         : m_callable(callable) { }
00051     LEAN_INLINE ~scope_annex_impl()
00052     {
00053         if (valid())
00054             m_callable();
00055     }
00056 };
00057 
00059 typedef const scope_annex_base& scope_annex;
00060 
00062 template <class Callable>
00063 LEAN_INLINE scope_annex_impl<Callable> make_scope_annex(const Callable& callable)
00064 {
00065     return scope_annex_impl<Callable>(callable);
00066 }
00067 
00069 template <class Signature>
00070 LEAN_INLINE scope_annex_impl< callable_fun<Signature> > make_scope_annex(Signature *fun)
00071 {
00072     return make_scope_annex( make_callable(fun) );
00073 }
00074 
00076 template <class Class, class Signature>
00077 LEAN_INLINE scope_annex_impl< callable_memfun<Class, Signature> > make_scope_annex(Class *obj, Signature Class::*fun)
00078 {
00079     return make_scope_annex( make_callable(obj, fun) );
00080 }
00081 
00083 class scope_guard_base : public nonassignable
00084 {
00085 private:
00086     mutable bool m_armed;
00087 
00088 protected:
00090     LEAN_INLINE explicit scope_guard_base(bool arm = true)
00091         : m_armed(arm) { }
00093     LEAN_INLINE scope_guard_base(const scope_guard_base &right)
00094         : m_armed(right.m_armed)
00095     {
00096         right.disarm();
00097     }
00098     LEAN_INLINE ~scope_guard_base() throw() { }
00099 
00100 public:
00102     LEAN_INLINE void armed(bool arm) const { m_armed = arm; }
00104     LEAN_INLINE bool armed() const { return m_armed; }
00105 
00107     LEAN_INLINE void disarm() const { armed(false); }
00109     LEAN_INLINE void arm() const { armed(true); }
00110 };
00111 
00113 typedef const scope_guard_base& scope_guard;
00114 
00116 template <class Callable>
00117 class scope_guard_impl : public scope_guard_base
00118 {
00119 private:
00120     Callable m_callable;
00121 
00122 public:
00124     LEAN_INLINE explicit scope_guard_impl(const Callable &callable, bool arm = true)
00125         : scope_guard_base(arm),
00126         m_callable(callable) { }
00128     LEAN_INLINE ~scope_guard_impl()
00129     {
00130         if (armed())
00131             m_callable();
00132     }
00133 };
00134 
00136 template <class Callable>
00137 LEAN_INLINE scope_guard_impl<Callable> make_scope_guard(const Callable& callable)
00138 {
00139     return scope_guard_impl<Callable>(callable);
00140 }
00141 
00143 template <class Signature>
00144 LEAN_INLINE scope_guard_impl< callable_fun<Signature> > make_scope_guard(Signature *fun)
00145 {
00146     return make_scope_guard( make_callable(fun) );
00147 }
00148 
00150 template <class Class, class Signature>
00151 LEAN_INLINE scope_guard_impl< callable_memfun<Class, Signature> > make_scope_guard(Class *obj, Signature Class::*fun)
00152 {
00153     return make_scope_guard( make_callable(obj, fun) );
00154 }
00155 
00156 } // namespace
00157 
00158 using smart::scope_annex;
00159 using smart::make_scope_annex;
00160 
00161 using smart::scope_guard;
00162 using smart::make_scope_guard;
00163 
00164 } // namespace
00165 
00166 #endif