From bd43295f7df4c1c1b019c0a71dae43296c89f974 Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Wed, 1 Sep 2021 11:06:40 +0200
Subject: [PATCH] LOG: Send the messages to the queue in a thread safe way,
 clear the loggers from sink cache on destruction

---
 src/Lib/Log.cc   | 25 +++++++++++++------------
 src/Lib/Log.hh   | 21 ++++++++++++++-------
 src/Lib/Utils.hh | 18 ++++++++++++++----
 3 files changed, 41 insertions(+), 23 deletions(-)

diff --git a/src/Lib/Log.cc b/src/Lib/Log.cc
index 461c6945..e09f7480 100644
--- a/src/Lib/Log.cc
+++ b/src/Lib/Log.cc
@@ -3,6 +3,7 @@
 using namespace Vivy;
 
 LogSink::~LogSink() noexcept {}
+Logger::~Logger() noexcept { parentLogSink->closeLoggerClients(); }
 LogMessage::~LogMessage() noexcept { parentLogger->sendLogMessage(*this); }
 
 const chrono::milliseconds
@@ -30,12 +31,19 @@ Logger::sendLogMessage(const LogMessage &msg) const noexcept
     parentLogSink->recieveLogMessage(this, msg);
 }
 
+const std::string_view
+Logger::getCategoryView() const noexcept
+{
+    return std::string_view{ logCategory };
+}
+
 // 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
 {
     const std::lock_guard<std::mutex> messageQueueLockGuard(messageQueueLock);
-    messageQueue.emplace_back(msg);
+    messageQueue.push_back(
+        std::tuple<const std::string_view, const LogMessage>{ logger->getCategoryView(), msg });
 }
 
 std::shared_ptr<LogSink>
@@ -54,18 +62,11 @@ LogSink::registerLoggerClient(std::shared_ptr<Logger> logger) noexcept
 }
 
 void
-LogSink::closeLoggerClient(Logger *const logger) noexcept
-{
-    clientLoggers.erase(std::remove_if(std::begin(clientLoggers), std::end(clientLoggers),
-                                       [logger](const std::shared_ptr<Logger> &ptr) {
-                                           return ptr.get() == logger;
-                                       }));
-}
-
-void
-LogSink::closeLoggerClient(const std::shared_ptr<Logger> &ptr) noexcept
+LogSink::closeLoggerClients() noexcept
 {
-    closeLoggerClient(ptr.get());
+    clientLoggers.erase(
+        std::remove_if(std::begin(clientLoggers), std::end(clientLoggers),
+                       [](const std::weak_ptr<Logger> &weakPtr) { return !weakPtr.expired(); }));
 }
 
 LogMessage
diff --git a/src/Lib/Log.hh b/src/Lib/Log.hh
index 227389ea..a9d4a22b 100644
--- a/src/Lib/Log.hh
+++ b/src/Lib/Log.hh
@@ -47,22 +47,21 @@ enum class LogLevel : int {
 class LogSink {
     VIVY_UNMOVABLE_OBJECT(LogSink)
 
-    LogSink() noexcept = default;
+    explicit LogSink() noexcept = default;
 
 public:
     static std::shared_ptr<LogSink> newSink() noexcept;
     ~LogSink() noexcept;
 
     void registerLoggerClient(std::shared_ptr<Logger>) noexcept;
-    void closeLoggerClient(Logger *const) noexcept;
-    void closeLoggerClient(const std::shared_ptr<Logger> &) noexcept;
+    void closeLoggerClients() noexcept;
 
     void recieveLogMessage(const Logger *const, LogMessage const &) noexcept;
 
 private:
     std::mutex messageQueueLock{};
-    std::vector<LogMessage> messageQueue;
-    std::vector<std::shared_ptr<Logger>> clientLoggers;
+    std::vector<std::tuple<const std::string_view, const LogMessage>> messageQueue;
+    std::vector<std::weak_ptr<Logger>> clientLoggers;
 };
 
 // Message to be logged, constructed by a logger then send
@@ -75,7 +74,11 @@ public:
         const int lineNumberInFile;
     };
 
-    LogMessage(Logger *const, const Header) noexcept;
+    VIVY_DEFAULT_COPY_CTOR(LogMessage)
+    VIVY_DEFAULT_MOVE_CTOR(LogMessage)
+    VIVY_DISABLE_ASSIGN_OPERATORS(LogMessage)
+
+    explicit LogMessage(Logger *const, const Header) noexcept;
     ~LogMessage() noexcept; // The message will be send on destruction
 
     Header const &getHeader() const noexcept;
@@ -123,7 +126,7 @@ class Logger : public std::enable_shared_from_this<Logger> {
 public:
     // Templated constructor, construct from anything that can be considered as
     // a string.
-    Logger(LogSink *const sink, const std::string_view category) noexcept
+    explicit Logger(LogSink *const sink, const std::string_view category) noexcept
         : parentLogSink(sink)
         , logCategory(anyStringToStdString(category))
     {
@@ -131,6 +134,10 @@ public:
         sink->registerLoggerClient(self);
     }
 
+    ~Logger() noexcept;
+
+    const std::string_view getCategoryView() const noexcept;
+
     void sendLogMessage(const 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 da89c510..aca6e2ab 100644
--- a/src/Lib/Utils.hh
+++ b/src/Lib/Utils.hh
@@ -31,13 +31,23 @@ using chrono::duration_cast;
 #define parallel_for \
     _Pragma("omp parallel for") for
 
-// 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 */        \
+// Disable copy and move assign operators
+#define VIVY_DISABLE_ASSIGN_OPERATORS(classname)                        \
     classname &operator=(const classname &) = delete; /* Copy assign */ \
     classname &operator=(classname &&) = delete;      /* Move assign */
 
+// 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 */ \
+    VIVY_DISABLE_ASSIGN_OPERATORS(classname)
+
+#define VIVY_DEFAULT_COPY_CTOR(classname) \
+    explicit classname(const classname &) noexcept = default; /* Copy */
+
+#define VIVY_DEFAULT_MOVE_CTOR(classname) \
+    explicit classname(classname &&) noexcept = default; /* Move  */
+
 // QStringLiteral but for regexes
 #define QRegExpLiteral(str) QRegExp(QStringLiteral(str))
 
-- 
GitLab