Sierra Toolkit Version of the Day
stk_util/stk_util/diag/Trace.hpp
00001 #ifndef STK_UTIL_SIERRA_TRACE_HPP
00002 #define STK_UTIL_SIERRA_TRACE_HPP
00003 
00004 #include <cstring>
00005 #include <vector>
00006 #include <map>
00007 #include <string>
00008 #include <functional>
00009 
00010 #include <stk_util/diag/Writer_fwd.hpp>
00011 
00012 #include <ostream>
00013 
00014 #define SLIB_TRACE_COVERAGE
00015 
00016 namespace stk {
00017 namespace diag {
00018 
00023 
00032 class Tracespec
00033 {
00034 public:
00041   explicit Tracespec(const char *function_spec)
00042     : m_functionSpec(function_spec)
00043   {}
00044 
00050   inline const char *getFunctionSpec() const {
00051     return m_functionSpec;
00052   }
00053 
00059   std::string getFunctionName() const;
00060 
00066   std::string getFunctionShortName() const;
00067 
00073   std::string getFunctionClass() const;
00074 
00080   std::string getFunctionNamespace() const;
00081 
00087   std::string getFunctionShortClass() const;
00088 
00089 protected:
00090   const char *      m_functionSpec;    
00091 };
00092 
00093 typedef std::vector<const char *> TracebackStack;
00094 
00102 class Traceback : public Tracespec
00103 {
00104 public:
00114   enum TracebackState{RUNNING, THROWING};
00115 
00116   enum {STACK_SIZE = 2048};        
00117   typedef const char *Stack[STACK_SIZE] ;    
00118   typedef const char * const *  const_stack_iterator;  
00119   typedef const char **  stack_iterator;      
00120 
00129   typedef std::map<const char *, int> Coverage;
00130 
00136   class Preserve
00137   {
00138   public:
00144     Preserve() {
00145       Traceback::preserveStack();
00146     }
00147 
00152     ~Preserve() {
00153       Traceback::releaseStack();
00154     }
00155   };
00156 
00163   explicit Traceback(const char *function_spec)
00164     : Tracespec(function_spec)
00165   {
00166     if (s_top >= &s_stack[STACK_SIZE - 1] || s_top == 0)
00167       s_top = s_stack;
00168     *s_top++ = function_spec;
00169 
00170     if (s_tracebackState == THROWING && !s_tracebackPreserve && !std::uncaught_exception())
00171       s_tracebackState = RUNNING;
00172 
00173 #ifdef SLIB_TRACE_COVERAGE
00174     if (s_coverageEnabled)
00175       ++s_coverage[function_spec];
00176 #endif
00177   }
00178 
00179 
00185   ~Traceback() {
00186     if (!s_tracebackPreserve && std::uncaught_exception() && s_tracebackState == RUNNING) {
00187       s_tracebackState = THROWING;
00188       s_storedTop = s_storedStack + (s_top - s_stack);
00189       std::copy(s_stack, s_top, s_storedStack);
00190     }
00191     if (s_top > &s_stack[0])
00192       --s_top;
00193   }
00194 
00195   static TracebackStack snapshot();
00196 
00202   inline static void enableTracebackDisplay() {
00203     --s_tracebackDisplay;
00204   }
00205 
00211   inline static void disableTracebackDisplay() {
00212     ++s_tracebackDisplay;
00213   }
00214 
00222   inline static bool displayTraceback() {
00223     return s_tracebackDisplay == 0;
00224   }
00225 
00231   inline static void preserveStack() {
00232     ++s_tracebackPreserve;
00233   }
00234 
00240   inline static void releaseStack() {
00241     --s_tracebackPreserve;
00242   }
00243 
00253   inline static void enableCoverage(bool coverage_enabled = true) {
00254     s_coverageEnabled = coverage_enabled;
00255   }
00256 
00264   inline static bool coverageEnabled() {
00265     return s_coverageEnabled;
00266   }
00267 
00274   inline static TracebackState getTracebackState() {
00275     return s_tracebackState;
00276   }
00277 
00282   struct PrintCoverage
00283   {};
00284 
00292   static PrintCoverage printCoverage() {
00293     return PrintCoverage();
00294   }
00295 
00302   static std::ostream &printCoverage(std::ostream &os);
00303 
00313   static std::string printTraceback(const TracebackStack &traceback_stack);
00314 
00325   Writer &verbose_print(Writer &dout) const;
00326 
00327 private:
00328   static TracebackState    s_tracebackState;  
00329   static int      s_tracebackPreserve;  
00330   static int      s_tracebackDisplay;  
00331   static const char **    s_top;      
00332   static Stack      s_stack;    
00333   static const char **    s_storedTop;    
00334   static Stack      s_storedStack;    
00335   static bool     s_coverageEnabled;  
00336   static Coverage   s_coverage;   
00337 };
00338 
00339 
00351 class Trace : public Traceback
00352 {
00353 public:
00359   typedef Writer & (*ExtraFuncPtr)(Writer &);
00360 
00365   struct TraceList : public std::vector<const char *> {
00366   public:
00367     TraceList() {
00368       s_traceListExists = true;
00369     }
00370 
00371     ~TraceList() {
00372       s_traceListExists = false;
00373     }
00374   };
00375 
00380   enum {
00381     IN_TRACE_LIST  = 0x01    
00382   };
00383 
00401   Trace(Writer &dout, const char *function_name, int print_mask = LOG_TRACE, bool do_trace = true);
00402 
00408   ~Trace();
00409 
00419   inline static ExtraFuncPtr setExtra(ExtraFuncPtr extra) {
00420     ExtraFuncPtr x = s_extra;
00421     s_extra = extra;
00422     return x;
00423   }
00424 
00432   inline static void addTraceFunction(const std::string &function_prefix) {
00433     char *s = std::strcpy(new char[function_prefix.length() + 1], function_prefix.c_str());
00434 
00435     s_traceList.push_back(s);
00436   }
00437 
00443   inline static void clearTraceFunctions() {
00444     for (std::vector<const char *>::iterator it = s_traceList.begin(); it != s_traceList.end(); ++it)
00445       delete[] (*it);
00446 
00447     s_traceList.clear();
00448   }
00449 
00458   Writer &verbose_print(Writer &dout) const;
00459 
00460 private:
00461   Writer &      m_diagWriter;    
00462   double      m_startCpuTime;    
00463   size_t      m_startMemAlloc;  
00464   PrintMask      m_lineMask;    
00465   bool                          m_do_trace;             
00466   int        m_flags;    
00467 
00468   static ExtraFuncPtr    s_extra;    
00469   static TraceList    s_traceList;    
00470   static bool                   s_traceListExists;      
00471 };
00472 
00486 inline Writer &operator<<(Writer &dout, const Trace &diag_trace) {
00487   return diag_trace.verbose_print(dout);
00488 }
00489 
00503 inline std::ostream &operator<<(std::ostream &os, const Traceback::PrintCoverage &) {
00504   return Traceback::printCoverage(os);
00505 }
00506 
00507 
00508 } // namespace diag
00509 } // namespace stk
00510 
00511 namespace sierra {
00512 namespace Diag {
00513 
00514 typedef stk::diag::Tracespec Tracespec;
00515 typedef stk::diag::Traceback Traceback;
00516 typedef stk::diag::Trace Trace;
00517 
00518 } // namespace sierra 
00519 } // namespace Diag 
00520 
00521 
00525 
00526 #endif // STK_UTIL_SIERRA_TRACE_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines