7#ifndef PXR_BASE_TF_DEBUG_H
8#define PXR_BASE_TF_DEBUG_H
15#include "pxr/base/tf/api.h"
18#include "pxr/base/tf/preprocessorUtilsLite.h"
29PXR_NAMESPACE_OPEN_SCOPE
31class Tf_DebugSymbolRegistry;
123 enum _NodeState { _NodeUninitialized, _NodeDisabled, _NodeEnabled };
135 _SetNode(_GetNode(val), Tf_DebugGetEnumName(val),
true);
141 _SetNode(_GetNode(val), Tf_DebugGetEnumName(val),
false);
152 const int n = _Traits<T>::NumCodes;
153 for (
int i = 0; i != n; ++i) {
154 T code =
static_cast<T
>(i);
155 _SetNode(_GetNode(code), Tf_DebugGetEnumName(code),
true);
162 const int n = _Traits<T>::NumCodes;
163 for (
int i = 0; i != n; ++i) {
164 T code =
static_cast<T
>(i);
165 _SetNode(_GetNode(code), Tf_DebugGetEnumName(code),
false);
177 static_assert(_Traits<T>::IsDeclared,
178 "Must declare debug codes with TF_DEBUG_CODES()");
179 if (_Traits<T>::CompileTimeEnabled) {
180 _Node &node = _GetNode(val);
181 _NodeState curState = node.state.load();
182 if (ARCH_UNLIKELY(curState == _NodeUninitialized)) {
183 _InitializeNode(_GetNode(val), Tf_DebugGetEnumName(val));
184 curState = node.state.load();
186 return curState == _NodeEnabled;
195 static_assert(_Traits<T>::IsDeclared,
196 "Must declare debug codes with TF_DEBUG_CODES()");
197 return _Traits<T>::CompileTimeEnabled;
205 static_assert(_Traits<T>::IsDeclared,
206 "Must declare debug codes with TF_DEBUG_CODES()");
207 return _Traits<T>::NumCodes;
212 static TF_API
void Msg(
const std::string& msg);
219 ScopeHelper(
bool enabled,
const char* name) {
220 if ((active = enabled)) {
222 TfDebug::_ScopedOutput(
true, str);
230 TfDebug::_ScopedOutput(
false, str);
238 struct TimedScopeHelper {
239 TimedScopeHelper(
bool enabled,
const char* fmt, ...)
255 static
std::vector<
std::
string> SetDebugSymbolsByName(
256 const
std::
string& pattern,
bool value);
260 static
bool IsDebugSymbolNameEnabled(const
std::
string& name);
267 static
std::
string GetDebugSymbolDescriptions();
271 static
std::vector<
std::
string> GetDebugSymbolNames();
279 static
std::
string GetDebugSymbolDescription(const
std::
string& name);
288 static
void SetOutputFile(FILE *file);
295 static
void _RegisterDebugSymbol(
296 T enumVal,
char const *name,
char const *descrip) {
297 static_assert(_Traits<T>::IsDeclared,
298 "Must declare debug codes with TF_DEBUG_CODES()");
299 const int index =
static_cast<int>(enumVal);
300 const int numCodes = _Traits<T>::NumCodes;
301 if (ARCH_UNLIKELY(index < 0 || index >= numCodes)) {
302 _ComplainAboutInvalidSymbol(name);
305 _RegisterDebugSymbolImpl(&_GetNode(enumVal), name, descrip);
309 static void _RegisterDebugSymbolImpl(_Node *addr,
char const *enumName,
310 char const *descrip);
318 static constexpr bool IsDeclared =
false;
324 mutable std::atomic<_NodeState> state;
331 static _Node nodes[_Traits<T>::NumCodes];
335 static _Node &_GetNode(T val) {
336 return _Data<T>::nodes[
static_cast<int>(val)];
339 friend class Tf_DebugSymbolRegistry;
342 static void _InitializeNode(_Node &node,
char const *name);
345 static void _ComplainAboutInvalidSymbol(
char const *name);
348 static void _SetNode(_Node &node,
char const *name,
bool state);
351 static void _ScopedOutput(
bool start,
char const *str);
355TfDebug::_Node TfDebug::_Data<T>::nodes[];
358struct TfDebug::TimedScopeHelper<false> {
359 TimedScopeHelper(
bool,
const char*, ...)
376#define TF_DEBUG_CODES(...) \
377 TF_CONDITIONALLY_COMPILE_TIME_ENABLED_DEBUG_CODES(true, __VA_ARGS__)
397#define TF_CONDITIONALLY_COMPILE_TIME_ENABLED_DEBUG_CODES(condition, ...) \
398 enum _TF_DEBUG_ENUM_NAME(__VA_ARGS__) { \
400 TF_PP_CAT( _TF_DEBUG_ENUM_NAME(__VA_ARGS__), __PAST_END) \
403 struct TfDebug::_Traits<_TF_DEBUG_ENUM_NAME(__VA_ARGS__)> { \
404 static constexpr bool IsDeclared = true; \
405 static constexpr int NumCodes = \
406 TF_PP_CAT(_TF_DEBUG_ENUM_NAME(__VA_ARGS__), __PAST_END); \
407 static constexpr bool CompileTimeEnabled = (condition); \
409 inline char const * \
410 Tf_DebugGetEnumName(_TF_DEBUG_ENUM_NAME(__VA_ARGS__) val) { \
411 constexpr char const *CStrings[] = { \
412 TF_PP_FOR_EACH(_TF_DEBUG_MAKE_STRING, __VA_ARGS__) \
414 return CStrings[static_cast<int>(val)]; \
417#define _TF_DEBUG_MAKE_STRING(x) #x,
422#define _TF_DEBUG_ENUM_NAME(...) \
423 TF_PP_CAT(_TF_DEBUG_FIRST_CODE(__VA_ARGS__, dummy), __DebugCodes)
425#define _TF_DEBUG_FIRST_CODE(first, ...) first
449#define TF_DEBUG_MSG(enumVal, ...) \
450 if (!TfDebug::IsEnabled(enumVal)) ; else TfDebug::Helper().Msg(__VA_ARGS__)
484#define TF_DEBUG(enumVal) \
485 if (!TfDebug::IsEnabled(enumVal)) ; else TfDebug::Helper()
494#define TF_INFO(x) TF_DEBUG(x)
523#define TF_DEBUG_TIMED_SCOPE(enumVal, ...) \
524 TfDebug::TimedScopeHelper< \
526 std::decay<decltype(enumVal)>::type>::CompileTimeEnabled> \
527 TF_PP_CAT(local__TfScopeDebugSwObject, __LINE__)( \
528 TfDebug::IsEnabled(enumVal), __VA_ARGS__)
548#define TF_DEBUG_ENVIRONMENT_SYMBOL(VAL, descrip) \
549 if (TfDebug::_Traits< \
550 std::decay<decltype(VAL)>::type>::CompileTimeEnabled) { \
551 TF_ADD_ENUM_NAME(VAL); \
552 TfDebug::_RegisterDebugSymbol(VAL, #VAL, descrip); \
557PXR_NAMESPACE_CLOSE_SCOPE
Define function attributes.
#define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
Macro used to indicate a function takes a printf-like specification.
Enum-based debugging messages.
static void Enable(T val)
Mark debugging as enabled for enum value val.
static void Disable(T val)
Mark debugging as disabled for enum value val.
static size_t GetNumDebugCodes()
Return the number of debugging symbols of this type.
static bool IsEnabled(T val)
True if debugging is enabled for the enum value val.
static bool IsCompileTimeEnabled()
True if debugging can be activated at run-time, whether or not it is currently enabled.
static void EnableAll()
Mark debugging as enabled for all enum values of type T.
static void DisableAll()
Mark debugging as disabled for all enum values of type T.
Low-cost, high-resolution timer datatype.
A file containing basic constants and definitions.