All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
debug.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef TF_DEBUG_H
25 #define TF_DEBUG_H
26 
30 
31 #include "pxr/pxr.h"
32 #include "pxr/base/tf/api.h"
33 #include "pxr/base/tf/tf.h"
34 #include "pxr/base/tf/enum.h"
35 #include "pxr/base/tf/preprocessorUtilsLite.h"
36 #include "pxr/base/tf/registryManager.h"
37 #include "pxr/base/tf/stopwatch.h"
38 #include "pxr/base/arch/attributes.h"
39 
40 #include <cstdio>
41 #include <string>
42 #include <type_traits>
43 #include <typeinfo>
44 #include <vector>
45 
46 PXR_NAMESPACE_OPEN_SCOPE
47 
48 class Tf_DebugSymbolRegistry;
49 
52 
148 class TfDebug {
149 public:
157  template <class T>
158  static void Enable(T val) {
159  _SetNodes(&_GetNode(val), 1, true);
160  }
161 
163  template <class T>
164  static void Disable(T val) {
165  _SetNodes(&_GetNode(val), 1, false);
166  }
167 
174  template <class T>
175  static void EnableAll() {
176  _SetNodes(&_Data<T>::nodes[0], _Traits<T>::n, true);
177  }
178 
180  template <class T>
181  static void DisableAll() {
182  _SetNodes(&_Data<T>::nodes[0], _Traits<T>::n, false);
183  }
184 
191  template <class T>
192  static bool IsEnabled(T val) {
193  return _Traits<T>::compileTimeEnabled && _GetNode(val).enabled;
194  }
195 
198  template <class T>
199  static bool IsCompileTimeEnabled() {
200  return _Traits<T>::compileTimeEnabled;
201  }
202 
207  template <class T>
208  static size_t GetDebugRangeCount() {
209  return _Traits<T>::n;
210  }
211 
223  template <class T>
224  static T GetDebugSymbol(size_t index) {
225  if (index >= _Traits<T>::n)
226  index = _Traits<T>::n-1;
227 
228  return T(_Traits<T>::min + index);
229  }
230 
231 #if !defined(doxygen)
232  struct Helper {
233  static TF_API void Msg(const std::string& msg);
234  static TF_API void Msg(const char* msg, ...) ARCH_PRINTF_FUNCTION(1,2);
235  };
236 #endif
237 
238  template <bool B>
239  struct ScopeHelper {
240  ScopeHelper(bool enabled, const char* name) {
241  if ((active = enabled)) {
242  str = name;
243  TfDebug::_ScopedOutput(true, str);
244  }
245  else
246  str = NULL;
247  }
248 
249  ~ScopeHelper() {
250  if (active)
251  TfDebug::_ScopedOutput(false, str);
252  }
253 
254  bool active;
255  const char* str;
256  };
257 
258  template <bool B>
259  struct TimedScopeHelper {
260  TimedScopeHelper(bool enabled, const char* fmt, ...)
261  ARCH_PRINTF_FUNCTION(3, 4);
262  ~TimedScopeHelper();
263 
264  bool active;
265  std::string str;
266  TfStopwatch stopwatch;
267  };
268 
275  TF_API
276  static std::vector<std::string> SetDebugSymbolsByName(
277  const std::string& pattern, bool value);
278 
280  TF_API
281  static bool IsDebugSymbolNameEnabled(const std::string& name);
282 
287  TF_API
288  static std::string GetDebugSymbolDescriptions();
289 
291  TF_API
292  static std::vector<std::string> GetDebugSymbolNames();
293 
299  TF_API
300  static std::string GetDebugSymbolDescription(const std::string& name);
301 
308  TF_API
309  static void SetOutputFile(FILE *file);
310 
311  struct _Node;
312 
313  // Public, to be used in TF_DEBUG_ENVIRONMENT_SYMBOL() macro,
314  // but not meant to be used otherwise.
315  template <class T>
316  static _Node* _GetSymbolAddr(T val, const char* name) {
317  _Traits<T>::Enum_Not_Listed_In_Any_TF_DEBUG_RANGE();
318  int index = int(val) - _Traits<T>::min;
319  if (index < 0 || index >= int(_Traits<T>::n))
320  _ComplainAboutInvalidSymbol(name);
321 
322  return &_GetNode(val);
323  }
324 
325  // Public, to be used in TF_DEBUG_ENVIRONMENT_SYMBOL() macro,
326  // but not meant to be used otherwise.
327  TF_API
328  static void _RegisterDebugSymbol(TfEnum val, _Node* addr,
329  const char* descrip);
330 
331  // This function is only meant for use by TfRegistryManager.
332  // It's relatively expensive, and not meant for large-scale use.
333  TF_API
334  static bool _CheckEnvironmentForMatch(const std::string& enumName);
335 
336  // Unfortunately, we need to make both _Traits and _Node, below
337  // public because of their use in macros.
338  // Please treat both as a private data structures!
339 
340  template <class T>
341  struct _Traits {
342  static const int min = 0;
343  static const size_t n = 1;
344  enum{compileTimeEnabled = 0};
345  };
346 
347  // Note: this is a POD (plain old data structure) so it is initialized
348  // to zero statically.
349  struct _Node {
350  bool enabled;
351  };
352 
353 private:
354 
355  template <class T>
356  struct _Data {
357  static _Node nodes[_Traits<T>::n];
358  };
359 
360  template <class T>
361  static _Node& _GetNode(T val) {
362  return _Data<T>::nodes[int(val) - _Traits<T>::min];
363  }
364 
365  friend class Tf_DebugSymbolRegistry;
366 
367  TF_API
368  static void _ComplainAboutInvalidSymbol(const char*);
369  TF_API
370  static void _SetNodes(_Node* ptr, size_t nNodes, bool state);
371  TF_API
372  static void _ScopedOutput(bool start, const char* str);
373 };
374 
375 template <class T>
376 TfDebug::_Node TfDebug::_Data<T>::nodes[];
377 
378 template <>
379 struct TfDebug::TimedScopeHelper<false> {
380  TimedScopeHelper(bool, const char*, ...)
381  ARCH_PRINTF_FUNCTION(3, 4) {
382  }
383 };
384 
397 #define TF_DEBUG_CODES(...) \
398  enum _TF_DEBUG_ENUM_NAME(__VA_ARGS__) { \
399  TF_PP_CAT( _TF_DEBUG_ENUM_NAME(__VA_ARGS__), __FIRST) \
400  , __VA_ARGS__ \
401  , TF_PP_CAT( _TF_DEBUG_ENUM_NAME(__VA_ARGS__), __LAST) \
402  }; \
403  TF_DEBUG_RANGE( \
404  _TF_DEBUG_ENUM_NAME(__VA_ARGS__), \
405  TF_PP_CAT( _TF_DEBUG_ENUM_NAME(__VA_ARGS__), __FIRST), \
406  TF_PP_CAT( _TF_DEBUG_ENUM_NAME(__VA_ARGS__), __LAST), \
407  true);
408 
409 // In the _TF_DEBUG_ENUM_NAME macro below we pass 'dummy' to
410 // _TF_DEBUG_FIRST_CODE as the second argument to ensure that we always
411 // have more than one argument as expected by _TF_DEBUG_FIRST_CODE.
412 #define _TF_DEBUG_ENUM_NAME(...) \
413  TF_PP_CAT( _TF_DEBUG_FIRST_CODE(__VA_ARGS__, dummy), __DebugCodes )
414 
415 #define _TF_DEBUG_FIRST_CODE(first, ...) \
416  first
417 
431 #define TF_DEBUG_RANGE(enumType, first, last, enabled) \
432  template <> \
433  struct TfDebug::_Traits<enumType> { \
434  static const int min = first; \
435  static const size_t n = 1 + int(last) - int(first); \
436  enum {compileTimeEnabled = enabled}; \
437  static void Enum_Not_Listed_In_Any_TF_DEBUG_RANGE() { } \
438  };
439 
462 #define TF_DEBUG_MSG(enumVal, ...) \
463  if (!TfDebug::IsEnabled(enumVal)) /* empty */ ; else TfDebug::Helper().Msg(__VA_ARGS__)
464 
497 #define TF_DEBUG(enumVal) \
498  if (!TfDebug::IsEnabled(enumVal)) /* empty */ ; else TfDebug::Helper()
499 
507 #define TF_INFO(x) TF_DEBUG(x)
508 
536 #define TF_DEBUG_TIMED_SCOPE(enumVal, ...) \
537  TfDebug::TimedScopeHelper< \
538  TfDebug::_Traits< \
539  std::decay<decltype(enumVal)>::type>::compileTimeEnabled> \
540  TF_PP_CAT(local__TfScopeDebugSwObject, __LINE__)( \
541  TfDebug::IsEnabled(enumVal), __VA_ARGS__)
542 
561 #define TF_DEBUG_ENVIRONMENT_SYMBOL(VAL, descrip) \
562  if (TfDebug::_Traits< \
563  std::decay<decltype(VAL)>::type>::compileTimeEnabled) { \
564  TF_ADD_ENUM_NAME(VAL); \
565  TfDebug::_RegisterDebugSymbol(TfEnum(VAL), \
566  TfDebug::_GetSymbolAddr(VAL, #VAL), \
567  descrip); \
568  }
569 
571 
572 PXR_NAMESPACE_CLOSE_SCOPE
573 
574 #endif
static size_t GetDebugRangeCount()
Return the number of debugging symbols of this type.
Definition: debug.h:208
static TF_API void SetOutputFile(FILE *file)
Direct debug output to either stdout or stderr.
static bool IsCompileTimeEnabled()
True if debugging can be activated at run-time, whether or not it is currently enabled.
Definition: debug.h:199
static void DisableAll()
Mark debugging as disabled for all enum values of type T.
Definition: debug.h:181
static TF_API bool IsDebugSymbolNameEnabled(const std::string &name)
True if the specified debug symbol is set.
static TF_API std::vector< std::string > SetDebugSymbolsByName(const std::string &pattern, bool value)
Set registered debug symbols matching pattern to value.
An enum class that records both enum type and enum value.
Definition: enum.h:140
Low-cost, high-resolution timer datatype.
Definition: stopwatch.h:57
Enum-based debugging messages.
Definition: debug.h:148
static T GetDebugSymbol(size_t index)
Return the index-th debug symbol of this type.
Definition: debug.h:224
static bool IsEnabled(T val)
True if debugging is enabled for the enum value val.
Definition: debug.h:192
#define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
Macro used to indicate a function takes a printf-like specification.
Definition: attributes.h:51
static TF_API std::vector< std::string > GetDebugSymbolNames()
Get a listing of all debug symbols.
static void EnableAll()
Mark debugging as enabled for all enum values of type T.
Definition: debug.h:175
static TF_API std::string GetDebugSymbolDescriptions()
Get a description of all debug symbols and their purpose.
static void Enable(T val)
Mark debugging as enabled for enum value val.
Definition: debug.h:158
static void Disable(T val)
Mark debugging as disabled for enum value val.
Definition: debug.h:164
static TF_API std::string GetDebugSymbolDescription(const std::string &name)
Get a description for the specified debug symbol.