From a5510604e9adb511297bf9cb20a5fbdbaabe3e26 Mon Sep 17 00:00:00 2001
From: Jeremie Deray <jeremie.deray@pal-robotics.com>
Date: Mon, 10 Oct 2016 18:40:28 +0200
Subject: [PATCH] add a bunch of utils for multi_threading

---
 src/multi_threading_utils.h | 171 ++++++++++++++++++++++++++++++++++++
 1 file changed, 171 insertions(+)
 create mode 100644 src/multi_threading_utils.h

diff --git a/src/multi_threading_utils.h b/src/multi_threading_utils.h
new file mode 100644
index 000000000..eaadf6d4b
--- /dev/null
+++ b/src/multi_threading_utils.h
@@ -0,0 +1,171 @@
+#ifndef WOLF_MULTI_THREADING_UTILS_H_
+#define WOLF_MULTI_THREADING_UTILS_H_
+
+#include <iostream>
+#include <mutex>
+#include <chrono>
+
+#include <sys/syscall.h>
+
+namespace wolf
+{
+
+namespace core
+{
+inline long get_thread_id() { return syscall(__NR_gettid); }
+}
+
+namespace details
+{
+using std::chrono::hours;
+using std::chrono::minutes;
+using std::chrono::seconds;
+using std::chrono::milliseconds;
+using std::chrono::microseconds;
+using std::chrono::nanoseconds;
+
+using wolf_time_unit    = nanoseconds;
+using wolf_clock_t      = std::chrono::_V2::high_resolution_clock;
+using wolf_time_point_t = std::chrono::time_point<wolf_clock_t, wolf_time_unit>;
+using wolf_duration_t   = std::chrono::duration<wolf_clock_t, std::nano>;
+
+const wolf_time_unit zero = wolf_time_unit(0);
+const wolf_time_unit min  = std::numeric_limits<wolf_time_unit>::lowest();
+const wolf_time_unit max  = std::numeric_limits<wolf_time_unit>::max();
+}
+
+/**
+  * \brief Return current time in 'unit'.
+  * Default nanoseconds.
+  * \return long, current time.
+  */
+template <typename unit = details::wolf_time_unit>
+long int getTime()
+{
+  auto duration_since_epoch_to_now_unit =
+      std::chrono::duration_cast<unit>(
+        std::chrono::time_point_cast<unit>(
+          std::chrono::system_clock::now()
+          ).time_since_epoch()
+        );
+
+  return static_cast<long int>(duration_since_epoch_to_now_unit.count());
+}
+
+namespace io
+{
+
+enum class CoutColor
+{
+  BLACK,
+  RED,
+  GREEN,
+  YELLOW,
+  BLUE,
+  MAGENTA,
+  CYAN,
+  WHITE,
+  ENDCOLOR
+};
+
+inline std::ostream& operator<<(std::ostream& os, CoutColor c)
+{
+  switch(c)
+  {
+  // AINSI color codes. Prints bold color.
+  case CoutColor::BLACK    : os << "\033[1;30m"; break;
+  case CoutColor::RED      : os << "\033[1;31m"; break;
+  case CoutColor::GREEN    : os << "\033[1;32m"; break;
+  case CoutColor::YELLOW   : os << "\033[1;33m"; break;
+  case CoutColor::BLUE     : os << "\033[1;34m"; break;
+  case CoutColor::MAGENTA  : os << "\033[1;35m"; break;
+  case CoutColor::CYAN     : os << "\033[1;36m"; break;
+  case CoutColor::WHITE    : os << "\033[1;37m"; break;
+  case CoutColor::ENDCOLOR : os << "\033[0m";    break;
+  default                  : os << "\033[0m";
+  }
+  return os;
+}
+
+namespace details
+{
+
+static std::mutex the_infamous_cout_mutex;
+
+/**
+ * \brief Return current time in nanoseconds.
+ * \return Current time formated as string.
+ */
+inline std::string printTime()
+{
+  std::string now = std::to_string(getTime()).insert(10, ".");
+  return ("[" + now + "]");
+}
+
+inline void cout_impl()
+{
+  std::cout << CoutColor::ENDCOLOR << std::endl;
+}
+
+template <typename T>
+inline void cout_impl(const T& message)
+{
+  std::cout << message;
+  cout_impl();
+}
+
+template <typename T, typename... Args>
+inline void cout_impl(const T& message, const Args&... rest)
+{
+  std::cout << message;
+  cout_impl(rest...);
+}
+} // namespace details
+
+template <typename T, typename... Args>
+inline void locked_cout(const T& message, const Args&... rest)
+{
+  std::lock_guard<std::mutex> lock_cout{details::the_infamous_cout_mutex};
+  std::cout << details::printTime() << " " << message;
+
+  details::cout_impl(rest...);
+}
+
+template <typename... Args>
+inline void locked_cout(const CoutColor& color, const Args&... rest)
+{
+  std::lock_guard<std::mutex> lock_cout{details::the_infamous_cout_mutex};
+  std::cout << color << details::printTime() << " ";
+
+  details::cout_impl(rest...);
+}
+
+} // namespace io
+
+#define WOLF_PRINT_COLOR(...) \
+  locked_cout(__VA_ARGS__)
+
+#define WOLF_INFO(...) \
+  locked_cout(wolf::io::CoutColor::ENDCOLOR, __VA_ARGS__)
+
+#define WOLF_WARN(...) \
+  locked_cout(wolf::io::CoutColor::MAGENTA, __VA_ARGS__)
+
+#define WOLF_ERROR(...) \
+  locked_cout(wolf::io::CoutColor::RED, __VA_ARGS__)
+
+#define WOLF_PRINT_COLOR_COND(cond, ...) \
+  if (cond) locked_cout(__VA_ARGS__)
+
+#define WOLF_INFO_COND(cond, ...) \
+  if (cond) locked_cout(cond, wolf::io::CoutColor::ENDCOLOR, __VA_ARGS__)
+
+#define WOLF_WARN_COND(...) \
+  if (cond) locked_cout(cond, wolf::io::CoutColor::MAGENTA, __VA_ARGS__)
+
+#define WOLF_ERROR_COND(...) \
+  if (cond) locked_cout(cond, wolf::io::CoutColor::RED, __VA_ARGS__)
+
+} // namespace wolf
+
+#endif /* WOLF_MULTI_THREADING_UTILS_H_ */
-- 
GitLab