From 9be6036265b62e25e259b59b2fc76bf27daa289d Mon Sep 17 00:00:00 2001 From: NaifBanana <30419422+NaifBanana@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:43:08 -0600 Subject: [PATCH] Refactored to do CRTP. Got multi val init working --- engine/NBCore/DataSink.hpp | 79 ++++++++++------- engine/NBCore/Logger.hpp | 133 +++++++++++++++++++++++------ engine/NBCore/tests/testErrors.cpp | 10 +-- 3 files changed, 161 insertions(+), 61 deletions(-) diff --git a/engine/NBCore/DataSink.hpp b/engine/NBCore/DataSink.hpp index a15a521..75cbad6 100644 --- a/engine/NBCore/DataSink.hpp +++ b/engine/NBCore/DataSink.hpp @@ -33,80 +33,99 @@ class BufferedDataProcessor : public DataSink { using Base = DataSink; public: using Base::Base; - bool in(const DataType& val) { this->push(val); return true;} + + bool stop() noexcept { return type_ptr->stop(); } + bool run() { return type_ptr->run(); } + bool in(const DataType& val) { return type_ptr->in(val); } protected: - virtual unsigned int count() const = 0; - virtual void push(const DataType&) = 0; - virtual DataType pop() = 0; - virtual void flush() = 0; - virtual void clear() = 0; - virtual bool process(const DataType& val) = 0; + unsigned int count() const { + return type_ptr->count(); + } + void push(const DataType& val) { + type_ptr->push(val); + } + DataType pop() { + return type_ptr->pop(); + } + void flush() { + type_ptr->flush(); + } + void clear() { + type_ptr->clear(); + } + bool process(const DataType& val) { + return type_ptr->process(val); + } using Base::_running; BufferType _buffer; + +private: + ProcessorType* const type_ptr = static_cast(this); + }; template -class MultithreadedDataProcessor : public BufferedDataProcessor, ProcessorType> { +class MultithreadedDataProcessor +: public BufferedDataProcessor, ProcessorType> { using Base = BufferedDataProcessor, ProcessorType>; public: - ~MultithreadedDataProcessor() { this->stop(); } + ~MultithreadedDataProcessor() { type_ptr->stop(); } bool isRunning() const noexcept override { - return this->_running && _runningThread; + return this->_running && (_runningThread!=nullptr); } - bool run() override { - if (!isRunning()) { + bool run() { + if (!type_ptr->isRunning()) { this->_running = true; _runningThread = std::make_shared([&]{ - auto this_type = static_cast(this); - while(this_type->isRunning()) { - this_type->flush(); + while(type_ptr->isRunning()) { + flush(); } }); } - return isRunning(); + return this->isRunning(); } bool stop() noexcept override { - if (isRunning()) { + if (type_ptr->isRunning()) { this->_running = false; _runningThread->join(); _runningThread = nullptr; - auto this_type = static_cast(this); } - return !isRunning(); + return !type_ptr->isRunning(); } protected: using Base::Base; - unsigned int count() const override { + unsigned int count() const { return this->_buffer.size(); } - virtual void push(const DataType& val) { + void push(const DataType& val) { this->_buffer.push(val); }; - virtual DataType pop() { + DataType pop() { std::shared_ptr event; this->_buffer.pop(event); - process(*event); + this->process(*event); return *event; } - virtual void flush() override { - auto this_type = static_cast(this); - while(this_type->count()) { - this_type->pop(); + void flush() { + while(type_ptr->count()) { + pop(); } } - virtual void clear() override { + void clear() { this->_buffer.empty(); } - virtual bool process(const DataType&) = 0; - std::shared_ptr _runningThread; + +private: + ProcessorType* type_ptr = static_cast(this); + }; diff --git a/engine/NBCore/Logger.hpp b/engine/NBCore/Logger.hpp index 7319852..30d676c 100644 --- a/engine/NBCore/Logger.hpp +++ b/engine/NBCore/Logger.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -32,30 +33,90 @@ struct LogEvent{ typedef std::string (*LogProcessFunction)(const LoggerTimePoint&, const std::string&); typedef std::unordered_map LogProcessFunctionMap; -/* template -class LoggerBase; - -template -class LoggerBase -: public MultithreadedDataProcessor{ -protected: - typename Logger::StreamType _ostreams; -}; */ - -class DebugLogger : public MultithreadedDataProcessor{ +template +class LoggerBase +: public MultithreadedDataProcessor{ + using StreamType = ST; + using LoggerType = Logger; + using Base = MultithreadedDataProcessor; public: - DebugLogger(std::ostream& stream) : _ostream(&stream) {} + bool run() { + if (!type_ptr->isRunning()) { + this->_running = true; + this->_runningThread = std::make_shared([&]{ + while(type_ptr->isRunning()) { + type_ptr->flush(); + } + type_ptr->flush(); + }); + } + return type_ptr->isRunning(); + } +protected: + LoggerBase() = default; - ~DebugLogger() { stop(); } + StreamType _ostream; - virtual bool stop() noexcept override { - auto ret = MultithreadedDataProcessor::stop(); - flush(); - return ret; +private: + LoggerType* type_ptr = static_cast(this); +}; + +template +struct PackIsType; + +template +struct PackIsType { + const bool value = std::is_base_of::value; +}; + +template +struct PackIsType { + const bool value = std::is_base_of::value && PackIsType::value; +}; + +template +struct StreamRefToPtrVec { + StreamRefToPtrVec(std::vector _vec, Pack1& p1, Pack&... packs) + : vec(_vec) { + static_assert(std::is_base_of::value); + vec.push_back(&p1); + vec = StreamRefToPtrVec(vec, packs...).vec; } + StreamRefToPtrVec(Pack1& p1, Pack&... packs) + : StreamRefToPtrVec({}, p1, packs...) {} + + std::vector vec; +}; + +template +struct StreamRefToPtrVec { + StreamRefToPtrVec(std::vector _vec, Pack& p1) + : vec(_vec) { + static_assert(std::is_base_of::value); + vec.push_back(&p1); + } + + StreamRefToPtrVec(Pack& p1) + : StreamRefToPtrVec({}, p1) {} + + std::vector vec; +}; + +template +class DebugLogger : public LoggerBase>{ + using StreamType = std::vector; + using LoggerType = LT; + using Base = LoggerBase; +public: + + template + DebugLogger(ST&... streams) : _ostream(StreamRefToPtrVec(streams...).vec) {} + + ~DebugLogger() { type_ptr->stop(); } + void log(const std::string& msg, const uint8_t& lvl=0xFF) { - push(LogEvent{ + type_ptr->push(LogEvent{ std::chrono::system_clock::now(), lvl, msg, @@ -66,27 +127,47 @@ public: template void log(char const(&msg) [N], const uint8_t& lvl=0xFF) { - log(std::string(msg), lvl); + type_ptr->log(std::string(msg), lvl); } void log(const std::exception& err, const uint8_t& lvl=0xFF) { - log(err.what(), lvl); + type_ptr->log(err.what(), lvl); } template - void warn(const U& val, const uint8_t& lvl=0x01) { log(val, lvl); } + void warn(const U& val, const uint8_t& lvl=0x01) { type_ptr->log(val, lvl); } template - void error(const U& val, const uint8_t& lvl=0xFF) { log(val, lvl); } + void error(const U& val) { type_ptr->log(val, 0xFF); } protected: - std::ostream* const _ostream; + std::vector _ostream; - virtual bool process(const LogEvent& msg) override { - *_ostream << msg.pid << " - " << msg.tid << " : " << msg.msg << "\n"; +private: + LoggerType* type_ptr = static_cast(this); + +}; + +class DefaultDebugLogger : public DebugLogger { + using LoggerType = DefaultDebugLogger; + using Base = DebugLogger; +public: + using Base::Base; + + ~DefaultDebugLogger() { stop(); } + + friend class BufferedDataProcessor, DefaultDebugLogger>; + +protected: + using Base::_ostream; + + bool process(const LogEvent& msg) { + for (const auto os : this->_ostream) { + (*os) << msg.pid << " - " << msg.tid << " : " << msg.msg << "\n"; + } return true; } - + }; /* class BasicLogger : public LoggerBase { diff --git a/engine/NBCore/tests/testErrors.cpp b/engine/NBCore/tests/testErrors.cpp index 5999c86..196ab32 100644 --- a/engine/NBCore/tests/testErrors.cpp +++ b/engine/NBCore/tests/testErrors.cpp @@ -30,11 +30,11 @@ const ErrorCodeMap TestError::ErrorMessages{ TEST(ErrorTest, Test) { EXPECT_EQ(1, 1); - nb::DebugLogger log(std::cout); - ASSERT_TRUE(log.run()); - ASSERT_TRUE(log.isRunning()); - while (!log.isRunning()){ + nb::DefaultDebugLogger logr(std::cout, std::cout, std::cout); + ASSERT_TRUE(logr.run()); + ASSERT_TRUE(logr.isRunning()); + while (!logr.isRunning()){ 1+1; } - log.log("Hey!"); + logr.log("Hey!"); } \ No newline at end of file