core: use Boost.Log for logging

This makes the logging backend asynchronous

Change-Id: Ib3417e2ae424c5ae7237c071dc4698ca9769a33c
Refs: #2513
diff --git a/core/logger.hpp b/core/logger.hpp
index 54af7cb..853a922 100644
--- a/core/logger.hpp
+++ b/core/logger.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2016,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -31,8 +31,8 @@
 #ifdef HAVE_CUSTOM_LOGGER
 #include "custom-logger.hpp"
 #else
-
-#include <mutex>
+#include <boost/log/common.hpp>
+#include <boost/log/sources/logger.hpp>
 
 namespace nfd {
 
@@ -84,12 +84,8 @@
     m_moduleName = name;
   }
 
-  /** \return string representation of time since epoch: seconds.microseconds
-   *  \warning Return value is in a statically allocated buffer,
-   *           which subsequent calls will overwrite.
-   */
-  static const char*
-  now();
+public:
+  boost::log::sources::logger boostLogger;
 
 private:
   std::string m_moduleName;
@@ -103,6 +99,20 @@
   return output;
 }
 
+/**
+ * \brief a tag that writes a timestamp upon stream output
+ */
+struct LoggerTimestamp
+{
+};
+
+/**
+ * \brief write a timestamp to \p os
+ * \note This function is thread-safe.
+ */
+std::ostream&
+operator<<(std::ostream& os, const LoggerTimestamp&);
+
 } // namespace nfd
 
 #include "core/logger-factory.hpp"
@@ -130,16 +140,15 @@
 template<>                                                                 \
 nfd::Logger& cls<s1, s2>::g_logger = nfd::LoggerFactory::create(name)
 
-extern std::mutex g_logMutex;
+#define NFD_LOG_LINE(msg, expression) \
+LoggerTimestamp{} << " "#msg": " << "[" << g_logger  << "] " << expression
 
-#define NFD_LOG(level, msg, expression)                          \
-do {                                                             \
-  if (g_logger.isEnabled(::nfd::LOG_##level)) {                  \
-    std::lock_guard<std::mutex> lock(::nfd::g_logMutex);         \
-    std::clog << ::nfd::Logger::now() << " "#msg": "             \
-              << "[" << g_logger << "] " << expression << "\n";  \
-  }                                                              \
-} while (false)
+#define NFD_LOG(level, msg, expression)                                 \
+  do {                                                                  \
+    if (g_logger.isEnabled(::nfd::LOG_##level)) {                       \
+      BOOST_LOG(g_logger.boostLogger) << NFD_LOG_LINE(msg, expression); \
+    }                                                                   \
+  } while (false)
 
 #define NFD_LOG_TRACE(expression) NFD_LOG(TRACE, TRACE,   expression)
 #define NFD_LOG_DEBUG(expression) NFD_LOG(DEBUG, DEBUG,   expression)