libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/base/scope_guard.hpp
Go to the documentation of this file.
00001 
00018 /*
00019  *  Copyright (C) 2011 Juan Pedro BolĂ­var Puente
00020  *
00021  *  This file is part of Psychosynth.
00022  *   
00023  *  Psychosynth is free software: you can redistribute it and/or modify
00024  *  it under the terms of the GNU General Public License as published by
00025  *  the Free Software Foundation, either version 3 of the License, or
00026  *  (at your option) any later version.
00027  *
00028  *  Psychosynth is distributed in the hope that it will be useful,
00029  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00030  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00031  *  GNU General Public License for more details.
00032  *
00033  *  You should have received a copy of the GNU General Public License
00034  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00035  *
00036  */
00037 
00038 #ifndef PSYNTH_BASE_SCOPE_GUARD_H_
00039 #define PSYNTH_BASE_SCOPE_GUARD_H_
00040 
00041 #include <boost/utility.hpp>
00042 #include <psynth/base/util.hpp>
00043 
00044 namespace psynth
00045 {
00046 namespace base
00047 {
00048  
00049 class scope_guard_impl_base : public boost::noncopyable
00050 {
00051 public:
00052     void dismiss () const throw()
00053     { _dismissed = true; }
00054 
00055 protected:
00056     scope_guard_impl_base ()
00057         : _dismissed (false) {}
00058 
00059     scope_guard_impl_base (scope_guard_impl_base&& other)
00060         : _dismissed (other._dismissed)
00061     { other.dismiss (); }
00062     
00063     ~scope_guard_impl_base () {} // nonvirtual to allow polymorphic
00064                                  // behaviour. read the alexandrescu
00065                                  // article for details.
00066     
00067     mutable bool _dismissed;
00068 };
00069 
00070 template <typename Fun>
00071 class scope_guard_impl : public scope_guard_impl_base
00072 {
00073     typedef scope_guard_impl_base base;
00074 public:
00075     scope_guard_impl (const Fun& fun)
00076         : _fun (fun) {}
00077 
00078     scope_guard_impl (scope_guard_impl&& other)
00079         : base (std::move (other)) // TODO: Why is this needed?
00080         , _fun (other._fun)
00081     {}
00082     
00083     ~scope_guard_impl ()
00084     {
00085         if (!_dismissed)
00086             try { _fun (); } catch (...) { /* TODO: Handle error? */ }
00087     }
00088     
00089 private:
00090     Fun _fun;
00091 };
00092 
00093 template <typename Fun>
00094 scope_guard_impl<Fun> make_guard (const Fun& fun)
00095 {
00096     return scope_guard_impl<Fun> (fun);
00097 }
00098 
00099 typedef const scope_guard_impl_base& scope_guard;
00100 
00101 #define PSYNTH_CONCATENATE_DIRECT(s1, s2)  s1##s2
00102 #define PSYNTH_CONCATENATE(s1, s2)         PSYNTH_CONCATENATE_DIRECT(s1, s2)
00103 #define PSYNTH_ANONYMOUS_VARIABLE(str)     PSYNTH_CONCATENATE(str, __LINE__)
00104 
00105 #define PSYNTH_ON_BLOCK_EXIT(f)                                         \
00106     ::psynth::base::scope_guard PSYNTH_ANONYMOUS_VARIABLE(scope_guard) = ::psynth::base::make_guard(f); ::psynth::base::ignore_unused_variable_warning (PSYNTH_ANONYMOUS_VARIABLE(scope_guard)) 
00107 
00108 } /* namespace base */
00109 } /* namespace psynth */
00110 
00111 #endif /* PSYNTH_BASE_SCOPE_GUARD_H_ */