diff options
author | crupest <crupest@outlook.com> | 2022-02-21 18:44:40 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2022-02-21 18:44:40 +0800 |
commit | ced1a63686e6c64cb574d74a34d1bbd07d0a668e (patch) | |
tree | 4082e4689e5e7cede8d59a0538d0f1ae37064acb /include/cru | |
parent | 6b00fca7c662301bf657a99cb1e89f21541a46bc (diff) | |
download | cru-ced1a63686e6c64cb574d74a34d1bbd07d0a668e.tar.gz cru-ced1a63686e6c64cb574d74a34d1bbd07d0a668e.tar.bz2 cru-ced1a63686e6c64cb574d74a34d1bbd07d0a668e.zip |
...
Diffstat (limited to 'include/cru')
25 files changed, 239 insertions, 137 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 diff --git a/include/cru/osx/graphics/quartz/Painter.h b/include/cru/osx/graphics/quartz/Painter.h index 19428583..87389437 100644 --- a/include/cru/osx/graphics/quartz/Painter.h +++ b/include/cru/osx/graphics/quartz/Painter.h @@ -11,8 +11,7 @@ namespace cru::platform::graphics::osx::quartz { class QuartzCGContextPainter : public OsxQuartzResource, public virtual IPainter { - CRU_DEFINE_CLASS_LOG_TAG( - u"cru::platform::graphics::osx::quartz::QuartzCGContextPainter") + CRU_DEFINE_CLASS_LOG_TAG(u"QuartzCGContextPainter") public: explicit QuartzCGContextPainter( diff --git a/include/cru/ui/controls/TextHostControlService.h b/include/cru/ui/controls/TextHostControlService.h index 74da1e19..dec9b3e0 100644 --- a/include/cru/ui/controls/TextHostControlService.h +++ b/include/cru/ui/controls/TextHostControlService.h @@ -76,7 +76,7 @@ class TextControlMovePattern : public Object { }; class CRU_UI_API TextHostControlService : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::controls::TextControlService") + CRU_DEFINE_CLASS_LOG_TAG(u"TextControlService") public: TextHostControlService(gsl::not_null<Control*> control); diff --git a/include/cru/ui/helper/ClickDetector.h b/include/cru/ui/helper/ClickDetector.h index 0d74b9c0..3bf28451 100644 --- a/include/cru/ui/helper/ClickDetector.h +++ b/include/cru/ui/helper/ClickDetector.h @@ -41,7 +41,7 @@ enum class ClickState { }; class ClickDetector : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::ClickDetector") + CRU_DEFINE_CLASS_LOG_TAG(u"ClickDetector") public: explicit ClickDetector(controls::Control* control); diff --git a/include/cru/ui/helper/ShortcutHub.h b/include/cru/ui/helper/ShortcutHub.h index 84e786aa..28c41234 100644 --- a/include/cru/ui/helper/ShortcutHub.h +++ b/include/cru/ui/helper/ShortcutHub.h @@ -2,6 +2,7 @@ #include "../Base.h" #include "../events/UiEvents.h" +#include "cru/common/Base.h" #include "cru/common/Event.h" #include "cru/platform/gui/Keyboard.h" @@ -97,6 +98,7 @@ struct ShortcutInfo { }; class CRU_UI_API ShortcutHub : public Object { + CRU_DEFINE_CLASS_LOG_TAG(u"ShortcutHub") public: ShortcutHub() = default; diff --git a/include/cru/ui/host/WindowHost.h b/include/cru/ui/host/WindowHost.h index 9fe46ac0..b1d0c998 100644 --- a/include/cru/ui/host/WindowHost.h +++ b/include/cru/ui/host/WindowHost.h @@ -19,7 +19,7 @@ struct AfterLayoutEventArgs {}; // The bridge between control tree and native window. class CRU_UI_API WindowHost : public Object { friend controls::Control; - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::host::WindowHost") + CRU_DEFINE_CLASS_LOG_TAG(u"WindowHost") public: explicit WindowHost(controls::Control* root_control); diff --git a/include/cru/ui/render/BorderRenderObject.h b/include/cru/ui/render/BorderRenderObject.h index 2fc74f0f..a71cd6a0 100644 --- a/include/cru/ui/render/BorderRenderObject.h +++ b/include/cru/ui/render/BorderRenderObject.h @@ -5,7 +5,7 @@ namespace cru::ui::render { class CRU_UI_API BorderRenderObject : public SingleChildRenderObject { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::BorderRenderObject") + CRU_DEFINE_CLASS_LOG_TAG(u"BorderRenderObject") public: BorderRenderObject(); diff --git a/include/cru/ui/render/FlexLayoutRenderObject.h b/include/cru/ui/render/FlexLayoutRenderObject.h index ff7340cb..4effacb1 100644 --- a/include/cru/ui/render/FlexLayoutRenderObject.h +++ b/include/cru/ui/render/FlexLayoutRenderObject.h @@ -93,7 +93,7 @@ struct FlexChildLayoutData { // class CRU_UI_API FlexLayoutRenderObject : public LayoutRenderObject<FlexChildLayoutData> { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::FlexLayoutRenderObject") + CRU_DEFINE_CLASS_LOG_TAG(u"FlexLayoutRenderObject") public: FlexLayoutRenderObject() = default; diff --git a/include/cru/ui/render/RenderObject.h b/include/cru/ui/render/RenderObject.h index 311ab044..e8dc3b17 100644 --- a/include/cru/ui/render/RenderObject.h +++ b/include/cru/ui/render/RenderObject.h @@ -36,7 +36,7 @@ namespace cru::ui::render { * void OnLayoutContent(const Rect& content_rect) override; */ class CRU_UI_API RenderObject : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::RenderObject") + CRU_DEFINE_CLASS_LOG_TAG(u"RenderObject") protected: RenderObject() = default; diff --git a/include/cru/ui/render/SingleChildRenderObject.h b/include/cru/ui/render/SingleChildRenderObject.h index cc9e4126..a98465f0 100644 --- a/include/cru/ui/render/SingleChildRenderObject.h +++ b/include/cru/ui/render/SingleChildRenderObject.h @@ -3,7 +3,7 @@ namespace cru::ui::render { class CRU_UI_API SingleChildRenderObject : public RenderObject { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::SingleChildRenderObject") + CRU_DEFINE_CLASS_LOG_TAG(u"SingleChildRenderObject") public: SingleChildRenderObject() = default; diff --git a/include/cru/ui/render/StackLayoutRenderObject.h b/include/cru/ui/render/StackLayoutRenderObject.h index b522ecbb..4da63ea2 100644 --- a/include/cru/ui/render/StackLayoutRenderObject.h +++ b/include/cru/ui/render/StackLayoutRenderObject.h @@ -28,7 +28,7 @@ struct StackChildLayoutData { // to min size. class CRU_UI_API StackLayoutRenderObject : public LayoutRenderObject<StackChildLayoutData> { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render:StackLayoutRenderObject") + CRU_DEFINE_CLASS_LOG_TAG(u"StackLayoutRenderObject") public: StackLayoutRenderObject() = default; diff --git a/include/cru/ui/render/TextRenderObject.h b/include/cru/ui/render/TextRenderObject.h index db8ff0d0..079c5680 100644 --- a/include/cru/ui/render/TextRenderObject.h +++ b/include/cru/ui/render/TextRenderObject.h @@ -18,7 +18,7 @@ namespace cru::ui::render { // If the result layout box is bigger than actual text box, then text is center // aligned. class CRU_UI_API TextRenderObject : public RenderObject { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::TextRenderObject") + CRU_DEFINE_CLASS_LOG_TAG(u"TextRenderObject") public: constexpr static float default_caret_width = 2; diff --git a/include/cru/ui/render/TreeRenderObject.h b/include/cru/ui/render/TreeRenderObject.h index 4a176926..8c589d7a 100644 --- a/include/cru/ui/render/TreeRenderObject.h +++ b/include/cru/ui/render/TreeRenderObject.h @@ -49,7 +49,7 @@ class CRU_UI_API TreeRenderObjectItem : public Object { }; class CRU_UI_API TreeRenderObject : public RenderObject { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render:TreeRenderObject") + CRU_DEFINE_CLASS_LOG_TAG(u"TreeRenderObject") public: TreeRenderObject(); diff --git a/include/cru/win/DebugLogger.h b/include/cru/win/DebugLogger.h index 6a7173ea..43e08f20 100644 --- a/include/cru/win/DebugLogger.h +++ b/include/cru/win/DebugLogger.h @@ -1,7 +1,7 @@ #pragma once #include "Base.h" -#include "cru/common/Logger.h" +#include "cru/common/log/Logger.h" namespace cru::platform::win { diff --git a/include/cru/win/StdOutLogger.h b/include/cru/win/StdOutLogger.h index 831d006f..d6009bb3 100644 --- a/include/cru/win/StdOutLogger.h +++ b/include/cru/win/StdOutLogger.h @@ -1,7 +1,7 @@ #pragma once #include "Base.h" -#include "cru/common/Logger.h" +#include "cru/common/log/Logger.h" namespace cru::platform::win { class CRU_WIN_API WinStdOutLoggerSource : public ::cru::log::ILogSource { diff --git a/include/cru/win/gui/Cursor.h b/include/cru/win/gui/Cursor.h index 7a9a2198..f9cb0a09 100644 --- a/include/cru/win/gui/Cursor.h +++ b/include/cru/win/gui/Cursor.h @@ -8,7 +8,7 @@ namespace cru::platform::gui::win { class CRU_WIN_GUI_API WinCursor : public WinNativeResource, public virtual ICursor { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::WinCursor") + CRU_DEFINE_CLASS_LOG_TAG(u"WinCursor") public: WinCursor(HCURSOR handle, bool auto_destroy); diff --git a/include/cru/win/gui/GodWindow.h b/include/cru/win/gui/GodWindow.h index 63051245..fe61c80d 100644 --- a/include/cru/win/gui/GodWindow.h +++ b/include/cru/win/gui/GodWindow.h @@ -9,7 +9,7 @@ namespace cru::platform::gui::win { class CRU_WIN_GUI_API GodWindow : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::GodWindow") + CRU_DEFINE_CLASS_LOG_TAG(u"GodWindow") public: explicit GodWindow(WinUiApplication* application); diff --git a/include/cru/win/gui/InputMethod.h b/include/cru/win/gui/InputMethod.h index 27a621be..8e28f857 100644 --- a/include/cru/win/gui/InputMethod.h +++ b/include/cru/win/gui/InputMethod.h @@ -12,7 +12,7 @@ namespace cru::platform::gui::win { class CRU_WIN_GUI_API AutoHIMC : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::AutoHIMC") + CRU_DEFINE_CLASS_LOG_TAG(u"AutoHIMC") public: explicit AutoHIMC(HWND hwnd); @@ -36,7 +36,7 @@ class CRU_WIN_GUI_API AutoHIMC : public Object { class CRU_WIN_GUI_API WinInputMethodContext : public WinNativeResource, public virtual IInputMethodContext { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::WinInputMethodContext") + CRU_DEFINE_CLASS_LOG_TAG(u"WinInputMethodContext") public: WinInputMethodContext(gsl::not_null<WinNativeWindow*> window); diff --git a/include/cru/win/gui/Window.h b/include/cru/win/gui/Window.h index fcbe1dbd..b279a434 100644 --- a/include/cru/win/gui/Window.h +++ b/include/cru/win/gui/Window.h @@ -11,7 +11,7 @@ namespace cru::platform::gui::win { class CRU_WIN_GUI_API WinNativeWindow : public WinNativeResource, public virtual INativeWindow { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::WinNativeWindow") + CRU_DEFINE_CLASS_LOG_TAG(u"WinNativeWindow") public: explicit WinNativeWindow(WinUiApplication* application); |