.. _program_listing_file_src_navtk_errors.hpp: Program Listing for File errors.hpp =================================== |exhale_lsh| :ref:`Return to documentation for file ` (``src/navtk/errors.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once #include #include #include #include // These includes must appear after #include to prevent linker errors when // formatting complex types such as std::vector. #include #include namespace navtk { enum class ErrorMode { OFF, LOG, DIE }; std::ostream& operator<<(std::ostream& os, ErrorMode error_mode); typedef std::runtime_error DefaultLogOrThrowException; constexpr spdlog::level::level_enum DEFAULT_LOG_OR_THROW_LEVEL = spdlog::level::level_enum::err; ErrorMode get_global_error_mode(); class ErrorModeLock { public: ErrorModeLock(ErrorMode target_mode, bool enable_restore = true); ErrorModeLock(ErrorModeLock&& src); ErrorModeLock(const ErrorModeLock&) = delete; ErrorModeLock& operator=(ErrorModeLock&&) = delete; ErrorModeLock& operator=(const ErrorModeLock&) = delete; virtual ~ErrorModeLock(); protected: void unlock(); void relock(); private: bool restore_enabled; bool restore_needed; std::unique_lock lock; ErrorMode restore_mode; ErrorMode target_mode; }; // TODO(PNTOS-387): optional timeout parameter to prevent deadlocks void set_global_error_mode(ErrorMode mode); #ifndef NEED_DOXYGEN_EXHALE_WORKAROUND // we hide the 'full' implementation of log_or_throw in a detail namespace to prevent infinitely // recursive template evaluation when trying to resolve the overloads -- this allows the other // overloads to invoke detail::log_or_throw and we know we're always invoking the "main" one. // End users can also invoke the main one because of the `using detail::log_or_throw` line below. namespace detail { #endif template void log_or_throw(ErrorMode mode, spdlog::format_string_t fmt, FormatArgs&&... args) { auto message = fmt::format(fmt, std::forward(args)...); if (mode != ErrorMode::OFF) spdlog::log(Level, "{}", message); if (mode == ErrorMode::DIE) throw Exc(std::move(message)); } #ifndef NEED_DOXYGEN_EXHALE_WORKAROUND } using detail::log_or_throw; template void log_or_throw(spdlog::format_string_t fmt, FormatArgs&&... args) { detail::log_or_throw( get_global_error_mode(), fmt, std::forward(args)...); } template void log_or_throw(spdlog::format_string_t fmt, FormatArgs&&... args) { detail::log_or_throw( get_global_error_mode(), fmt, std::forward(args)...); } template void log_or_throw(ErrorMode mode, spdlog::format_string_t fmt, FormatArgs&&... args) { detail::log_or_throw( mode, fmt, std::forward(args)...); } // SEE ALSO: py_log_or_throw_ in bindings/python/navtk.cpp, a re-implementation that uses runtime // values instead of template parameters. #endif // NEED_DOXYGEN_EXHALE_WORKAROUND } // namespace navtk