From 7033474455d3cef305bcdd7795960802d5eb4ef0 Mon Sep 17 00:00:00 2001 From: Brett Date: Thu, 20 Jul 2023 21:44:52 -0400 Subject: [PATCH] memory\!, working on logging! --- include/blt/profiling/profiler.h | 2 +- include/blt/std/logging.h | 56 +++++++++++--------- include/blt/std/memory.h | 91 ++++++++++++++++++++++++++++++++ src/blt/profiling/profiler.cpp | 4 +- src/blt/std/logging.cpp | 18 ++++--- src/tests/profiling_tests.h | 2 +- src/tests/queue_tests.h | 6 +-- 7 files changed, 140 insertions(+), 39 deletions(-) diff --git a/include/blt/profiling/profiler.h b/include/blt/profiling/profiler.h index 1f18d85..f9b3a68 100644 --- a/include/blt/profiling/profiler.h +++ b/include/blt/profiling/profiler.h @@ -54,7 +54,7 @@ namespace blt::profiling { profile getProfile(const std::string& profileName); void printProfile( - const std::string& profileName, logging::LOG_LEVEL loggingLevel = logging::BLT_NONE, + const std::string& profileName, logging::LogLevel loggingLevel = logging::LogLevel::NONE, bool averageHistory = false ); diff --git a/include/blt/std/logging.h b/include/blt/std/logging.h index e333620..d2bff9c 100644 --- a/include/blt/std/logging.h +++ b/include/blt/std/logging.h @@ -13,13 +13,21 @@ namespace blt::logging { - enum LOG_LEVEL { + enum class LogLevel { + // low level + TRACE0, TRACE1, TRACE2, TRACE3, // normal - BLT_TRACE = 0, BLT_DEBUG = 1, BLT_INFO = 2, + TRACE, DEBUG, INFO, + WARN, // errors - BLT_WARN = 3, BLT_ERROR = 4, BLT_FATAL = 5, + ERROR, FATAL, // default - BLT_NONE = 6 + NONE + }; + + class ILogHandler { + public: + virtual void log(std::string message, LogLevel level) = 0; }; struct LOG_PROPERTIES { @@ -31,7 +39,7 @@ namespace blt::logging { // print the whole path or just the file name? bool m_logFullPath = false; const char* m_directory = "./"; - LOG_LEVEL minLevel = BLT_TRACE; + LogLevel minLevel = LogLevel::TRACE; explicit constexpr LOG_PROPERTIES( bool useColor, bool logToConsole, bool logToFile, const char* directory @@ -43,7 +51,7 @@ namespace blt::logging { }; struct logger { - LOG_LEVEL level; + LogLevel level; void log_internal(const std::string& str) const; // evil hack, todo: better way @@ -64,18 +72,18 @@ namespace blt::logging { static void flush_all(); }; - static logger std_out{BLT_NONE}; + static logger std_out{LogLevel::NONE}; - static logger trace{BLT_TRACE}; - static logger debug{BLT_DEBUG}; - static logger info{BLT_INFO}; - static logger warn{BLT_WARN}; - static logger error{BLT_ERROR}; - static logger fatal{BLT_FATAL}; + static logger trace{LogLevel::TRACE}; + static logger debug{LogLevel::DEBUG}; + static logger info{LogLevel::INFO}; + static logger warn{LogLevel::WARN}; + static logger error{LogLevel::ERROR}; + static logger fatal{LogLevel::FATAL}; - static inline logger& getLoggerFromLevel(LOG_LEVEL level) { - static logger loggerLevelDecode[7]{trace, debug, info, warn, error, fatal, std_out}; - return loggerLevelDecode[level]; + static inline logger& getLoggerFromLevel(LogLevel level) { + static logger loggerLevelDecode[11]{trace, trace, trace, trace, trace, debug, info, warn, error, fatal, std_out}; + return loggerLevelDecode[(int)level]; } static inline logger& operator<<(logger& out, const std::string& str) { @@ -92,7 +100,7 @@ namespace blt::logging { void init(LOG_PROPERTIES properties); void log_internal( - const std::string& format, LOG_LEVEL level, const char* file, int currentLine, + const std::string& format, LogLevel level, const char* file, int currentLine, int auto_line, ... ); @@ -111,7 +119,7 @@ namespace blt::logging { */ template::value>::type* = nullptr> inline void log_internal( - T t, LOG_LEVEL level, const char* file, int currentLine, int auto_line + T t, LogLevel level, const char* file, int currentLine, int auto_line ) { log_internal(std::to_string(t), level, file, currentLine, auto_line); } @@ -133,12 +141,12 @@ namespace blt::logging { #define BLT_FATAL(format, ...) #else #ifndef BLT_DISABLE_LOGGING - #define BLT_TRACE(format, ...) log_internal(format, blt::logging::BLT_TRACE, __FILE__, __LINE__, true, ##__VA_ARGS__) - #define BLT_DEBUG(format, ...) log_internal(format, blt::logging::BLT_DEBUG, __FILE__, __LINE__, true, ##__VA_ARGS__) - #define BLT_INFO(format, ...) log_internal(format, blt::logging::BLT_INFO, __FILE__, __LINE__, true, ##__VA_ARGS__) - #define BLT_WARN(format, ...) log_internal(format, blt::logging::BLT_WARN, __FILE__, __LINE__, true, ##__VA_ARGS__) - #define BLT_ERROR(format, ...) log_internal(format, blt::logging::BLT_ERROR, __FILE__, __LINE__, true, ##__VA_ARGS__) - #define BLT_FATAL(format, ...) log_internal(format, blt::logging::BLT_FATAL, __FILE__, __LINE__, true, ##__VA_ARGS__) + #define BLT_TRACE(format, ...) log_internal(format, blt::logging::LogLevel::TRACE, __FILE__, __LINE__, true, ##__VA_ARGS__) + #define BLT_DEBUG(format, ...) log_internal(format, blt::logging::LogLevel::DEBUG, __FILE__, __LINE__, true, ##__VA_ARGS__) + #define BLT_INFO(format, ...) log_internal(format, blt::logging::LogLevel::INFO, __FILE__, __LINE__, true, ##__VA_ARGS__) + #define BLT_WARN(format, ...) log_internal(format, blt::logging::LogLevel::WARN, __FILE__, __LINE__, true, ##__VA_ARGS__) + #define BLT_ERROR(format, ...) log_internal(format, blt::logging::LogLevel::ERROR, __FILE__, __LINE__, true, ##__VA_ARGS__) + #define BLT_FATAL(format, ...) log_internal(format, blt::logging::LogLevel::FATAL, __FILE__, __LINE__, true, ##__VA_ARGS__) #endif #endif diff --git a/include/blt/std/memory.h b/include/blt/std/memory.h index 6c7b4d6..c82ef5e 100644 --- a/include/blt/std/memory.h +++ b/include/blt/std/memory.h @@ -7,7 +7,53 @@ #ifndef BLT_TESTS_MEMORY_H #define BLT_TESTS_MEMORY_H +#include +#include + namespace blt { + + template + struct ptr_iterator { + public: + using iterator_category = std::random_access_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = V; + using pointer = value_type*; + using reference = value_type&; + + explicit ptr_iterator(V* v): _v(v) {} + + reference operator*() const { return *_v; } + pointer operator->() { return _v; } + ptr_iterator& operator++() { + _v++; + return *this; + } + ptr_iterator& operator--() { + _v--; + return *this; + } + ptr_iterator operator++(int){ + auto tmp = *this; + ++(*this); + return tmp; + } + ptr_iterator operator--(int){ + auto tmp = *this; + --(*this); + return tmp; + } + friend bool operator==(const ptr_iterator& a, const ptr_iterator& b) { + return a._v == b._v; + } + friend bool operator!=(const ptr_iterator& a, const ptr_iterator& b) { + return a._v != b._v; + } + + private: + V* _v; + }; + /** * Creates an encapsulation of a T array which will be automatically deleted when this object goes out of scope. * This is a simple buffer meant to be used only inside of a function and not moved around, with a few minor exceptions. @@ -77,6 +123,51 @@ namespace blt { ~nullptr_initializer() = default; }; + + /** + * Creates a hash-map like association between an enum key and any arbitrary value. + * The storage is backed by a contiguous array for faster access. + * @tparam K enum value + * @tparam V associated value + */ + template + class enum_storage { + private: + V* _values; + size_t _size = 0; + public: + + + enum_storage(std::initializer_list> init){ + for (auto& i : init) + _size = std::max((size_t)i, _size); + _values = new V[_size]; + } + + inline V& operator[](size_t index){ + return _values[index]; + } + + inline const V& operator[](size_t index) const { + return _values[index]; + } + + [[nodiscard]] inline size_t size() const { + return _size; + } + + ptr_iterator begin(){ + return ptr_iterator{_values}; + } + + ptr_iterator end(){ + return ptr_iterator{&_values[_size]}; + } + + ~enum_storage(){ + delete[] _values; + } + }; } #endif //BLT_TESTS_MEMORY_H diff --git a/src/blt/profiling/profiler.cpp b/src/blt/profiling/profiler.cpp index a632388..3c43abc 100644 --- a/src/blt/profiling/profiler.cpp +++ b/src/blt/profiling/profiler.cpp @@ -30,7 +30,7 @@ namespace blt::profiling { difference(difference), name(std::move(name)), total(total) {} }; - inline void println(const std::vector&& lines, logging::LOG_LEVEL level) { + inline void println(const std::vector&& lines, logging::LogLevel level) { auto& logger = logging::getLoggerFromLevel(level); for (const auto& line : lines) logger << line << "\n"; @@ -104,7 +104,7 @@ namespace blt::profiling { } void printProfile( - const std::string& profileName, logging::LOG_LEVEL loggingLevel, bool averageHistory + const std::string& profileName, logging::LogLevel loggingLevel, bool averageHistory ) { auto& profile = profiles[profileName]; const auto& intervals = profile.intervals; diff --git a/src/blt/std/logging.cpp b/src/blt/std/logging.cpp index 66313d6..f046b7b 100644 --- a/src/blt/std/logging.cpp +++ b/src/blt/std/logging.cpp @@ -22,6 +22,8 @@ // https://publications.gbdirect.co.uk//c_book/chapter9/stdarg.html // https://cplusplus.com/reference/cstdio/printf/ +#include + namespace blt::logging { @@ -120,7 +122,7 @@ namespace blt::logging { return final; } - inline void log(const std::string& str, bool hasEndingLinefeed, LOG_LEVEL level, const char* file, int currentLine, int auto_line){ + inline void log(const std::string& str, bool hasEndingLinefeed, LogLevel level, const char* file, int currentLine, int auto_line){ if (level < BLT_LOGGING_PROPERTIES.minLevel) return; std::string outputString = system::getTimeStringLog(); @@ -133,13 +135,13 @@ namespace blt::logging { outputString += "] "; } - outputString += levelNames[level]; + outputString += levelNames[(int)level]; outputString += str; std::string fileString = outputString; if (BLT_LOGGING_PROPERTIES.m_useColor) { - outputString = levelColors[level] + outputString; + outputString = levelColors[(int)level] + outputString; outputString += "\033[0m"; } @@ -149,7 +151,7 @@ namespace blt::logging { } if (BLT_LOGGING_PROPERTIES.m_logToConsole) { - if (level > BLT_WARN) + if (level > LogLevel::WARN) std::cerr << outputString; else std::cout << outputString; @@ -160,7 +162,7 @@ namespace blt::logging { } } - void log_internal(const std::string& format, LOG_LEVEL level, const char* file, int currentLine, int auto_line, ...) { + void log_internal(const std::string& format, LogLevel level, const char* file, int currentLine, int auto_line, ...) { va_list args; va_start(args, auto_line); @@ -181,7 +183,7 @@ namespace blt::logging { } // stores an association between thread -> log level -> current line buffer - std::unordered_map> thread_local_strings; + std::unordered_map> thread_local_strings; void logger::log_internal(const std::string& str) const { auto id = std::this_thread::get_id(); @@ -191,7 +193,7 @@ namespace blt::logging { if (blt::string::contains(str, "\n")){ // make sure new lines are properly formatted to prevent danging lines. Ie "[trace]: .... [debug]: ...." bool hasEndingLinefeed = str[str.length()-1] == '\n'; - if (level == BLT_NONE) { + if (level == LogLevel::NONE) { std::cout << th_str; } else logging::log(th_str, false, level, "", -1, !hasEndingLinefeed); @@ -201,7 +203,7 @@ namespace blt::logging { } } - void flushLogger_internal(std::thread::id id, LOG_LEVEL level){ + void flushLogger_internal(std::thread::id id, LogLevel level){ auto th_str = thread_local_strings[id][level]; if (th_str.empty()) return; diff --git a/src/tests/profiling_tests.h b/src/tests/profiling_tests.h index bd3d1e5..485a4ad 100644 --- a/src/tests/profiling_tests.h +++ b/src/tests/profiling_tests.h @@ -38,7 +38,7 @@ static void runProfilingAndTableTests() { BLT_END_INTERVAL("Help", "UnderSet" + std::to_string(i)); } - BLT_PRINT_PROFILE("Help", blt::logging::LOG_LEVEL::BLT_TRACE); + BLT_PRINT_PROFILE("Help", blt::logging::LogLevel::TRACE); BLT_TRACE(""); blt::string::TableFormatter formatter; diff --git a/src/tests/queue_tests.h b/src/tests/queue_tests.h index eb8a52c..59b6e3b 100644 --- a/src/tests/queue_tests.h +++ b/src/tests/queue_tests.h @@ -140,9 +140,9 @@ static inline void test_queues() { fill_queues(); random_access(); - BLT_PRINT_PROFILE("Insert", blt::logging::LOG_LEVEL::BLT_INFO, true); - BLT_PRINT_PROFILE("Access", blt::logging::LOG_LEVEL::BLT_INFO, true); - BLT_PRINT_PROFILE("Random", blt::logging::LOG_LEVEL::BLT_INFO, true); + BLT_PRINT_PROFILE("Insert", blt::logging::LogLevel::INFO, true); + BLT_PRINT_PROFILE("Access", blt::logging::LogLevel::INFO, true); + BLT_PRINT_PROFILE("Random", blt::logging::LogLevel::INFO, true); } #endif //BLT_TESTS_QUEUE_TESTS_H