Sierra Toolkit Version of the Day
stk_util/stk_util/diag/Trace.hpp
00001 #ifndef STK_UTIL_DIAG_TRACE_HPP
00002 #define STK_UTIL_DIAG_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 
00013 #define SLIB_TRACE_COVERAGE
00014 
00015 namespace stk {
00016 namespace diag {
00017 
00022 
00031 class Tracespec
00032 {
00033 public:
00040   explicit Tracespec(const char *function_spec)
00041     : m_functionSpec(function_spec)
00042   {}
00043 
00049   inline const char *getFunctionSpec() const {
00050     return m_functionSpec;
00051   }
00052 
00058   std::string getFunctionName() const;
00059 
00065   std::string getFunctionShortName() const;
00066 
00072   std::string getFunctionClass() const;
00073 
00079   std::string getFunctionNamespace() const;
00080 
00086   std::string getFunctionShortClass() const;
00087 
00088 protected:
00089   const char *      m_functionSpec;    
00090 };
00091 
00092 typedef std::vector<const char *> TracebackStack;
00093 
00101 class Traceback : public Tracespec
00102 {
00103 public:
00113   enum TracebackState{RUNNING, THROWING};
00114 
00115   enum {STACK_SIZE = 2048};        
00116   typedef const char *Stack[STACK_SIZE] ;    
00117   typedef const char * const *  const_stack_iterator;  
00118   typedef const char **  stack_iterator;      
00119 
00128   typedef std::map<const char *, int> Coverage;
00129 
00135   class Preserve
00136   {
00137   public:
00143     Preserve() {
00144       Traceback::preserveStack();
00145     }
00146 
00151     ~Preserve() {
00152       Traceback::releaseStack();
00153     }
00154   };
00155 
00162   explicit Traceback(const char *function_spec)
00163     : Tracespec(function_spec)
00164   {
00165     if (s_top >= &s_stack[STACK_SIZE - 1] || s_top == 0)
00166       s_top = s_stack;
00167     *s_top++ = function_spec;
00168 
00169     if (s_tracebackState == THROWING && !s_tracebackPreserve && !std::uncaught_exception())
00170       s_tracebackState = RUNNING;
00171   }
00172 
00173 
00179   ~Traceback() {
00180     if (!s_tracebackPreserve && std::uncaught_exception() && s_tracebackState == RUNNING) {
00181       s_tracebackState = THROWING;
00182       s_storedTop = s_storedStack + (s_top - s_stack);
00183       std::copy(s_stack, s_top, s_storedStack);
00184     }
00185     if (s_top > &s_stack[0])
00186       --s_top;
00187   }
00188 
00189   static TracebackStack snapshot();
00190 
00196   inline static void enableTracebackDisplay() {
00197     --s_tracebackDisplay;
00198   }
00199 
00205   inline static void disableTracebackDisplay() {
00206     ++s_tracebackDisplay;
00207   }
00208 
00216   inline static bool displayTraceback() {
00217     return s_tracebackDisplay == 0;
00218   }
00219 
00225   inline static void preserveStack() {
00226     ++s_tracebackPreserve;
00227   }
00228 
00234   inline static void releaseStack() {
00235     --s_tracebackPreserve;
00236   }
00237 
00244   inline static TracebackState getTracebackState() {
00245     return s_tracebackState;
00246   }
00247 
00257   static std::string printTraceback(const TracebackStack &traceback_stack);
00258 
00259 private:
00260   static TracebackState    s_tracebackState;  
00261   static int      s_tracebackPreserve;  
00262   static int      s_tracebackDisplay;  
00263   static const char **    s_top;      
00264   static Stack      s_stack;    
00265   static const char **    s_storedTop;    
00266   static Stack      s_storedStack;    
00267 };
00268 
00269 
00281 class Trace : public Traceback
00282 {
00283 public:
00289   typedef Writer & (*ExtraFuncPtr)(Writer &);
00290 
00295   struct TraceList : public std::vector<const char *> {
00296   public:
00297     TraceList() {
00298       s_traceListExists = true;
00299     }
00300 
00301     ~TraceList() {
00302       s_traceListExists = false;
00303     }
00304   };
00305 
00310   enum {
00311     IN_TRACE_LIST  = 0x01    
00312   };
00313 
00331   Trace(Writer &dout, const char *function_name, int print_mask = LOG_TRACE, bool do_trace = true);
00332 
00338   ~Trace();
00339 
00349   inline static ExtraFuncPtr setExtra(ExtraFuncPtr extra) {
00350     ExtraFuncPtr x = s_extra;
00351     s_extra = extra;
00352     return x;
00353   }
00354 
00362   inline static void addTraceFunction(const std::string &function_prefix) {
00363     char *s = std::strcpy(new char[function_prefix.length() + 1], function_prefix.c_str());
00364 
00365     s_traceList.push_back(s);
00366   }
00367 
00373   inline static void clearTraceFunctions() {
00374     for (std::vector<const char *>::iterator it = s_traceList.begin(); it != s_traceList.end(); ++it)
00375       delete[] (*it);
00376 
00377     s_traceList.clear();
00378   }
00379 
00388   Writer &verbose_print(Writer &dout) const;
00389 
00390 private:
00391   Writer &      m_diagWriter;    
00392   double      m_startCpuTime;    
00393   size_t      m_startMemAlloc;  
00394   PrintMask      m_lineMask;    
00395   bool                          m_do_trace;             
00396   int        m_flags;    
00397 
00398   static ExtraFuncPtr    s_extra;    
00399   static TraceList    s_traceList;    
00400   static bool                   s_traceListExists;      
00401 };
00402 
00416 inline Writer &operator<<(Writer &dout, const Trace &diag_trace) {
00417   return diag_trace.verbose_print(dout);
00418 }
00419 
00420 } // namespace diag
00421 } // namespace stk
00422 
00426 
00427 #endif // STK_UTIL_DIAG_TRACE_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends