From e9ca6a04e7996ef8d9fd8495caa65664c507daa4 Mon Sep 17 00:00:00 2001
From: janis <janis@nirgendwo.xyz>
Date: Mon, 20 Jun 2022 21:10:15 +0100
Subject: [PATCH] threaded flusher

---
 .gitignore     |  1 +
 src/journal.cc | 57 ++++++++++++++++++++++++++++++++++++++------------
 src/main.cc    |  8 ++++++-
 test.log       |  3 ---
 4 files changed, 52 insertions(+), 17 deletions(-)
 delete mode 100644 test.log

diff --git a/.gitignore b/.gitignore
index f6df8e6..bd3ccd6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 .cache/
 target/
 compile_commands.json
+test.log
diff --git a/src/journal.cc b/src/journal.cc
index aded530..6c0e075 100644
--- a/src/journal.cc
+++ b/src/journal.cc
@@ -10,7 +10,9 @@
 #include <mutex>
 #include <optional>
 #include <ostream>
+#include <stop_token>
 #include <string_view>
+#include <thread>
 
 namespace journal {
 namespace mutex {
@@ -176,10 +178,10 @@ struct Verbosity {
   }
 };
 
-namespace sinks {
-
 using namespace std::chrono_literals;
 
+namespace sinks {
+
 struct BaseSink {
   Verbosity min_verbosity;
   Verbosity max_verbosity;
@@ -255,25 +257,44 @@ struct FileSink : public OStreamSink {
       : OStreamSink(std::make_shared<std::ofstream>(file_path, open_mode), min,
                     max) {}
 };
+
 } // namespace sinks
 
+static auto try_flush_all_loop(std::stop_token) -> void;
+
 class Journal {
   std::vector<std::unique_ptr<sinks::BaseSink>> sinks;
+  std::jthread flush_thread;
 
 public:
-Journal() {}
-auto log(const Verbosity &verbosity, source_location source,
-         std::string_view msg) {
-  const auto now = std::chrono::system_clock::now();
-  for (auto &&sink : sinks) {
-    if (sink->should_sink_verbosity(verbosity)) {
-      (*sink) << format(msg, verbosity, source);
-    }
-    if (sink->should_flush()) {
-      sink->flush();
+  Journal() { flush_thread = std::jthread(&detail::try_flush_all_loop); }
+  ~Journal() {
+    log(LogVerbosity::Trace, source_location::current(),
+        "Requesting stop for flush thread");
+    flush_thread.request_stop();
+    log(LogVerbosity::Trace, source_location::current(),
+        "Waiting for flush thread to join..");
+    flush_thread.join();
+    log(LogVerbosity::Trace, source_location::current(), "Flush thread joined");
+    try_flush_all();
+  }
+
+  auto try_flush_all() -> void {
+    for (auto &&sink : sinks) {
+      if (sink->should_flush()) {
+        sink->flush();
+      }
+    }
+  }
+
+  auto log(const Verbosity &verbosity, source_location source,
+           std::string_view msg) -> void {
+    for (auto &&sink : sinks) {
+      if (sink->should_sink_verbosity(verbosity)) {
+        (*sink) << format(msg, verbosity, source);
+      }
     }
   }
-}
 
 auto format(std::string_view str, const Verbosity &verbosity,
             const source_location &source) -> std::string {
@@ -310,6 +331,16 @@ auto add_std_err() { add_sink(std::make_unique<sinks::StdErrSink>()); }
 
 static mutex::Mutex<std::unique_ptr<Journal>> global_journal;
 
+static auto try_flush_all_loop(std::stop_token stoken) -> void {
+  while (!stoken.stop_requested()) {
+    {
+      auto &&[lock, ref] = global_journal.mut();
+      ref->try_flush_all();
+    }
+    std::this_thread::sleep_for(5s);
+  }
+}
+
 auto log_internal(const LogVerbosity &verbosity, detail::source_location source,
                   const std::string &msg) -> void {
   auto &&[lock, ref] = global_journal.ref();
diff --git a/src/main.cc b/src/main.cc
index 876a421..5ae5d46 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -1,13 +1,19 @@
-#include <stdio.h>
 #include "journal.hpp"
 #include <iostream>
+#include <sstream>
+#include <stdio.h>
 
 int main(int argc, const char* argv[]) {
+  auto stream = std::make_shared<std::stringstream>();
+
   journal::init_std_out_err();
+  journal::add_sink(stream, journal::LogVerbosity::Warn);
   journal::add_file("test.log");
   journal::info("some info!");
   journal::error("something went wrong!");
+  journal::warn("something went slightly wrong!");
   std::cin.get();
+  std::cout << "stream content: \n" << stream->view() << "\n";
   journal::trace("just some very verbose stuff here");
   return 1;
 }
\ No newline at end of file
diff --git a/test.log b/test.log
deleted file mode 100644
index 5f84d18..0000000
--- a/test.log
+++ /dev/null
@@ -1,3 +0,0 @@
-[2022-06-20 19:45:53 UTC] [INFO ] [main.cc::8] some info!
-[2022-06-20 19:45:53 UTC] [ERROR] [main.cc::9] something went wrong!
-[2022-06-20 19:45:59 UTC] [TRACE] [main.cc::11] just some very verbose stuff here