|
Sierra Toolkit
Version of the Day
|
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_classic::mesh::setStream(use_case::dwout()); 00032 // meshlog.setPrintMask(stk_classic::mesh::LOG_ENTITY | stk_classic::mesh::LOG_TRACE | stk_classic::mesh::LOG_TRACE_SUB_CALLS); 00033 // stk_classic::mesh::watch(stk_classic::mesh::EntityKey(0, 11)); // Node 11 00034 // stk_classic::diag::Trace::addTraceFunction("stk_classic::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_classic { 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_classic::mesh::Trace trace__(location) 00130 00131 #define TraceIf(location, mask) stk_classic::mesh::Trace trace__(location, mask) 00132 00133 #define TraceIfWatching(location, mask, item) \ 00134 stk_classic::mesh::Trace trace__(location, mask, stk_classic::mesh::internal_is_watching(item)); \ 00135 DiagIfWatching(mask, item, "Watched item is: " << item << stk_classic::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_classic::mesh::Trace trace##dec__(location, mask, stk_classic::mesh::internal_is_watching(item)); \ 00141 DiagIfWatching(mask, item, "Watched item is: " << item << stk_classic::diag::dendl) 00142 00143 #define DiagIfWatching(mask, item, message) \ 00144 meshlog.w(stk_classic::mesh::internal_is_watching(item), mask) << message << stk_classic::diag::dendl 00145 00146 #define DiagIf(mask, message) \ 00147 meshlog.m(mask) << message << stk_classic::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_classic 00166 00167 #endif