Sierra Toolkit Version of the Day
stk_mesh/stk_mesh/base/Trace.hpp
00001 #ifndef stk_mesh_Trace_hpp
00002 #define stk_mesh_Trace_hpp
00003 
00005 // Macros/functions for tracing. This file contains the "layer" between
00006 // stk_mesh and the stk-util tracing interface; this layer is necessary because
00007 // one of our goal is to ensure that all tracing code will be compiled-out
00008 // unless tracing is enabled. We also wanted to support the ability to watch
00009 // certain objects/values while tracing and this capability is not supported
00010 // natively in the stk_util interface.
00011 //
00012 // No tracing will occur unless STK_MESH_TRACE_ENABLED is defined. You rebuild
00013 // with tracing with: 'bake -c ; bake <product> cxxflags=-DSTK_MESH_TRACE_ENABLED'
00014 // You'll need to be sure you link with stk_util/use_cases.
00015 //
00016 // If a macro is setting up your main function, be sure to use STKUNIT_WITH_TRACING_MAIN.
00017 // If you're setting up the main function yourself, be sure to set up the
00018 // environment with UseCaseEnvironment.
00019 //
00020 // You'll probably want to add the "--pout" argument so that each processor
00021 // produces it's own trace file.
00022 //
00023 // (Diag|Trace)If will produce diag/trace output if the given PrintMask is
00024 // activated.
00025 //
00026 // (Diag|Trace)IfWatching will produce diag/trace output if the given key is in
00027 // the watch list AND the given PrintMask is activated.
00028 //
00029 // A common pattern for code that wants tracing (put this code somewhere before
00030 // the code you want to trace).
00031 //   stk::mesh::setStream(use_case::dwout());
00032 //   meshlog.setPrintMask(stk::mesh::LOG_ENTITY | stk::mesh::LOG_TRACE | stk::mesh::LOG_TRACE_SUB_CALLS);
00033 //   stk::mesh::watch(stk::mesh::EntityKey(0, 11)); // Node 11
00034 //   stk::diag::Trace::addTraceFunction("stk::mesh::");
00035 //
00036 // Other common items to watch are Parts, Buckets, and Fields
00037 //
00038 // For unit-testing, all trace-related libraries should be header-only so that
00039 // we can define STK_MESH_TRACE_ENABLED and #include the necessary headers and
00040 // be able to trace.
00041 //
00042 // TODO
00043 // * Describe the tracing/diagnostic command-line interface
00044 // * Describe the PrintMask system.
00045 // * Command-line interface to key watching system?
00046 // * Would like to see a "watch-all" operation based on type
00047 // * What if the id's of two different types of objects are the same?
00048 // * Would be nice if Trace("func") supported printing of arg values too
00049 // * Would be nice to have some automated way of checking that the method names
00050 //   are up to date.
00052 
00053 #include <stk_mesh/base/DiagWriter.hpp>
00054 #include <stk_mesh/base/EntityKey.hpp>
00055 
00056 #include <stk_util/diag/WriterExt.hpp>
00057 
00058 #include <string>
00059 #include <typeinfo>
00060 #include <vector>
00061 
00062 namespace stk {
00063 namespace mesh {
00064 
00066 
00067 class Watch
00068 {
00069  public:
00070   virtual ~Watch() {}
00071   virtual const std::type_info& type() const = 0;
00072   virtual bool match(const void* item_) const = 0;
00073   virtual void* item() = 0;
00074 };
00075 
00076 std::vector<Watch*>& watch_vector();
00077 
00078 template <typename T>
00079 bool internal_is_watching(const T& item)
00080 {
00081   for (std::vector<Watch*>::const_iterator
00082        itr = watch_vector().begin(); itr != watch_vector().end(); ++itr) {
00083     if ((*itr)->type() == typeid(T) &&
00084         (*itr)->match(&item)) {
00085       return true;
00086     }
00087   }
00088   return false;
00089 }
00090 
00091 template <typename T>
00092 class WatchClass : public Watch
00093 {
00094  public:
00095   WatchClass(const T& watch_item) : m_watch_item(watch_item),
00096                                     m_type_info(&typeid(T)) {
00097     watch_vector().push_back(this);
00098   }
00099 
00100   virtual const std::type_info& type() const { return *m_type_info; }
00101 
00102   virtual bool match(const void* item_) const {
00103     return *(static_cast<const T*>(item_)) == m_watch_item;
00104   }
00105 
00106   virtual void* item() { return &m_watch_item; }
00107 
00108  private:
00109   T m_watch_item;
00110   const std::type_info* m_type_info;
00111 };
00112 
00114 
00115 template <typename T>
00116 void watch(const T& watch_item)
00117 {
00118   // leaks, but who cares
00119   new WatchClass<T>(watch_item);
00120 }
00121 
00122 #ifdef STK_MESH_TRACE_ENABLED
00123 
00124 inline void setStream(std::ostream& stream)
00125 {
00126   initDiagWriter(stream);
00127 }
00128 
00129 #define Trace_(location) stk::mesh::Trace trace__(location)
00130 
00131 #define TraceIf(location, mask) stk::mesh::Trace trace__(location, mask)
00132 
00133 #define TraceIfWatching(location, mask, item) \
00134 stk::mesh::Trace trace__(location, mask, stk::mesh::internal_is_watching(item)); \
00135 DiagIfWatching(mask, item, "Watched item is: " << item << stk::diag::dendl)
00136 
00137 // Useful if you need two traces in the same scope, dec is used to modify the
00138 // name of the trace object to avoid conflicting.
00139 #define TraceIfWatchingDec(location, mask, item, dec) \
00140 stk::mesh::Trace trace##dec__(location, mask, stk::mesh::internal_is_watching(item)); \
00141 DiagIfWatching(mask, item, "Watched item is: " << item << stk::diag::dendl)
00142 
00143 #define DiagIfWatching(mask, item, message)                             \
00144 meshlog.w(stk::mesh::internal_is_watching(item), mask) << message << stk::diag::dendl
00145 
00146 #define DiagIf(mask, message)                   \
00147 meshlog.m(mask) << message << stk::diag::dendl
00148 
00150 
00151 #else
00152 
00153 inline void setStream(std::ostream& stream) { }
00154 
00155 #define Trace_(location)                              ((void) (0))
00156 #define TraceIf(location, mask)                       ((void) (0))
00157 #define TraceIfWatching(location, mask, item)         ((void) (0))
00158 #define TraceIfWatchingDec(location, mask, item, dec) ((void) (0))
00159 #define DiagIf(mask, message)                         ((void) (0))
00160 #define DiagIfWatching(mask, item, message)           ((void) (0))
00161 
00162 #endif
00163 
00164 } // namespace mesh
00165 } // namespace stk
00166 
00167 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends