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;
213 template <
class Enum>
214 explicit _Helper(Enum val) : _enumName(Tf_DebugGetEnumName(val)) {}
215 TF_API
void Msg(
const std::string& msg)
const;
218 char const * const _enumName = "<< no debug code >>";
222 template <
class A1,
class ...Args>
223 static void Msg(
char const *fmt, A1 &&a1, Args && ...args) {
224 return _Helper().Msg(
225 fmt, std::forward<A1>(a1), std::forward<Args>(args)...);
227 static void Msg(
const std::string &msg) {
228 return _Helper().Msg(msg);
235 ScopeHelper(
bool enabled,
const char* name) {
236 if ((active = enabled)) {
238 TfDebug::_ScopedOutput(
true, str);
246 TfDebug::_ScopedOutput(
false, str);
254 struct TimedScopeHelper {
255 TimedScopeHelper(
bool enabled,
const char* fmt, ...)
271 static
std::vector<
std::
string> SetDebugSymbolsByName(
272 const
std::
string& pattern,
bool value);
276 static
bool IsDebugSymbolNameEnabled(const
std::
string& name);
283 static
std::
string GetDebugSymbolDescriptions();
287 static
std::vector<
std::
string> GetDebugSymbolNames();
295 static
std::
string GetDebugSymbolDescription(const
std::
string& name);
304 static
void SetOutputFile(FILE *file);
311 static
void _RegisterDebugSymbol(
312 T enumVal,
char const *name,
char const *descrip) {
313 static_assert(_Traits<T>::IsDeclared,
314 "Must declare debug codes with TF_DEBUG_CODES()");
315 const int index =
static_cast<int>(enumVal);
316 const int numCodes = _Traits<T>::NumCodes;
317 if (ARCH_UNLIKELY(index < 0 || index >= numCodes)) {
318 _ComplainAboutInvalidSymbol(name);
321 _RegisterDebugSymbolImpl(&_GetNode(enumVal), name, descrip);
325 static void _RegisterDebugSymbolImpl(_Node *addr,
char const *enumName,
326 char const *descrip);
334 static constexpr bool IsDeclared =
false;
340 mutable std::atomic<_NodeState> state;
347 static _Node nodes[_Traits<T>::NumCodes];
351 static _Node &_GetNode(T val) {
352 return _Data<T>::nodes[
static_cast<int>(val)];
355 friend class Tf_DebugSymbolRegistry;
358 static void _InitializeNode(_Node &node,
char const *name);
361 static void _ComplainAboutInvalidSymbol(
char const *name);
364 static void _SetNode(_Node &node,
char const *name,
bool state);
367 static void _ScopedOutput(
bool start,
char const *str);
371TfDebug::_Node TfDebug::_Data<T>::nodes[];
374struct TfDebug::TimedScopeHelper<false> {
375 TimedScopeHelper(
bool,
const char*, ...)
392#define TF_DEBUG_CODES(...) \
393 TF_CONDITIONALLY_COMPILE_TIME_ENABLED_DEBUG_CODES(true, __VA_ARGS__)
413#define TF_CONDITIONALLY_COMPILE_TIME_ENABLED_DEBUG_CODES(condition, ...) \
414 enum _TF_DEBUG_ENUM_NAME(__VA_ARGS__) { \
416 TF_PP_CAT( _TF_DEBUG_ENUM_NAME(__VA_ARGS__), __PAST_END) \
419 struct TfDebug::_Traits<_TF_DEBUG_ENUM_NAME(__VA_ARGS__)> { \
420 static constexpr bool IsDeclared = true; \
421 static constexpr int NumCodes = \
422 TF_PP_CAT(_TF_DEBUG_ENUM_NAME(__VA_ARGS__), __PAST_END); \
423 static constexpr bool CompileTimeEnabled = (condition); \
425 inline char const * \
426 Tf_DebugGetEnumName(_TF_DEBUG_ENUM_NAME(__VA_ARGS__) val) { \
427 constexpr char const *CStrings[] = { \
428 TF_PP_FOR_EACH(_TF_DEBUG_MAKE_STRING, __VA_ARGS__) \
430 return CStrings[static_cast<int>(val)]; \
433#define _TF_DEBUG_MAKE_STRING(x) #x,
438#define _TF_DEBUG_ENUM_NAME(...) \
439 TF_PP_CAT(_TF_DEBUG_FIRST_CODE(__VA_ARGS__, dummy), __DebugCodes)
441#define _TF_DEBUG_FIRST_CODE(first, ...) first
465#define TF_DEBUG_MSG(enumVal, ...) \
466 if (!TfDebug::IsEnabled(enumVal)) ; \
467 else TfDebug::_Helper(enumVal).Msg(__VA_ARGS__)
501#define TF_DEBUG(enumVal) \
502 if (!TfDebug::IsEnabled(enumVal)) ; \
503 else TfDebug::_Helper(enumVal)
512#define TF_INFO(x) TF_DEBUG(x)
541#define TF_DEBUG_TIMED_SCOPE(enumVal, ...) \
542 TfDebug::TimedScopeHelper< \
544 std::decay<decltype(enumVal)>::type>::CompileTimeEnabled> \
545 TF_PP_CAT(local__TfScopeDebugSwObject, __LINE__)( \
546 TfDebug::IsEnabled(enumVal), __VA_ARGS__)
566#define TF_DEBUG_ENVIRONMENT_SYMBOL(VAL, descrip) \
567 if (TfDebug::_Traits< \
568 std::decay<decltype(VAL)>::type>::CompileTimeEnabled) { \
569 TF_ADD_ENUM_NAME(VAL); \
570 TfDebug::_RegisterDebugSymbol(VAL, #VAL, descrip); \
575PXR_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.