error_context.cc

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 2005-2007 University of Southern California
00006 // Rob Peters <rjpeters at usc dot edu>
00007 //
00008 // created: Thu Nov 17 16:14:11 2005
00009 // commit: $Id: error_context.cc 10065 2007-04-12 05:54:56Z rjpeters $
00010 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/rutz/error_context.cc $
00011 //
00012 // --------------------------------------------------------------------
00013 //
00014 // This file is part of GroovX.
00015 //   [http://www.klab.caltech.edu/rjpeters/groovx/]
00016 //
00017 // GroovX is free software; you can redistribute it and/or modify it
00018 // under the terms of the GNU General Public License as published by
00019 // the Free Software Foundation; either version 2 of the License, or
00020 // (at your option) any later version.
00021 //
00022 // GroovX is distributed in the hope that it will be useful, but
00023 // WITHOUT ANY WARRANTY; without even the implied warranty of
00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025 // General Public License for more details.
00026 //
00027 // You should have received a copy of the GNU General Public License
00028 // along with GroovX; if not, write to the Free Software Foundation,
00029 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00030 //
00032 
00033 #ifndef GROOVX_RUTZ_ERROR_CONTEXT_CC_UTC20051118001411_DEFINED
00034 #define GROOVX_RUTZ_ERROR_CONTEXT_CC_UTC20051118001411_DEFINED
00035 
00036 #include "rutz/error_context.h"
00037 
00038 #include <new>
00039 #include <pthread.h>
00040 #include <sstream>
00041 
00042 #include "rutz/debug.h"
00043 GVX_DBG_REGISTER
00044 
00045 namespace
00046 {
00047   // FIXME this "thread-local singleton" code is duplicated here and
00048   // in rutz/backtrace.cc; can we abstract out the common code?
00049 
00050   // thread-local storage (see rutz::error_context::current() below)
00051   pthread_key_t current_context_key;
00052   pthread_once_t current_context_key_once = PTHREAD_ONCE_INIT;
00053 
00054   void current_context_destroy(void* bt)
00055   {
00056     delete static_cast<rutz::error_context*>(bt);
00057   }
00058 
00059   void current_context_key_alloc()
00060   {
00061     pthread_key_create(&current_context_key,
00062                        &current_context_destroy);
00063   }
00064 
00065   // returns a mutable object (but note that
00066   // rutz::error_context::current() returns a const object)
00067   rutz::error_context* get_current_context()
00068   {
00069     pthread_once(&current_context_key_once,
00070                  &current_context_key_alloc);
00071 
00072     void* const ptr = pthread_getspecific(current_context_key);
00073 
00074     if (ptr != 0)
00075       {
00076         return static_cast<rutz::error_context*>(ptr);
00077       }
00078 
00079     // else...
00080     rutz::error_context* const c = new (std::nothrow) rutz::error_context;
00081 
00082     if (c == 0)
00083       GVX_ABORT("memory allocation failed");
00084 
00085     pthread_setspecific(current_context_key,
00086                         static_cast<void*>(c));
00087 
00088     return c;
00089   }
00090 }
00091 
00092 rutz::error_context::error_context() {}
00093 
00094 rutz::error_context::~error_context() {}
00095 
00096 const rutz::error_context& rutz::error_context::current()
00097 {
00098   return *(get_current_context());
00099 }
00100 
00101 bool rutz::error_context::add_entry(const error_context_entry* e)
00102 {
00103   return m_entries.push(e);
00104 }
00105 
00106 void rutz::error_context::remove_entry(const error_context_entry* e)
00107 {
00108   GVX_ASSERT(m_entries.top() == e);
00109   m_entries.pop();
00110 }
00111 
00112 rutz::fstring rutz::error_context::get_text() const
00113 {
00114   std::ostringstream result;
00115 
00116   const char* prefix = "==> while ";
00117 
00118   for (unsigned int i = 0; i < m_entries.size(); ++i)
00119     {
00120       result << prefix << m_entries[i]->text() << ":";
00121       prefix = "\n==> while ";
00122     }
00123 
00124   return rutz::fstring(result.str().c_str());
00125 }
00126 
00127 rutz::error_context_entry::error_context_entry(const rutz::fstring& msg)
00128   :
00129   m_text(msg),
00130   m_context(get_current_context())
00131 {
00132   if (!m_context->add_entry(this))
00133     m_context = 0;
00134 }
00135 
00136 rutz::error_context_entry::~error_context_entry()
00137 {
00138   if (m_context)
00139     m_context->remove_entry(this);
00140 }
00141 
00142 static const char __attribute__((used)) vcid_groovx_rutz_error_context_cc_utc20051118001411[] = "$Id: error_context.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00143 #endif // !GROOVX_RUTZ_ERROR_CONTEXT_CC_UTC20051118001411DEFINED

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.