24 #ifndef PXR_BASE_TF_DEBUG_H 25 #define PXR_BASE_TF_DEBUG_H 32 #include "pxr/base/tf/api.h" 35 #include "pxr/base/tf/preprocessorUtilsLite.h" 46 PXR_NAMESPACE_OPEN_SCOPE
48 class Tf_DebugSymbolRegistry;
140 enum _NodeState { _NodeUninitialized, _NodeDisabled, _NodeEnabled };
152 _SetNode(_GetNode(val), Tf_DebugGetEnumName(val),
true);
158 _SetNode(_GetNode(val), Tf_DebugGetEnumName(val),
false);
169 const int n = _Traits<T>::NumCodes;
170 for (
int i = 0; i != n; ++i) {
171 T code = static_cast<T>(i);
172 _SetNode(_GetNode(code), Tf_DebugGetEnumName(code),
true);
179 const int n = _Traits<T>::NumCodes;
180 for (
int i = 0; i != n; ++i) {
181 T code = static_cast<T>(i);
182 _SetNode(_GetNode(code), Tf_DebugGetEnumName(code),
false);
194 static_assert(_Traits<T>::IsDeclared,
195 "Must declare debug codes with TF_DEBUG_CODES()");
196 if (_Traits<T>::CompileTimeEnabled) {
197 _Node &node = _GetNode(val);
198 _NodeState curState = node.state.load();
199 if (ARCH_UNLIKELY(curState == _NodeUninitialized)) {
200 _InitializeNode(_GetNode(val), Tf_DebugGetEnumName(val));
201 curState = node.state.load();
203 return curState == _NodeEnabled;
212 static_assert(_Traits<T>::IsDeclared,
213 "Must declare debug codes with TF_DEBUG_CODES()");
214 return _Traits<T>::CompileTimeEnabled;
222 static_assert(_Traits<T>::IsDeclared,
223 "Must declare debug codes with TF_DEBUG_CODES()");
224 return _Traits<T>::NumCodes;
227 #if !defined(doxygen) 229 static TF_API
void Msg(
const std::string& msg);
236 ScopeHelper(
bool enabled,
const char* name) {
237 if ((active = enabled)) {
239 TfDebug::_ScopedOutput(
true, str);
247 TfDebug::_ScopedOutput(
false, str);
255 struct TimedScopeHelper {
256 TimedScopeHelper(
bool enabled,
const char* fmt, ...)
273 const std::
string& pattern,
bool value);
312 static
void _RegisterDebugSymbol(
313 T enumVal,
char const *name,
char const *descrip) {
314 static_assert(_Traits<T>::IsDeclared,
315 "Must declare debug codes with TF_DEBUG_CODES()");
316 const int index = static_cast<int>(enumVal);
317 const int numCodes = _Traits<T>::NumCodes;
318 if (ARCH_UNLIKELY(index < 0 || index >= numCodes)) {
319 _ComplainAboutInvalidSymbol(name);
322 _RegisterDebugSymbolImpl(&_GetNode(enumVal), name, descrip);
326 static void _RegisterDebugSymbolImpl(_Node *addr,
char const *enumName,
327 char const *descrip);
335 static constexpr
bool IsDeclared =
false;
341 mutable std::atomic<_NodeState> state;
348 static _Node nodes[_Traits<T>::NumCodes];
352 static _Node &_GetNode(T val) {
353 return _Data<T>::nodes[static_cast<int>(val)];
356 friend class Tf_DebugSymbolRegistry;
359 static void _InitializeNode(_Node &node,
char const *name);
362 static void _ComplainAboutInvalidSymbol(
char const *name);
365 static void _SetNode(_Node &node,
char const *name,
bool state);
368 static void _ScopedOutput(
bool start,
char const *str);
372 TfDebug::_Node TfDebug::_Data<T>::nodes[];
375 struct TfDebug::TimedScopeHelper<false> {
376 TimedScopeHelper(
bool,
const char*, ...)
393 #define TF_DEBUG_CODES(...) \ 394 TF_CONDITIONALLY_COMPILE_TIME_ENABLED_DEBUG_CODES(true, __VA_ARGS__) 414 #define TF_CONDITIONALLY_COMPILE_TIME_ENABLED_DEBUG_CODES(condition, ...) \ 415 enum _TF_DEBUG_ENUM_NAME(__VA_ARGS__) { \ 417 TF_PP_CAT( _TF_DEBUG_ENUM_NAME(__VA_ARGS__), __PAST_END) \ 420 struct TfDebug::_Traits<_TF_DEBUG_ENUM_NAME(__VA_ARGS__)> { \ 421 static constexpr bool IsDeclared = true; \ 422 static constexpr int NumCodes = \ 423 TF_PP_CAT(_TF_DEBUG_ENUM_NAME(__VA_ARGS__), __PAST_END); \ 424 static constexpr bool CompileTimeEnabled = (condition); \ 426 inline char const * \ 427 Tf_DebugGetEnumName(_TF_DEBUG_ENUM_NAME(__VA_ARGS__) val) { \ 428 constexpr char const *CStrings[] = { \ 429 TF_PP_FOR_EACH(_TF_DEBUG_MAKE_STRING, __VA_ARGS__) \ 431 return CStrings[static_cast<int>(val)]; \ 434 #define _TF_DEBUG_MAKE_STRING(x) #x, 439 #define _TF_DEBUG_ENUM_NAME(...) \ 440 TF_PP_CAT(_TF_DEBUG_FIRST_CODE(__VA_ARGS__, dummy), __DebugCodes) 442 #define _TF_DEBUG_FIRST_CODE(first, ...) first 466 #define TF_DEBUG_MSG(enumVal, ...) \ 467 if (!TfDebug::IsEnabled(enumVal)) ; else TfDebug::Helper().Msg(__VA_ARGS__) 501 #define TF_DEBUG(enumVal) \ 502 if (!TfDebug::IsEnabled(enumVal)) ; else TfDebug::Helper() 511 #define TF_INFO(x) TF_DEBUG(x) 540 #define TF_DEBUG_TIMED_SCOPE(enumVal, ...) \ 541 TfDebug::TimedScopeHelper< \ 543 std::decay<decltype(enumVal)>::type>::CompileTimeEnabled> \ 544 TF_PP_CAT(local__TfScopeDebugSwObject, __LINE__)( \ 545 TfDebug::IsEnabled(enumVal), __VA_ARGS__) 565 #define TF_DEBUG_ENVIRONMENT_SYMBOL(VAL, descrip) \ 566 if (TfDebug::_Traits< \ 567 std::decay<decltype(VAL)>::type>::CompileTimeEnabled) { \ 568 TF_ADD_ENUM_NAME(VAL); \ 569 TfDebug::_RegisterDebugSymbol(VAL, #VAL, descrip); \ 574 PXR_NAMESPACE_CLOSE_SCOPE
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.
static void DisableAll()
Mark debugging as disabled for all enum values of type T.
Define function attributes.
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.
Low-cost, high-resolution timer datatype.
Enum-based debugging messages.
static bool IsEnabled(T val)
True if debugging is enabled for the enum value val.
#define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
Macro used to indicate a function takes a printf-like specification.
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.
static TF_API std::string GetDebugSymbolDescriptions()
Get a description of all debug symbols and their purpose.
static size_t GetNumDebugCodes()
Return the number of debugging symbols of this type.
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 TF_API std::string GetDebugSymbolDescription(const std::string &name)
Get a description for the specified debug symbol.
A file containing basic constants and definitions.