libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/base/throw.hpp
Go to the documentation of this file.
00001 
00015 /*
00016  *  Copyright (C) 2011 Juan Pedro BolĂ­var Puente
00017  *
00018  *  This file is part of Psychosynth.
00019  *   
00020  *  Psychosynth is free software: you can redistribute it and/or modify
00021  *  it under the terms of the GNU General Public License as published by
00022  *  the Free Software Foundation, either version 3 of the License, or
00023  *  (at your option) any later version.
00024  *
00025  *  Psychosynth is distributed in the hope that it will be useful,
00026  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00028  *  GNU General Public License for more details.
00029  *
00030  *  You should have received a copy of the GNU General Public License
00031  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00032  *
00033  */
00034 
00035 #ifndef PSYNTH_BASE_THROW_HPP_
00036 #define PSYNTH_BASE_THROW_HPP_
00037 
00038 #include <psynth/base/logger.hpp>
00039 #include <psynth/base/exception.hpp>
00040 
00041 namespace psynth
00042 {
00043 namespace base
00044 {
00045 
00046 namespace detail
00047 {
00048 
00049 template <class Base, bool IsPsynth>
00050 class exception_wrapper : public virtual Base
00051 {
00052 public:
00053     exception_wrapper (const char* where)
00054         : _where (where)
00055         , _stream (logger::self ().path (where))
00056     {
00057         _stream.set_level (Base::level ());
00058     }
00059 
00060     exception_wrapper (const exception_wrapper&) = default;
00061     exception_wrapper (exception_wrapper&&) = default;
00062     exception_wrapper& operator= (const exception_wrapper&) = default;
00063 
00064     ~exception_wrapper () throw () {}
00065     
00066     const char* where () const throw ()
00067     { return _where; }
00068 
00069     const char* what () const throw ()
00070     { return _stream.message ().c_str (); }
00071 
00072     int level () const throw ()
00073     { return _stream.level (); }
00074 
00075     log_stream_adapter& stream ()
00076     { return _stream; }
00077     
00078 private:
00079     const char*        _where;
00080     log_stream_adapter _stream;
00081 };
00082 
00083 template <class Base>
00084 class exception_wrapper<Base, false> : public virtual Base
00085                                      , public virtual exception
00086 {
00087 public:
00088     exception_wrapper (const char* where)
00089         : Base ("") // HACK: This allows throwing logic_error etc, but
00090                     // forbidds raw std::exception and others.
00091         , _where (where)
00092         , _stream (logger::self ().path (where))
00093     {
00094         _stream.set_level (default_error_level ());
00095     }
00096 
00097     exception_wrapper (const exception_wrapper&) = default;
00098     exception_wrapper (exception_wrapper&&) = default;
00099     exception_wrapper& operator= (const exception_wrapper&) = default;
00100 
00101     ~exception_wrapper () throw () {}
00102     
00103     const char* what () const throw ()
00104     { return _stream.message ().c_str (); }
00105 
00106     const char* where () const throw ()
00107     { return _where; }
00108     
00109     int level () const throw ()
00110     { return _stream.level (); }
00111 
00112     log_stream_adapter& stream ()
00113     { return _stream; }
00114     
00115 private:
00116     const char*        _where;
00117     log_stream_adapter _stream;
00118 };
00119 
00120 } /* namespace detail */
00121 
00122 template <class Exception>
00123 class throw_with : public boost::noncopyable
00124 {
00125 public:
00126     explicit throw_with (const char* where = "")
00127         : _exception (where)
00128         , _owner (false)
00129     {}
00130 
00131     throw_with (throw_with&& other)
00132         : _exception (std::move (other._exception))
00133         , _owner (true)
00134     {
00135         other._owner = false;
00136     }
00137     
00138     ~throw_with ()
00139     {
00140         if (_owner)
00141             throw _exception;
00142     }
00143 
00144 private:
00145     template <class E, typename T>
00146     friend throw_with<E> operator<< (throw_with<E>, const T&);
00147 
00148     typedef detail::exception_wrapper<
00149         Exception,
00150         std::is_base_of<exception, Exception>::value >
00151     exception_type;
00152 
00153     exception_type _exception;
00154     bool           _owner;
00155 };
00156 
00157 template <class E, typename T>
00158 throw_with<E> operator<< (throw_with<E> ts, const T& what)
00159 {
00160     ts._exception.stream () << what;
00161     return std::move (ts);
00162 }
00163 
00164 #define PSYNTH_THROW(exception) \
00165     ::psynth::base::throw_with<exception> (PSYNTH_MODULE_NAME)
00166 
00167 
00168 } /* namespace base */
00169 } /* namespace psynth */
00170 
00171 #endif /* PSYNTH_BASE_THROW_HPP_ */
00172 
00173