aboutsummaryrefslogtreecommitdiff
path: root/include/cru/common
diff options
context:
space:
mode:
Diffstat (limited to 'include/cru/common')
-rw-r--r--include/cru/common/Base.h2
-rw-r--r--include/cru/common/Format.h4
-rw-r--r--include/cru/common/Logger.h114
-rw-r--r--include/cru/common/String.h2
-rw-r--r--include/cru/common/concurrent/ConcurrentQueue.h110
-rw-r--r--include/cru/common/log/Logger.h88
-rw-r--r--include/cru/common/log/StdioLogTarget.h17
7 files changed, 219 insertions, 118 deletions
diff --git a/include/cru/common/Base.h b/include/cru/common/Base.h
index 4d4d1f5f..899cfc13 100644
--- a/include/cru/common/Base.h
+++ b/include/cru/common/Base.h
@@ -94,5 +94,5 @@ inline void hash_combine(std::size_t& s, const T& v) {
#define CRU_DEFINE_CLASS_LOG_TAG(tag) \
private: \
- constexpr static StringView log_tag = tag;
+ constexpr static const char16_t* kLogTag = tag;
} // namespace cru
diff --git a/include/cru/common/Format.h b/include/cru/common/Format.h
index 7628f07d..2b08f03b 100644
--- a/include/cru/common/Format.h
+++ b/include/cru/common/Format.h
@@ -92,7 +92,7 @@ struct FormatToken {
String place_holder_option;
};
-std::vector<FormatToken> CRU_BASE_API ParseToFormatTokenList(const String& str);
+std::vector<FormatToken> CRU_BASE_API ParseToFormatTokenList(StringView str);
void CRU_BASE_API FormatAppendFromFormatTokenList(
String& current, const std::vector<FormatToken>& format_token_list,
@@ -123,7 +123,7 @@ void FormatAppendFromFormatTokenList(
} // namespace details
template <typename... T>
-String Format(const String& format, T&&... args) {
+String Format(StringView format, T&&... args) {
String result;
details::FormatAppendFromFormatTokenList(
diff --git a/include/cru/common/Logger.h b/include/cru/common/Logger.h
deleted file mode 100644
index 25875651..00000000
--- a/include/cru/common/Logger.h
+++ /dev/null
@@ -1,114 +0,0 @@
-#pragma once
-#include "Base.h"
-
-#include "String.h"
-#include "Format.h"
-
-#include <list>
-#include <memory>
-
-namespace cru::log {
-
-enum class LogLevel { Debug, Info, Warn, Error };
-
-struct CRU_BASE_API ILogSource : virtual Interface {
- // Write the string s. LogLevel is just a helper. It has no effect on the
- // content to write.
- virtual void Write(LogLevel level, StringView s) = 0;
-};
-
-class CRU_BASE_API Logger : public Object {
- public:
- static Logger* GetInstance();
-
- public:
- Logger() = default;
-
- CRU_DELETE_COPY(Logger)
- CRU_DELETE_MOVE(Logger)
-
- ~Logger() override = default;
-
- public:
- void AddSource(std::unique_ptr<ILogSource> source);
- void RemoveSource(ILogSource* source);
-
- public:
- void Log(LogLevel level, StringView message);
- void Log(LogLevel level, StringView tag, StringView message);
-
- private:
- std::list<std::unique_ptr<ILogSource>> sources_;
-};
-
-// TODO: Remove argument evaluation in Debug.
-template <typename... TArgs>
-void Debug([[maybe_unused]] TArgs&&... args) {
-#ifdef CRU_DEBUG
- Logger::GetInstance()->Log(LogLevel::Debug,
- Format(std::forward<TArgs>(args)...));
-#endif
-}
-
-template <typename... TArgs>
-void Info(TArgs&&... args) {
- Logger::GetInstance()->Log(LogLevel::Info,
- Format(std::forward<TArgs>(args)...));
-}
-
-template <typename... TArgs>
-void Warn(TArgs&&... args) {
- Logger::GetInstance()->Log(LogLevel::Warn,
- Format(std::forward<TArgs>(args)...));
-}
-
-template <typename... TArgs>
-void Error(TArgs&&... args) {
- Logger::GetInstance()->Log(LogLevel::Error,
- Format(std::forward<TArgs>(args)...));
-}
-
-// TODO: Remove argument evaluation in Debug.
-template <typename... TArgs>
-void TagDebug([[maybe_unused]] StringView tag,
- [[maybe_unused]] TArgs&&... args) {
-#ifdef CRU_DEBUG
- Logger::GetInstance()->Log(LogLevel::Debug, tag,
- Format(std::forward<TArgs>(args)...));
-#endif
-}
-
-template <typename... TArgs>
-void TagInfo(StringView tag, TArgs&&... args) {
- Logger::GetInstance()->Log(LogLevel::Info, tag,
- Format(std::forward<TArgs>(args)...));
-}
-
-template <typename... TArgs>
-void TagWarn(StringView tag, TArgs&&... args) {
- Logger::GetInstance()->Log(LogLevel::Warn, tag,
- Format(std::forward<TArgs>(args)...));
-}
-
-template <typename... TArgs>
-void TagError(StringView tag, TArgs&&... args) {
- Logger::GetInstance()->Log(LogLevel::Error, tag,
- Format(std::forward<TArgs>(args)...));
-}
-
-class StdioLogSource : public Object, public virtual ILogSource {
- public:
- explicit StdioLogSource(bool use_lock = false);
-
- CRU_DELETE_COPY(StdioLogSource)
- CRU_DELETE_MOVE(StdioLogSource)
-
- ~StdioLogSource() override;
-
- public:
- void Write(LogLevel level, StringView s) override;
-
- private:
- bool use_lock_;
-};
-} // namespace cru::log
diff --git a/include/cru/common/String.h b/include/cru/common/String.h
index 0b1b031b..be886168 100644
--- a/include/cru/common/String.h
+++ b/include/cru/common/String.h
@@ -63,7 +63,7 @@ class CRU_BASE_API String {
public:
String() = default;
- explicit String(const_pointer str);
+ String(const_pointer str);
String(const_pointer str, size_type size);
template <Index size>
diff --git a/include/cru/common/concurrent/ConcurrentQueue.h b/include/cru/common/concurrent/ConcurrentQueue.h
new file mode 100644
index 00000000..4f649a41
--- /dev/null
+++ b/include/cru/common/concurrent/ConcurrentQueue.h
@@ -0,0 +1,110 @@
+#pragma once
+#include <condition_variable>
+#include <mutex>
+#include <optional>
+#include <utility>
+
+namespace cru::concurrent {
+namespace details {
+template <typename T>
+struct ConcurrentQueueNode {
+ ConcurrentQueueNode(T&& value, ConcurrentQueueNode* next = nullptr)
+ : value(std::move(value)), next(next) {}
+
+ T value;
+ ConcurrentQueueNode* next;
+};
+} // namespace details
+
+template <typename T>
+class ConcurrentQueue {
+ public:
+ ConcurrentQueue() {}
+
+ ConcurrentQueue(const ConcurrentQueue&) = delete;
+ ConcurrentQueue& operator=(const ConcurrentQueue&) = delete;
+
+ ConcurrentQueue(ConcurrentQueue&& other)
+ : head_(other.head_),
+ tail_(other.tail_),
+ mutex_(std::move(other.mutex_)),
+ condition_variable_(std::move(other.condition_variable_)) {
+ other.head_ = nullptr;
+ other.tail_ = nullptr;
+ }
+
+ ConcurrentQueue& operator=(ConcurrentQueue&& other) {
+ if (this != &other) {
+ head_ = other.head_;
+ tail_ = other.tail_;
+ mutex_ = std::move(other.mutex_);
+ condition_variable_ = std::move(other.condition_variable_);
+ other.head_ = nullptr;
+ other.tail_ = nullptr;
+ return *this;
+ }
+ return *this;
+ }
+
+ ~ConcurrentQueue() {
+ if (head_) {
+ auto node = head_;
+ while (node) {
+ auto next = node->next;
+ delete node;
+ node = next;
+ }
+ }
+ }
+
+ public:
+ void Push(T&& value) {
+ std::unique_lock<std::mutex> lock(mutex_);
+ if (head_ == nullptr) {
+ head_ = tail_ = new details::ConcurrentQueueNode<T>(std::move(value));
+ condition_variable_.notify_one();
+ } else {
+ tail_->next = new details::ConcurrentQueueNode<T>(std::move(value));
+ tail_ = tail_->next;
+ }
+ }
+
+ T Pull() {
+ std::unique_lock<std::mutex> lock(mutex_);
+ if (head_ == nullptr) {
+ condition_variable_.wait(lock);
+ }
+ assert(head_ != nullptr);
+ auto value = std::move(head_->value);
+ auto next = head_->next;
+ delete head_;
+ head_ = next;
+ if (next == nullptr) {
+ tail_ = nullptr;
+ }
+ return value;
+ }
+
+ std::optional<T> Poll() {
+ std::unique_lock<std::mutex> lock(mutex_);
+ if (head_ == nullptr) {
+ return std::nullopt;
+ }
+ auto value = std::move(head_->value);
+ auto next = head_->next;
+ delete head_;
+ head_ = next;
+ if (next == nullptr) {
+ tail_ = nullptr;
+ }
+ return value;
+ }
+
+ private:
+ details::ConcurrentQueueNode<T>* head_ = nullptr;
+ details::ConcurrentQueueNode<T>* tail_ = nullptr;
+
+ std::mutex mutex_;
+ std::condition_variable condition_variable_;
+};
+} // namespace cru::concurrent
diff --git a/include/cru/common/log/Logger.h b/include/cru/common/log/Logger.h
new file mode 100644
index 00000000..25735e14
--- /dev/null
+++ b/include/cru/common/log/Logger.h
@@ -0,0 +1,88 @@
+#pragma once
+#include "../Base.h"
+
+#include "../Format.h"
+#include "../String.h"
+#include "../concurrent/ConcurrentQueue.h"
+
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+namespace cru::log {
+enum class LogLevel { Debug, Info, Warn, Error };
+
+struct CRU_BASE_API LogInfo {
+ LogInfo(LogLevel level, String tag, String message)
+ : level(level), tag(std::move(tag)), message(std::move(message)) {}
+
+ CRU_DEFAULT_COPY(LogInfo)
+ CRU_DEFAULT_MOVE(LogInfo)
+
+ ~LogInfo() = default;
+
+ LogLevel level;
+ String tag;
+ String message;
+};
+
+struct CRU_BASE_API ILogTarget : virtual Interface {
+ // Write the string s. LogLevel is just a helper. It has no effect on the
+ // content to write.
+ virtual void Write(LogLevel level, StringView s) = 0;
+};
+
+class CRU_BASE_API Logger : public Object {
+ public:
+ static Logger* GetInstance();
+
+ public:
+ Logger();
+
+ CRU_DELETE_COPY(Logger)
+ CRU_DELETE_MOVE(Logger)
+
+ ~Logger() override;
+
+ public:
+ void AddLogTarget(std::unique_ptr<ILogTarget> source);
+ void RemoveLogTarget(ILogTarget* source);
+
+ public:
+ void Log(LogLevel level, String tag, String message) {
+ Log(LogInfo(level, std::move(tag), std::move(message)));
+ }
+ void Log(LogInfo log_info);
+
+ template <typename... Args>
+ void FormatLog(LogLevel level, String tag, StringView format,
+ Args&&... args) {
+ Log(level, std::move(tag), Format(format, std::forward<Args>(args)...));
+ }
+
+ private:
+ concurrent::ConcurrentQueue<LogInfo> log_queue_;
+
+ std::mutex target_list_mutex_;
+ std::vector<std::unique_ptr<ILogTarget>> target_list_;
+
+ std::thread log_thread_;
+};
+} // namespace cru::log
+
+#define CRU_LOG_DEBUG(...) \
+ cru::log::Logger::GetInstance()->FormatLog(cru::log::LogLevel::Debug, \
+ kLogTag, __VA_ARGS__)
+
+#define CRU_LOG_INFO(...) \
+ cru::log::Logger::GetInstance()->FormatLog(cru::log::LogLevel::Info, \
+ kLogTag, __VA_ARGS__)
+
+#define CRU_LOG_WARN(...) \
+ cru::log::Logger::GetInstance()->FormatLog(cru::log::LogLevel::Warn, \
+ kLogTag, __VA_ARGS__)
+
+#define CRU_LOG_ERROR(...) \
+ cru::log::Logger::GetInstance()->FormatLog(cru::log::LogLevel::Error, \
+ kLogTag, __VA_ARGS__)
diff --git a/include/cru/common/log/StdioLogTarget.h b/include/cru/common/log/StdioLogTarget.h
new file mode 100644
index 00000000..4123766b
--- /dev/null
+++ b/include/cru/common/log/StdioLogTarget.h
@@ -0,0 +1,17 @@
+#pragma once
+#include "Logger.h"
+
+namespace cru::log {
+class StdioLogTarget : public Object, public virtual log::ILogTarget {
+ public:
+ explicit StdioLogTarget();
+
+ CRU_DELETE_COPY(StdioLogTarget)
+ CRU_DELETE_MOVE(StdioLogTarget)
+
+ ~StdioLogTarget() override;
+
+ public:
+ void Write(log::LogLevel level, StringView s) override;
+};
+} // namespace cru::log