00001 /** @file rutz/error.cc exception base class, derives from 00002 std::exception */ 00003 /////////////////////////////////////////////////////////////////////// 00004 // 00005 // Copyright (c) 1999-2004 California Institute of Technology 00006 // Copyright (c) 2004-2007 University of Southern California 00007 // Rob Peters <rjpeters at usc dot edu> 00008 // 00009 // created: Tue Jun 22 14:59:48 1999 00010 // commit: $Id: error.cc 12074 2009-11-24 07:51:51Z itti $ 00011 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/error.cc $ 00012 // 00013 // -------------------------------------------------------------------- 00014 // 00015 // This file is part of GroovX. 00016 // [http://ilab.usc.edu/rjpeters/groovx/] 00017 // 00018 // GroovX is free software; you can redistribute it and/or modify it 00019 // under the terms of the GNU General Public License as published by 00020 // the Free Software Foundation; either version 2 of the License, or 00021 // (at your option) any later version. 00022 // 00023 // GroovX is distributed in the hope that it will be useful, but 00024 // WITHOUT ANY WARRANTY; without even the implied warranty of 00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00026 // General Public License for more details. 00027 // 00028 // You should have received a copy of the GNU General Public License 00029 // along with GroovX; if not, write to the Free Software Foundation, 00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00031 // 00032 /////////////////////////////////////////////////////////////////////// 00033 00034 #ifndef GROOVX_RUTZ_ERROR_CC_UTC20050626084020_DEFINED 00035 #define GROOVX_RUTZ_ERROR_CC_UTC20050626084020_DEFINED 00036 00037 #include "rutz/error.h" 00038 00039 #include "rutz/backtrace.h" 00040 #include "rutz/error_context.h" 00041 #include "rutz/fstring.h" 00042 #include "rutz/mutex.h" 00043 00044 #include <cmath> 00045 #include <cstdlib> 00046 #include <new> 00047 #include <pthread.h> 00048 #include <cstdio> 00049 00050 #include "rutz/trace.h" 00051 #include "rutz/debug.h" 00052 GVX_DBG_REGISTER 00053 00054 namespace 00055 { 00056 rutz::backtrace* g_last_backtrace = 0; 00057 pthread_mutex_t g_last_backtrace_mutex = PTHREAD_MUTEX_INITIALIZER; 00058 } 00059 00060 rutz::error::error(const rutz::file_pos& pos) : 00061 std::exception(), 00062 m_msg(), 00063 m_context(rutz::error_context::current().get_text()), 00064 m_file_pos(pos), 00065 m_backtrace(new rutz::backtrace(rutz::backtrace::current())) 00066 { 00067 GVX_TRACE("rutz::error::error()"); 00068 00069 dbg_dump(4, m_msg); 00070 00071 { 00072 GVX_MUTEX_LOCK(&g_last_backtrace_mutex); 00073 00074 if (g_last_backtrace == 0) 00075 g_last_backtrace = new rutz::backtrace(*m_backtrace); 00076 else 00077 *g_last_backtrace = *m_backtrace; 00078 } 00079 00080 if (GVX_DBG_LEVEL() >= 4) 00081 { 00082 m_backtrace->print(); 00083 } 00084 } 00085 00086 rutz::error::error(const rutz::fstring& msg, 00087 const rutz::file_pos& pos) : 00088 std::exception(), 00089 m_msg(msg), 00090 m_context(rutz::error_context::current().get_text()), 00091 m_file_pos(pos), 00092 m_backtrace(new rutz::backtrace(rutz::backtrace::current())) 00093 { 00094 GVX_TRACE("rutz::error::error(fstring)"); 00095 00096 dbg_dump(4, m_msg); 00097 00098 { 00099 GVX_MUTEX_LOCK(&g_last_backtrace_mutex); 00100 00101 if (g_last_backtrace == 0) 00102 g_last_backtrace = new rutz::backtrace(*m_backtrace); 00103 else 00104 *g_last_backtrace = *m_backtrace; 00105 } 00106 00107 if (GVX_DBG_LEVEL() >= 4) 00108 { 00109 m_backtrace->print(); 00110 } 00111 } 00112 00113 rutz::error::error(const rutz::error& other) throw() : 00114 std::exception(other), 00115 m_msg(other.m_msg), 00116 m_context(other.m_context), 00117 m_file_pos(other.m_file_pos), 00118 m_backtrace(0) 00119 { 00120 GVX_TRACE("rutz::error::error(copy)"); 00121 00122 dbg_dump(4, m_msg); 00123 00124 if (other.m_backtrace != 0) 00125 m_backtrace = 00126 new (std::nothrow) rutz::backtrace(*other.m_backtrace); 00127 } 00128 00129 rutz::error::~error() throw() 00130 { 00131 GVX_TRACE("rutz::error::~error"); 00132 delete m_backtrace; 00133 } 00134 00135 const char* rutz::error::what() const throw() 00136 { 00137 if (m_what.length() == 0) 00138 { 00139 // we don't use rutz::sfmt() here to generate the fstring, 00140 // because then we'd have a cyclic dependency between 00141 // rutz/sfmt.cc and rutz/error.cc 00142 00143 const size_t len = 00144 strlen(m_file_pos.m_file_name) 00145 + 2 + size_t(ceil(log10(m_file_pos.m_line_no))) 00146 + m_msg.length() 00147 + 1; 00148 00149 char buf[len]; 00150 00151 if (snprintf(&buf[0], len, "at %s:%d:\n%s", 00152 m_file_pos.m_file_name, 00153 m_file_pos.m_line_no, m_msg.c_str()) < 0) 00154 { 00155 m_what = m_msg; 00156 } 00157 else 00158 { 00159 m_what = rutz::fstring(&buf[0]); 00160 } 00161 } 00162 00163 return m_what.c_str(); 00164 } 00165 00166 void rutz::error::get_last_backtrace(rutz::backtrace& dst) 00167 { 00168 GVX_MUTEX_LOCK(&g_last_backtrace_mutex); 00169 00170 if (g_last_backtrace == 0) 00171 g_last_backtrace = new rutz::backtrace(); 00172 00173 dst = *g_last_backtrace; 00174 } 00175 00176 static const char __attribute__((used)) vcid_groovx_rutz_error_cc_utc20050626084020[] = "$Id: error.cc 12074 2009-11-24 07:51:51Z itti $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/error.cc $"; 00177 #endif // !GROOVX_RUTZ_ERROR_CC_UTC20050626084020_DEFINED