summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2016-06-17 14:25:14 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2016-06-17 14:25:14 +0200
commit0a89de68defe14fb166a0a24b59ef495113a8b9d (patch)
treedf74fa69fc7e4cd0e5d4e4ad7b4b35de5ee65f27
parent5950cd21ae4ad1b9ddc98a6f1c8716e1627ebbd2 (diff)
downloaddabmod-0a89de68defe14fb166a0a24b59ef495113a8b9d.tar.gz
dabmod-0a89de68defe14fb166a0a24b59ef495113a8b9d.tar.bz2
dabmod-0a89de68defe14fb166a0a24b59ef495113a8b9d.zip
Move logging writes to separate thread
-rw-r--r--configure.ac2
-rw-r--r--src/Log.cpp50
-rw-r--r--src/Log.h37
3 files changed, 73 insertions, 16 deletions
diff --git a/configure.ac b/configure.ac
index 60b1e4e..7bcb494 100644
--- a/configure.ac
+++ b/configure.ac
@@ -103,7 +103,7 @@ AS_IF([test "x$enable_output_uhd" = "xyes"],
[AC_DEFINE(HAVE_OUTPUT_UHD, [1], [Define if UHD output is enabled]) ,
AC_CHECK_LIB([uhd], [main], [], [AC_MSG_ERROR([library uhd is missing])])])
-AX_BOOST_BASE([1.41.0], [], AC_MSG_ERROR([BOOST 1.41 or later is required]))
+AX_BOOST_BASE([1.55.0], [], AC_MSG_ERROR([BOOST 1.55 or later is required]))
AC_CHECK_LIB([boost_system], [main], [], [AC_MSG_ERROR([library boost_system is missing])])
AC_CHECK_LIB([boost_thread], [main], [], [AC_MSG_ERROR([library boost_thread is missing])])
diff --git a/src/Log.cpp b/src/Log.cpp
index 55a4ebf..81f32a8 100644
--- a/src/Log.cpp
+++ b/src/Log.cpp
@@ -3,7 +3,7 @@
Her Majesty the Queen in Right of Canada (Communications Research
Center Canada)
- Copyright (C), 2014, Matthias P. Braendli, matthias.braendli@mpb.li
+ Copyright (C), 2016, Matthias P. Braendli, matthias.braendli@mpb.li
*/
/*
This file is part of ODR-DabMod.
@@ -65,20 +65,44 @@ void Logger::log(log_level_t level, const char* fmt, ...)
void Logger::logstr(log_level_t level, std::string message)
{
- /* Remove a potential trailing newline.
- * It doesn't look good in syslog
- */
- if (message[message.length()-1] == '\n') {
- message.resize(message.length()-1);
- }
+ log_message_t m;
+ m.level = level;
+ m.message = message;
- for (auto &backend : backends) {
- backend->log(level, message);
- }
+ m_message_queue.push(std::move(m));
+}
- if (level != log_level_t::trace) {
- std::lock_guard<std::mutex> guard(m_cerr_mutex);
- std::cerr << levels_as_str[level] << " " << message << std::endl;
+void Logger::io_process()
+{
+ set_thread_name("logger");
+ while (1) {
+ log_message_t m;
+ while (m_message_queue.pop(m) == false) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+
+ auto message = m.message;
+
+ if (m.level == debug and m.message.empty()) {
+ // Special message to stop thread
+ break;
+ }
+
+ /* Remove a potential trailing newline.
+ * It doesn't look good in syslog
+ */
+ if (message[message.length()-1] == '\n') {
+ message.resize(message.length()-1);
+ }
+
+ for (auto &backend : backends) {
+ backend->log(m.level, message);
+ }
+
+ if (m.level != log_level_t::trace) {
+ std::lock_guard<std::mutex> guard(m_cerr_mutex);
+ std::cerr << levels_as_str[m.level] << " " << message << std::endl;
+ }
}
}
diff --git a/src/Log.h b/src/Log.h
index cbc3569..799ca85 100644
--- a/src/Log.h
+++ b/src/Log.h
@@ -3,7 +3,7 @@
Her Majesty the Queen in Right of Canada (Communications Research
Center Canada)
- Copyright (C), 2014, Matthias P. Braendli, matthias.braendli@mpb.li
+ Copyright (C), 2016, Matthias P. Braendli, matthias.braendli@mpb.li
*/
/*
This file is part of ODR-DabMod.
@@ -40,6 +40,8 @@
#include <string>
#include <map>
#include <mutex>
+#include <thread>
+#include <boost/lockfree/spsc_queue.hpp>
#define SYSLOG_IDENT "ODR-DabMod"
#define SYSLOG_FACILITY LOG_LOCAL0
@@ -148,9 +150,32 @@ class LogTracer : public LogBackend {
class LogLine;
+struct log_message_t {
+ log_message_t(log_level_t _level, std::string _message) :
+ level(_level),
+ message(_message) {}
+
+ log_message_t() {}
+
+ log_level_t level;
+ std::string message;
+};
+
class Logger {
public:
- Logger() {}
+ Logger() {
+ m_io_thread = std::thread(&Logger::io_process, this);
+ }
+
+ Logger(const Logger& other) = delete;
+ const Logger& operator=(const Logger& other) = delete;
+ ~Logger() {
+ // Special message to stop the thread
+ log_message_t m(debug, "");
+
+ m_message_queue.push(m);
+ m_io_thread.join();
+ }
void register_backend(LogBackend* backend);
@@ -159,6 +184,9 @@ class Logger {
void logstr(log_level_t level, std::string message);
+ /* All logging IO is done in another thread */
+ void io_process(void);
+
/* Return a LogLine for the given level
* so that you can write etiLog.level(info) << "stuff = " << 21 */
LogLine level(log_level_t level);
@@ -166,6 +194,10 @@ class Logger {
private:
std::list<LogBackend*> backends;
+ boost::lockfree::spsc_queue<
+ log_message_t,
+ boost::lockfree::capacity<80> > m_message_queue;
+ std::thread m_io_thread;
std::mutex m_cerr_mutex;
};
@@ -176,6 +208,7 @@ extern Logger etiLog;
class LogLine {
public:
LogLine(const LogLine& logline);
+ const LogLine& operator=(const LogLine& other) = delete;
LogLine(Logger* logger, log_level_t level) :
logger_(logger)
{