diff --git a/docs/changelog/fix-log-scope.md b/docs/changelog/fix-log-scope.md new file mode 100644 index 000000000..50dc9c62f --- /dev/null +++ b/docs/changelog/fix-log-scope.md @@ -0,0 +1,11 @@ +# Fix VTKM_LOG_SCOPE + +The `VTKM_LOG_SCOPE` macro was not working as intended. It was supposed to +print a log message immediately and then print a second log message when +leaving the scope along with the number of seconds that elapsed between the +two messages. + +This was not what was happening. The second log message was being printed +immediately after the first. This is because the scope was taken inside of +the `LogScope` method. The macro has been rewritten to put the tracking in +the right scope. diff --git a/vtkm/cont/Logging.cxx b/vtkm/cont/Logging.cxx index 8c160a55a..02ada4e90 100644 --- a/vtkm/cont/Logging.cxx +++ b/vtkm/cont/Logging.cxx @@ -340,24 +340,50 @@ int getVerbosityByLevel(LogLevel level) return static_cast(level); } +namespace detail +{ + +struct LogScope::InternalStruct : loguru::LogScopeRAII +{ + template + InternalStruct(Ts&&... args) + : loguru::LogScopeRAII(std::forward(args)...) + { + } +}; + VTKM_CONT -void LogScope(LogLevel level, const char* file, unsigned line, const char* format...) +LogScope::LogScope(LogLevel level, const char* file, unsigned line, const char* format...) { auto verbosity = getVerbosityByLevel(level); if (verbosity > loguru::current_verbosity_cutoff()) { - loguru::LogScopeRAII(); + this->Internals = std::make_unique(); } else { va_list args; va_start(args, format); - loguru::LogScopeRAII(verbosity, file, line, format, args); + this->Internals = std::make_unique(verbosity, file, line, format, args); va_end(args); } } +LogScope::~LogScope() = default; + +} // namespace detail + +VTKM_CONT +void LogScope(LogLevel level, const char* file, unsigned line, const char* format...) +{ + // This does not scope right, but neither did the deprecated method this is replacing. + va_list args; + va_start(args, format); + detail::LogScope scopedVar{ level, file, line, format, args }; + va_end(args); +} + VTKM_CONT void LogCond(LogLevel level, bool cond, const char* file, unsigned line, const char* format...) { diff --git a/vtkm/cont/Logging.h b/vtkm/cont/Logging.h index e896589d8..7ca807494 100644 --- a/vtkm/cont/Logging.h +++ b/vtkm/cont/Logging.h @@ -13,11 +13,13 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -187,6 +189,15 @@ /// and then cast appropriately, as described here: /// https://gitlab.kitware.com/vtk/vtk-m/-/issues/358#note_550157 +#define VTKM_CONCAT_IMPL(s1, s2) s1##s2 +#define VTKM_CONCAT(s1, s2) VTKM_CONCAT_IMPL(s1, s2) + +#ifdef __COUNTER__ +#define VTKM_ANONYMOUS_VARIABLE VTKM_CONCAT(vtk_m_anonymous_, __COUNTER__) +#else +#define VTKM_ANONYMOUS_VARIABLE VTKM_CONCAT(vtk_m_anonymous_, __LINE__) +#endif + #if defined(VTKM_ENABLE_LOGGING) #define VTKM_LOG_IF_S(level, cond, ...) \ @@ -198,7 +209,8 @@ #define VTKM_LOG_S(level, ...) VTKM_LOG_IF_S(level, true, __VA_ARGS__) #define VTKM_LOG_F(level, ...) VTKM_LOG_IF_F(level, true, __VA_ARGS__) -#define VTKM_LOG_SCOPE(level, ...) vtkm::cont::LogScope(level, __FILE__, __LINE__, __VA_ARGS__) +#define VTKM_LOG_SCOPE(level, ...) \ + vtkm::cont::detail::LogScope VTKM_ANONYMOUS_VARIABLE { level, __FILE__, __LINE__, __VA_ARGS__ } #define VTKM_LOG_SCOPE_FUNCTION(level) VTKM_LOG_SCOPE(level, __func__) #define VTKM_LOG_ALWAYS_S(level, ...) VTKM_LOG_S(level, __VA_ARGS__) @@ -494,16 +506,37 @@ VTKM_CONT_EXPORT VTKM_CONT void LogCond(LogLevel level, bool cond, const char* file, unsigned line, const char* format...); +namespace detail +{ + /** * \brief Logs a scoped message with a printf-like format. * * The indentation level will be determined based on its LogLevel and it will - * print out its wall time upon exiting its scope. - * - * \param level Desired LogLevel value for the log message. - * \param cond When false this function is no-op. - * \param format Printf like format string. + * print out its wall time upon exiting its scope. The scope starts from when + * the object is created to when it is destroyed. */ +class VTKM_CONT_EXPORT LogScope +{ + struct InternalStruct; + std::unique_ptr Internals; + +public: + /* + * \param level Desired LogLevel value for the log message. + * \param cond When false this function is no-op. + * \param format Printf like format string. + */ + VTKM_CONT + LogScope(LogLevel level, const char* file, unsigned line, const char* format...); + + VTKM_CONT ~LogScope(); +}; + + +} // namespace detail + +VTKM_DEPRECATED(1.9, "Use VTKM_LOG_SCOPE macro.") VTKM_CONT_EXPORT VTKM_CONT void LogScope(LogLevel level, const char* file, unsigned line, const char* format...);