backtrace.cc

Go to the documentation of this file.
00001 
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: Wed Oct 13 16:33:19 2004
00010 // commit: $Id: backtrace.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/rutz/backtrace.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 //
00033 
00034 #ifndef GROOVX_RUTZ_BACKTRACE_CC_UTC20050626084019_DEFINED
00035 #define GROOVX_RUTZ_BACKTRACE_CC_UTC20050626084019_DEFINED
00036 
00037 #include "rutz/backtrace.h"
00038 
00039 #include "rutz/abort.h"
00040 #include "rutz/prof.h"
00041 
00042 #include <cstdio>  // for fprintf()
00043 #include <ostream>
00044 #include <pthread.h>
00045 
00046 namespace
00047 {
00048   // thread-local storage (see rutz::backtrace::current() below)
00049   pthread_key_t current_backtrace_key;
00050   pthread_once_t current_backtrace_key_once = PTHREAD_ONCE_INIT;
00051 
00052   void current_backtrace_destroy(void* bt)
00053   {
00054     delete static_cast<rutz::backtrace*>(bt);
00055   }
00056 
00057   void current_backtrace_key_alloc()
00058   {
00059     pthread_key_create(&current_backtrace_key,
00060                        &current_backtrace_destroy);
00061   }
00062 }
00063 
00065 //
00066 // rutz::backtrace member definitions
00067 //
00069 
00070 rutz::backtrace::backtrace() throw() :
00071   m_vec()
00072 {}
00073 
00074 rutz::backtrace::backtrace(const backtrace& other) throw() :
00075   m_vec(other.m_vec)
00076 {}
00077 
00078 rutz::backtrace& rutz::backtrace::operator=(const backtrace& other) throw()
00079 {
00080   m_vec = other.m_vec;
00081   return *this;
00082 }
00083 
00084 rutz::backtrace::~backtrace() throw()
00085 {}
00086 
00087 rutz::backtrace& rutz::backtrace::current() throw()
00088 {
00089   // we need one backtrace per thread, so we use pthreads thread-local
00090   // storage to set up that association
00091 
00092   pthread_once(&current_backtrace_key_once,
00093                &current_backtrace_key_alloc);
00094 
00095   void* const ptr = pthread_getspecific(current_backtrace_key);
00096 
00097   if (ptr != 0)
00098     {
00099       return *(static_cast<rutz::backtrace*>(ptr));
00100     }
00101 
00102   // else...
00103   rutz::backtrace* const bt = new (std::nothrow) rutz::backtrace;
00104 
00105   if (bt == 0)
00106     GVX_ABORT("memory allocation failed");
00107 
00108   pthread_setspecific(current_backtrace_key,
00109                       static_cast<void*>(bt));
00110 
00111   return *bt;
00112 }
00113 
00114 bool rutz::backtrace::push(rutz::prof* p) throw()
00115 {
00116   return m_vec.push(p);
00117 }
00118 
00119 void rutz::backtrace::pop() throw()
00120 {
00121   m_vec.pop();
00122 }
00123 
00124 unsigned int rutz::backtrace::size() const throw()
00125 {
00126   return m_vec.size();
00127 }
00128 
00129 rutz::prof* rutz::backtrace::top() const throw()
00130 {
00131   return m_vec.top();
00132 }
00133 
00134 rutz::prof* rutz::backtrace::at(unsigned int i) const throw()
00135 {
00136   return m_vec.at(i);
00137 }
00138 
00139 void rutz::backtrace::print() const throw()
00140 {
00141   const unsigned int end = size();
00142 
00143   if (end == 0)
00144     return; // don't print anything if we have an empty backtrace
00145 
00146   fprintf(stderr, "stack trace:\n");
00147 
00148   unsigned int i = 0;
00149   unsigned int ri = end-1;
00150 
00151   for (; i < end; ++i, --ri)
00152     {
00153       fprintf(stderr, "\t[%d] %s\n", int(i),
00154               m_vec.at(ri)->context_name());
00155     }
00156 }
00157 
00158 void rutz::backtrace::print(std::ostream& os) const throw()
00159 {
00160   const unsigned int end = size();
00161 
00162   if (end == 0)
00163     return; // don't print anything if we have an empty backtrace
00164 
00165   os.exceptions(std::ios::goodbit);
00166 
00167   os << "stack trace:\n";
00168 
00169   unsigned int i = 0;
00170   unsigned int ri = end-1;
00171 
00172   for (; i < end; ++i, --ri)
00173     {
00174       os << "\t[" << i << "] "
00175          << m_vec.at(ri)->context_name() << '\n';
00176     }
00177 
00178   os << std::flush;
00179 }
00180 
00181 static const char __attribute__((used)) vcid_groovx_rutz_backtrace_cc_utc20050626084019[] = "$Id: backtrace.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00182 #endif // !GROOVX_RUTZ_BACKTRACE_CC_UTC20050626084019_DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:40 2008 by Doxygen version 1.5.5.