diff --git a/Platformio/OmoteUI/UIs/LvglMutex.hpp b/Platformio/OmoteUI/UIs/LvglMutex.hpp deleted file mode 100644 index d703cac..0000000 --- a/Platformio/OmoteUI/UIs/LvglMutex.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include - -class LvglMutex { -public: - [[nodiscard]] static std::lock_guard lockScope() { - return std::lock_guard(mLvglMutex); - } - - inline static std::mutex mLvglMutex; -}; diff --git a/Platformio/OmoteUI/UIs/LvglResourceManger.hpp b/Platformio/OmoteUI/UIs/LvglResourceManger.hpp new file mode 100644 index 0000000..71c516a --- /dev/null +++ b/Platformio/OmoteUI/UIs/LvglResourceManger.hpp @@ -0,0 +1,49 @@ +#pragma once +#include +#include +#include + +namespace UI { +class UIBase; +} // namespace UI + +class LvglResourceManger { + friend UI::UIBase; + +public: + static LvglResourceManger &GetInstance() { + static LvglResourceManger mInstance; + return mInstance; + } + + [[nodiscard]] std::scoped_lock scopeLock() { + return std::scoped_lock(mLvglMutex); + } + + void AttemptNow(std::function aLvglModifierFunction) { + // Attempt to take mutex and preform op if you can't then queue up. + if (mLvglMutex.try_lock()) { + aLvglModifierFunction(); + mLvglMutex.unlock(); + } else { + QueueForLater(aLvglModifierFunction); + } + } + void QueueForLater(std::function aLvglModifierFunction) { + mLvglTasks.push(std::move(aLvglModifierFunction)); + } + +protected: + LvglResourceManger(){}; + + void HandleQueuedTasks() { + auto lock = scopeLock(); + while (!mLvglTasks.empty()) { + mLvglTasks.front()(); + mLvglTasks.pop(); + } + } + + std::queue> mLvglTasks; + std::mutex mLvglMutex; +}; diff --git a/Platformio/OmoteUI/UIs/UIBase.cpp b/Platformio/OmoteUI/UIs/UIBase.cpp index d2ac817..0cbc137 100644 --- a/Platformio/OmoteUI/UIs/UIBase.cpp +++ b/Platformio/OmoteUI/UIs/UIBase.cpp @@ -1,5 +1,5 @@ #include "UIBase.hpp" -#include "LvglMutex.hpp" +#include "LvglResourceManger.hpp" using namespace UI; @@ -7,9 +7,10 @@ UIBase::UIBase(std::shared_ptr aHardware) : mHardware(aHardware) {} void UIBase::loopHandler() { - lv_timer_handler(); { - auto lock = LvglMutex::lockScope(); + auto lock = LvglResourceManger::GetInstance().scopeLock(); + lv_timer_handler(); lv_task_handler(); } + LvglResourceManger::GetInstance().HandleQueuedTasks(); } \ No newline at end of file diff --git a/Platformio/OmoteUI/core/UIElement.cpp b/Platformio/OmoteUI/core/UIElement.cpp index 26bf16b..526f464 100644 --- a/Platformio/OmoteUI/core/UIElement.cpp +++ b/Platformio/OmoteUI/core/UIElement.cpp @@ -1,61 +1,69 @@ #include "UIElement.hpp" -#include "LvglMutex.hpp" +#include "LvglResourceManger.hpp" namespace UI { UIElement::UIElement(lv_obj_t *aLvglSelf, ID aId) : mLvglSelf(aLvglSelf), mId(aId) { - auto lock = LvglMutex::lockScope(); + auto lock = LvglResourceManger::GetInstance().scopeLock(); mLvglSelf->user_data = this; } UIElement::~UIElement() { - auto lock = LvglMutex::lockScope(); + auto lock = LvglResourceManger::GetInstance().scopeLock(); if (lv_obj_is_valid(mLvglSelf)) { lv_obj_del(mLvglSelf); } } void UIElement::AddElement(UIElement *anUIElement) { - auto lock = LvglMutex::lockScope(); - lv_obj_set_parent(anUIElement->mLvglSelf, mLvglSelf); + LvglResourceManger::GetInstance().AttemptNow([this, anUIElement] { + lv_obj_set_parent(anUIElement->mLvglSelf, mLvglSelf); + }); } -bool UIElement::IsVisible() { return lv_obj_is_visible(mLvglSelf); } +bool UIElement::IsVisible() { + auto lock = LvglResourceManger::GetInstance().scopeLock(); + return lv_obj_is_visible(mLvglSelf); +} void UIElement::SetWidth(lv_coord_t aWidth) { - auto lock = LvglMutex::lockScope(); - lv_obj_set_width(mLvglSelf, aWidth); + LvglResourceManger::GetInstance().AttemptNow( + [this, aWidth] { lv_obj_set_width(mLvglSelf, aWidth); }); } void UIElement::SetHeight(lv_coord_t aHeight) { - auto lock = LvglMutex::lockScope(); - lv_obj_set_height(mLvglSelf, aHeight); + LvglResourceManger::GetInstance().AttemptNow( + [this, aHeight] { lv_obj_set_height(mLvglSelf, aHeight); }); } lv_coord_t UIElement::GetHeight() { + auto lock = LvglResourceManger::GetInstance().scopeLock(); lv_obj_update_layout(mLvglSelf); return lv_obj_get_height(mLvglSelf); }; lv_coord_t UIElement::GetWidth() { + auto lock = LvglResourceManger::GetInstance().scopeLock(); lv_obj_update_layout(mLvglSelf); return lv_obj_get_width(mLvglSelf); } void UIElement::SetY(lv_coord_t aY) { - auto lock = LvglMutex::lockScope(); - lv_obj_set_y(mLvglSelf, aY); -} + LvglResourceManger::GetInstance().AttemptNow( + [this, aY] { lv_obj_set_y(mLvglSelf, aY); }); +}; void UIElement::SetX(lv_coord_t aX) { - auto lock = LvglMutex::lockScope(); - lv_obj_set_x(mLvglSelf, aX); + LvglResourceManger::GetInstance().AttemptNow( + [this, aX] { lv_obj_set_x(mLvglSelf, aX); }); } lv_coord_t UIElement::GetY() { + auto lock = LvglResourceManger::GetInstance().scopeLock(); lv_obj_update_layout(mLvglSelf); return lv_obj_get_y(mLvglSelf); } lv_coord_t UIElement::GetX() { + auto lock = LvglResourceManger::GetInstance().scopeLock(); lv_obj_update_layout(mLvglSelf); return lv_obj_get_x(mLvglSelf); } @@ -72,17 +80,25 @@ void UIElement::SetVisiblity(bool aVisible) { } void UIElement::SetBgColor(lv_color_t aColor, lv_style_selector_t aStyle) { - auto lock = LvglMutex::lockScope(); - lv_obj_set_style_bg_color(mLvglSelf, aColor, aStyle); + LvglResourceManger::GetInstance().AttemptNow([this, aColor, aStyle] { + lv_obj_set_style_bg_color(mLvglSelf, aColor, aStyle); + }); }; void UIElement::Show() { - lv_obj_clear_flag(mLvglSelf, LV_OBJ_FLAG_HIDDEN); + { + auto lock = LvglResourceManger::GetInstance().scopeLock(); + lv_obj_clear_flag(mLvglSelf, LV_OBJ_FLAG_HIDDEN); + } OnShow(); } void UIElement::Hide() { - lv_obj_add_flag(mLvglSelf, LV_OBJ_FLAG_HIDDEN); + + { + auto lock = LvglResourceManger::GetInstance().scopeLock(); + lv_obj_add_flag(mLvglSelf, LV_OBJ_FLAG_HIDDEN); + } OnHide(); }