Sierra Toolkit  Version of the Day
stk_mesh/stk_mesh/base/Trace.hpp
1 #ifndef stk_mesh_Trace_hpp
2 #define stk_mesh_Trace_hpp
3 
5 // Macros/functions for tracing. This file contains the "layer" between
6 // stk_mesh and the stk-util tracing interface; this layer is necessary because
7 // one of our goal is to ensure that all tracing code will be compiled-out
8 // unless tracing is enabled. We also wanted to support the ability to watch
9 // certain objects/values while tracing and this capability is not supported
10 // natively in the stk_util interface.
11 //
12 // No tracing will occur unless STK_MESH_TRACE_ENABLED is defined. You rebuild
13 // with tracing with: 'bake -c ; bake <product> cxxflags=-DSTK_MESH_TRACE_ENABLED'
14 // You'll need to be sure you link with stk_util/use_cases.
15 //
16 // If a macro is setting up your main function, be sure to use STKUNIT_WITH_TRACING_MAIN.
17 // If you're setting up the main function yourself, be sure to set up the
18 // environment with UseCaseEnvironment.
19 //
20 // You'll probably want to add the "--pout" argument so that each processor
21 // produces it's own trace file.
22 //
23 // (Diag|Trace)If will produce diag/trace output if the given PrintMask is
24 // activated.
25 //
26 // (Diag|Trace)IfWatching will produce diag/trace output if the given key is in
27 // the watch list AND the given PrintMask is activated.
28 //
29 // A common pattern for code that wants tracing (put this code somewhere before
30 // the code you want to trace).
31 // stk_classic::mesh::setStream(use_case::dwout());
32 // meshlog.setPrintMask(stk_classic::mesh::LOG_ENTITY | stk_classic::mesh::LOG_TRACE | stk_classic::mesh::LOG_TRACE_SUB_CALLS);
33 // stk_classic::mesh::watch(stk_classic::mesh::EntityKey(0, 11)); // Node 11
34 // stk_classic::diag::Trace::addTraceFunction("stk_classic::mesh::");
35 //
36 // Other common items to watch are Parts, Buckets, and Fields
37 //
38 // For unit-testing, all trace-related libraries should be header-only so that
39 // we can define STK_MESH_TRACE_ENABLED and #include the necessary headers and
40 // be able to trace.
41 //
42 // TODO
43 // * Describe the tracing/diagnostic command-line interface
44 // * Describe the PrintMask system.
45 // * Command-line interface to key watching system?
46 // * Would like to see a "watch-all" operation based on type
47 // * What if the id's of two different types of objects are the same?
48 // * Would be nice if Trace("func") supported printing of arg values too
49 // * Would be nice to have some automated way of checking that the method names
50 // are up to date.
52 
53 #include <stk_mesh/base/DiagWriter.hpp>
54 #include <stk_mesh/base/EntityKey.hpp>
55 
56 #include <stk_util/diag/WriterExt.hpp>
57 
58 #include <string>
59 #include <typeinfo>
60 #include <vector>
61 
62 namespace stk_classic {
63 namespace mesh {
64 
66 
67 class Watch
68 {
69  public:
70  virtual ~Watch() {}
71  virtual const std::type_info& type() const = 0;
72  virtual bool match(const void* item_) const = 0;
73  virtual void* item() = 0;
74 };
75 
76 std::vector<Watch*>& watch_vector();
77 
78 template <typename T>
79 bool internal_is_watching(const T& item)
80 {
81  for (std::vector<Watch*>::const_iterator
82  itr = watch_vector().begin(); itr != watch_vector().end(); ++itr) {
83  if ((*itr)->type() == typeid(T) &&
84  (*itr)->match(&item)) {
85  return true;
86  }
87  }
88  return false;
89 }
90 
91 template <typename T>
92 class WatchClass : public Watch
93 {
94  public:
95  WatchClass(const T& watch_item) : m_watch_item(watch_item),
96  m_type_info(&typeid(T)) {
97  watch_vector().push_back(this);
98  }
99 
100  virtual const std::type_info& type() const { return *m_type_info; }
101 
102  virtual bool match(const void* item_) const {
103  return *(static_cast<const T*>(item_)) == m_watch_item;
104  }
105 
106  virtual void* item() { return &m_watch_item; }
107 
108  private:
109  T m_watch_item;
110  const std::type_info* m_type_info;
111 };
112 
114 
115 template <typename T>
116 void watch(const T& watch_item)
117 {
118  // leaks, but who cares
119  new WatchClass<T>(watch_item);
120 }
121 
122 #ifdef STK_MESH_TRACE_ENABLED
123 
124 inline void setStream(std::ostream& stream)
125 {
126  initDiagWriter(stream);
127 }
128 
129 #define Trace_(location) stk_classic::mesh::Trace trace__(location)
130 
131 #define TraceIf(location, mask) stk_classic::mesh::Trace trace__(location, mask)
132 
133 #define TraceIfWatching(location, mask, item) \
134 stk_classic::mesh::Trace trace__(location, mask, stk_classic::mesh::internal_is_watching(item)); \
135 DiagIfWatching(mask, item, "Watched item is: " << item << stk_classic::diag::dendl)
136 
137 // Useful if you need two traces in the same scope, dec is used to modify the
138 // name of the trace object to avoid conflicting.
139 #define TraceIfWatchingDec(location, mask, item, dec) \
140 stk_classic::mesh::Trace trace##dec__(location, mask, stk_classic::mesh::internal_is_watching(item)); \
141 DiagIfWatching(mask, item, "Watched item is: " << item << stk_classic::diag::dendl)
142 
143 #define DiagIfWatching(mask, item, message) \
144 meshlog.w(stk_classic::mesh::internal_is_watching(item), mask) << message << stk_classic::diag::dendl
145 
146 #define DiagIf(mask, message) \
147 meshlog.m(mask) << message << stk_classic::diag::dendl
148 
150 
151 #else
152 
153 inline void setStream(std::ostream& stream) { }
154 
155 #define Trace_(location) ((void) (0))
156 #define TraceIf(location, mask) ((void) (0))
157 #define TraceIfWatching(location, mask, item) ((void) (0))
158 #define TraceIfWatchingDec(location, mask, item, dec) ((void) (0))
159 #define DiagIf(mask, message) ((void) (0))
160 #define DiagIfWatching(mask, item, message) ((void) (0))
161 
162 #endif
163 
164 } // namespace mesh
165 } // namespace stk_classic
166 
167 #endif
Sierra Toolkit.