diff --git a/src/Lib/Log.cc b/src/Lib/Log.cc index a30d0193057ddb1e3c13beaf118a5a7bf0637a02..35d84b25e3453026386a144b5237b52bf7f8129b 100644 --- a/src/Lib/Log.cc +++ b/src/Lib/Log.cc @@ -5,12 +5,6 @@ namespace Vivy { LogSinkDispatcher::~LogSinkDispatcher() noexcept {} -const std::string_view -LogSinkDispatcher::getDispatcherName() const noexcept -{ - return dispatcherName; -} - StderrLogSinkDispatcher::StderrLogSinkDispatcher(LogSink *const sink) noexcept : LogSinkDispatcher(sink, std::string_view{ "stderr" }) { @@ -31,11 +25,11 @@ LogSink::~LogSink() noexcept {} // Get the log message from the logger and add it to the sink's queue. void -LogSink::recieveLogMessage(const Logger *const logger, LogMessage const &msg) noexcept +LogSink::recieveLogMessage(const Logger *const logger, LogMessage &&msg) noexcept { const std::lock_guard<std::mutex> messageQueueLockGuard(messageQueueLock); - messageQueue.push_back( - std::tuple<const std::string_view, const LogMessage>{ logger->getCategoryView(), msg }); + messageQueue.emplace_back(std::make_tuple<const std::string_view, LogMessage>( + logger->getCategoryView(), std::move(msg.sink()))); } // Flush all LogMessages to all of the LogSinkDispatchers. Also clear the message queue. @@ -43,12 +37,9 @@ void LogSink::flush() noexcept { const std::lock_guard<std::mutex> messageQueueLockGuard(messageQueueLock); - for (std::weak_ptr<LogSinkDispatcher> weakDispatcher : logDispatchers) { - std::shared_ptr<LogSinkDispatcher> dispatcher = weakDispatcher.lock(); - if (dispatcher) { - for (const auto &[category, msg] : messageQueue) - dispatcher->handleLogMessage(category, msg); - } + for (std::shared_ptr<LogSinkDispatcher> dispatcher : logDispatchers) { + for (const auto &[category, msg] : messageQueue) + dispatcher->handleLogMessage(category, msg); } messageQueue.clear(); } @@ -62,57 +53,20 @@ LogSink::newSink() noexcept return std::make_shared<makeSharedEnabler>(); } -void -LogSink::registerLoggerClient(std::shared_ptr<Logger> logger) noexcept -{ - clientLoggers.push_back(logger); -} - -void -LogSink::registerLogDispatcher(std::shared_ptr<LogSinkDispatcher> dispatcher) noexcept -{ - logDispatchers.push_back(dispatcher); -} - -void -LogSink::closeLoggerClients() noexcept -{ - clientLoggers.erase( - std::remove_if(std::begin(clientLoggers), std::end(clientLoggers), - [](const std::weak_ptr<Logger> &weakPtr) { return !weakPtr.expired(); })); -} - -std::shared_ptr<Logger> -LogSink::getLoggerClient(const std::string_view category) const -{ - return getSharedPtr(clientLoggers, [category](std::shared_ptr<Logger> ptr) noexcept -> bool { - return ptr->getCategoryView() == category; - }); -} - -std::shared_ptr<LogSinkDispatcher> -LogSink::getLogDispatcher(const std::string_view name) const -{ - return getSharedPtr(logDispatchers, - [name](std::shared_ptr<LogSinkDispatcher> ptr) noexcept -> bool { - return ptr->getDispatcherName() == name; - }); -} +// void +// LogSink::registerLogDispatcher(std::shared_ptr<LogSinkDispatcher> dispatcher) noexcept +// { +// logDispatchers.push_back(dispatcher); +// } } // Vivy::Logger implementation namespace Vivy { void -Logger::sendLogMessage(const LogMessage &msg) const noexcept -{ - parentLogSink->recieveLogMessage(this, msg); -} - -const std::string_view -Logger::getCategoryView() const noexcept +Logger::sendLogMessage(LogMessage &&msg) const noexcept { - return std::string_view{ logCategory }; + parentLogSink->recieveLogMessage(this, std::move(msg)); } LogMessage @@ -125,18 +79,33 @@ Logger::logEvent(const char *fileName, const char *functionName, const int lineN .lineNumberInFile = lineNumber }); } -Logger::~Logger() noexcept { parentLogSink->closeLoggerClients(); } +Logger::~Logger() noexcept {} } // Vivy::LogMessage implementation namespace Vivy { -LogMessage::LogMessage(Logger *const logger, const LogMessage::Header hdr) noexcept +LogMessage::LogMessage(const Logger *const logger, const LogMessage::Header hdr) noexcept : messageHeader(hdr) , parentLogger(logger) { } +LogMessage::LogMessage(LogMessage &&other) noexcept + : messageHeader(other.messageHeader) + , parentLogger(other.parentLogger) +{ + std::memcpy(this, &other, sizeof(LogMessage)); + std::memset(&other, 0, sizeof(LogMessage)); +} + +LogMessage && +LogMessage::sink() noexcept +{ + parentLogger = nullptr; + return std::move(*this); +} + LogMessage & LogMessage::operator<<(const std::string &msg) noexcept { @@ -173,18 +142,6 @@ LogMessage::operator<<(const char *str) noexcept return *this; } -const chrono::milliseconds -LogMessage::getTimeStamp() const noexcept -{ - return timeStamp; -} - -LogMessage::Header const & -LogMessage::getHeader() const noexcept -{ - return messageHeader; -} - const std::string_view LogMessage::getTextBuffer() const noexcept { @@ -192,5 +149,9 @@ LogMessage::getTextBuffer() const noexcept return std::string_view{ txt, strlen(txt) }; } -LogMessage::~LogMessage() noexcept { parentLogger->sendLogMessage(*this); } +LogMessage::~LogMessage() noexcept +{ + if (parentLogger) + parentLogger->sendLogMessage(std::move(*this)); +} } diff --git a/src/Lib/Log.hh b/src/Lib/Log.hh index c74b0b05be69433ccfef35a410863acc37dab87f..5d507dafa7a3677caa18a74dacb3b6376c0fce62 100644 --- a/src/Lib/Log.hh +++ b/src/Lib/Log.hh @@ -49,45 +49,25 @@ class LogSink { explicit LogSink() noexcept = default; - template <typename T> - std::shared_ptr<T> getSharedPtr(std::vector<std::weak_ptr<T>> weakPtrList, auto nameCheck) const - { - std::shared_ptr<T> sharedPtr(nullptr); - auto end = std::end(weakPtrList); - auto it = std::find_if(std::begin(weakPtrList), end, - [&nameCheck, &sharedPtr](const std::weak_ptr<T> &weakPtr) { - sharedPtr = weakPtr.lock(); - return sharedPtr && nameCheck(sharedPtr); - }); - if (it == end || sharedPtr == nullptr) - throw std::logic_error("Pointer was not found or has expired"); - return sharedPtr; - } - public: static std::shared_ptr<LogSink> newSink() noexcept; ~LogSink() noexcept; - void recieveLogMessage(const Logger *const, LogMessage const &) noexcept; - - void registerLoggerClient(std::shared_ptr<Logger>) noexcept; - void registerLogDispatcher(std::shared_ptr<LogSinkDispatcher>) noexcept; - void closeLoggerClients() noexcept; - std::shared_ptr<Logger> getLoggerClient(const std::string_view category) const; - std::shared_ptr<LogSinkDispatcher> getLogDispatcher(const std::string_view category) const; - + void recieveLogMessage(const Logger *const, LogMessage &&) noexcept; void flush() noexcept; private: std::mutex messageQueueLock{}; - std::vector<std::tuple<const std::string_view, const LogMessage>> messageQueue; - std::vector<std::weak_ptr<Logger>> clientLoggers; - std::vector<std::weak_ptr<LogSinkDispatcher>> logDispatchers; + std::vector<std::tuple<const std::string_view, LogMessage>> messageQueue; + std::vector<std::shared_ptr<LogSinkDispatcher>> logDispatchers; }; // Message to be logged, constructed by a logger then send class LogMessage final { public: + using TimeStamp = chrono::milliseconds; + + // The header of the LogMessage struct Header final { const char *fileName; const char *functionName; @@ -95,32 +75,35 @@ public: const int lineNumberInFile; }; - VIVY_DEFAULT_COPY_CTOR(LogMessage) - VIVY_DEFAULT_MOVE_CTOR(LogMessage) +private: + const Header messageHeader; + const TimeStamp timeStamp{ duration_cast<TimeStamp>( + chrono::system_clock::now().time_since_epoch()) }; + + static constexpr inline size_t messageBufferLength = 2048; + std::array<char, messageBufferLength> textBuffer{}; + std::size_t indexInArray{ 0 }; + const Logger *parentLogger{ nullptr }; + +public: + VIVY_DISABLE_COPY_CTOR(LogMessage) VIVY_DISABLE_ASSIGN_OPERATORS(LogMessage) - explicit LogMessage(Logger *const, const Header) noexcept; + explicit LogMessage(const Logger *const, const Header) noexcept; + explicit LogMessage(LogMessage &&) noexcept; ~LogMessage() noexcept; // The message will be send on destruction - Header const &getHeader() const noexcept; + Header const &getHeader() const noexcept { return messageHeader; } const std::string_view getTextBuffer() const noexcept; - const chrono::milliseconds getTimeStamp() const noexcept; + const TimeStamp getTimeStamp() const noexcept { return timeStamp; } + + LogMessage &&sink() noexcept; LogMessage &operator<<(const std::string &) noexcept; LogMessage &operator<<(const QString &) noexcept; LogMessage &operator<<(const char *) noexcept; LogMessage &operator<<(const int) noexcept; LogMessage &operator<<(const long) noexcept; - -private: - const Header messageHeader; - const chrono::milliseconds timeStamp{ duration_cast<chrono::milliseconds>( - chrono::system_clock::now().time_since_epoch()) }; - - static constexpr inline size_t messageBufferLength = 2048; - std::array<char, messageBufferLength> textBuffer{}; - std::size_t indexInArray{ 0 }; - Logger *const parentLogger; }; // A LogSinkDispatcher will excavate LogMessages from the Sink and do something @@ -131,15 +114,15 @@ class LogSinkDispatcher : public std::enable_shared_from_this<LogSinkDispatcher> const std::string dispatcherName; protected: - explicit LogSinkDispatcher(LogSink *const sink, const std::string_view name) noexcept + explicit LogSinkDispatcher(LogSink *const, const std::string_view name) noexcept : dispatcherName(name) { std::shared_ptr<LogSinkDispatcher> self = shared_from_this(); - sink->registerLogDispatcher(self); + // sink->registerLogDispatcher(self); } public: - const std::string_view getDispatcherName() const noexcept; + const std::string_view getDispatcherName() const noexcept { return dispatcherName; } virtual ~LogSinkDispatcher() noexcept; virtual void handleLogMessage(const std::string_view, const LogMessage &) noexcept = 0; @@ -172,15 +155,16 @@ public: : parentLogSink(sink) , logCategory(anyStringToStdString(category)) { - std::shared_ptr<Logger> self = shared_from_this(); - sink->registerLoggerClient(self); } ~Logger() noexcept; - const std::string_view getCategoryView() const noexcept; + const std::string_view getCategoryView() const noexcept + { + return std::string_view{ logCategory }; + } - void sendLogMessage(const LogMessage &) const noexcept; + void sendLogMessage(LogMessage &&) const noexcept; LogMessage logEvent(const char *fileName, const char *functionName, const int lineNumber, const LogLevel) noexcept; }; diff --git a/src/Lib/Utils.hh b/src/Lib/Utils.hh index aca6e2ab50e95c6ade5166cab282cec9dea9a486..ff65ad6d5c475aa4ad1572db9cfea1aea21a2dd6 100644 --- a/src/Lib/Utils.hh +++ b/src/Lib/Utils.hh @@ -36,10 +36,13 @@ using chrono::duration_cast; classname &operator=(const classname &) = delete; /* Copy assign */ \ classname &operator=(classname &&) = delete; /* Move assign */ +#define VIVY_DISABLE_COPY_CTOR(classname) classname(const classname &) = delete; /* Copy */ +#define VIVY_DISABLE_MOVE_CTOR(classname) classname(classname &&) = delete; /* Move */ + // Don't move this object, create it in one place and never move it again. -#define VIVY_UNMOVABLE_OBJECT(classname) \ - classname(const classname &) = delete; /* Copy */ \ - classname(classname &&) = delete; /* Move */ \ +#define VIVY_UNMOVABLE_OBJECT(classname) \ + VIVY_DISABLE_COPY_CTOR(classname) \ + VIVY_DISABLE_MOVE_CTOR(classname) \ VIVY_DISABLE_ASSIGN_OPERATORS(classname) #define VIVY_DEFAULT_COPY_CTOR(classname) \