convert single LvglMutex into a Lvgl resource manager that will allow for easy multi threaded use of Lvgl through program.

This commit is contained in:
MatthewColvin 2023-10-03 20:40:17 -05:00
parent 94d75fa4d5
commit a19e84ee80
4 changed files with 88 additions and 33 deletions

View file

@ -1,11 +0,0 @@
#pragma once
#include <mutex>
class LvglMutex {
public:
[[nodiscard]] static std::lock_guard<std::mutex> lockScope() {
return std::lock_guard<std::mutex>(mLvglMutex);
}
inline static std::mutex mLvglMutex;
};

View file

@ -0,0 +1,49 @@
#pragma once
#include <functional>
#include <mutex>
#include <queue>
namespace UI {
class UIBase;
} // namespace UI
class LvglResourceManger {
friend UI::UIBase;
public:
static LvglResourceManger &GetInstance() {
static LvglResourceManger mInstance;
return mInstance;
}
[[nodiscard]] std::scoped_lock<std::mutex> scopeLock() {
return std::scoped_lock(mLvglMutex);
}
void AttemptNow(std::function<void()> 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<void()> aLvglModifierFunction) {
mLvglTasks.push(std::move(aLvglModifierFunction));
}
protected:
LvglResourceManger(){};
void HandleQueuedTasks() {
auto lock = scopeLock();
while (!mLvglTasks.empty()) {
mLvglTasks.front()();
mLvglTasks.pop();
}
}
std::queue<std::function<void()>> mLvglTasks;
std::mutex mLvglMutex;
};

View file

@ -1,5 +1,5 @@
#include "UIBase.hpp" #include "UIBase.hpp"
#include "LvglMutex.hpp" #include "LvglResourceManger.hpp"
using namespace UI; using namespace UI;
@ -7,9 +7,10 @@ UIBase::UIBase(std::shared_ptr<HardwareAbstract> aHardware)
: mHardware(aHardware) {} : mHardware(aHardware) {}
void UIBase::loopHandler() { void UIBase::loopHandler() {
lv_timer_handler();
{ {
auto lock = LvglMutex::lockScope(); auto lock = LvglResourceManger::GetInstance().scopeLock();
lv_timer_handler();
lv_task_handler(); lv_task_handler();
} }
LvglResourceManger::GetInstance().HandleQueuedTasks();
} }

View file

@ -1,61 +1,69 @@
#include "UIElement.hpp" #include "UIElement.hpp"
#include "LvglMutex.hpp" #include "LvglResourceManger.hpp"
namespace UI { namespace UI {
UIElement::UIElement(lv_obj_t *aLvglSelf, ID aId) UIElement::UIElement(lv_obj_t *aLvglSelf, ID aId)
: mLvglSelf(aLvglSelf), mId(aId) { : mLvglSelf(aLvglSelf), mId(aId) {
auto lock = LvglMutex::lockScope(); auto lock = LvglResourceManger::GetInstance().scopeLock();
mLvglSelf->user_data = this; mLvglSelf->user_data = this;
} }
UIElement::~UIElement() { UIElement::~UIElement() {
auto lock = LvglMutex::lockScope(); auto lock = LvglResourceManger::GetInstance().scopeLock();
if (lv_obj_is_valid(mLvglSelf)) { if (lv_obj_is_valid(mLvglSelf)) {
lv_obj_del(mLvglSelf); lv_obj_del(mLvglSelf);
} }
} }
void UIElement::AddElement(UIElement *anUIElement) { void UIElement::AddElement(UIElement *anUIElement) {
auto lock = LvglMutex::lockScope(); LvglResourceManger::GetInstance().AttemptNow([this, anUIElement] {
lv_obj_set_parent(anUIElement->mLvglSelf, mLvglSelf); 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) { void UIElement::SetWidth(lv_coord_t aWidth) {
auto lock = LvglMutex::lockScope(); LvglResourceManger::GetInstance().AttemptNow(
lv_obj_set_width(mLvglSelf, aWidth); [this, aWidth] { lv_obj_set_width(mLvglSelf, aWidth); });
} }
void UIElement::SetHeight(lv_coord_t aHeight) { void UIElement::SetHeight(lv_coord_t aHeight) {
auto lock = LvglMutex::lockScope(); LvglResourceManger::GetInstance().AttemptNow(
lv_obj_set_height(mLvglSelf, aHeight); [this, aHeight] { lv_obj_set_height(mLvglSelf, aHeight); });
} }
lv_coord_t UIElement::GetHeight() { lv_coord_t UIElement::GetHeight() {
auto lock = LvglResourceManger::GetInstance().scopeLock();
lv_obj_update_layout(mLvglSelf); lv_obj_update_layout(mLvglSelf);
return lv_obj_get_height(mLvglSelf); return lv_obj_get_height(mLvglSelf);
}; };
lv_coord_t UIElement::GetWidth() { lv_coord_t UIElement::GetWidth() {
auto lock = LvglResourceManger::GetInstance().scopeLock();
lv_obj_update_layout(mLvglSelf); lv_obj_update_layout(mLvglSelf);
return lv_obj_get_width(mLvglSelf); return lv_obj_get_width(mLvglSelf);
} }
void UIElement::SetY(lv_coord_t aY) { void UIElement::SetY(lv_coord_t aY) {
auto lock = LvglMutex::lockScope(); LvglResourceManger::GetInstance().AttemptNow(
lv_obj_set_y(mLvglSelf, aY); [this, aY] { lv_obj_set_y(mLvglSelf, aY); });
} };
void UIElement::SetX(lv_coord_t aX) { void UIElement::SetX(lv_coord_t aX) {
auto lock = LvglMutex::lockScope(); LvglResourceManger::GetInstance().AttemptNow(
lv_obj_set_x(mLvglSelf, aX); [this, aX] { lv_obj_set_x(mLvglSelf, aX); });
} }
lv_coord_t UIElement::GetY() { lv_coord_t UIElement::GetY() {
auto lock = LvglResourceManger::GetInstance().scopeLock();
lv_obj_update_layout(mLvglSelf); lv_obj_update_layout(mLvglSelf);
return lv_obj_get_y(mLvglSelf); return lv_obj_get_y(mLvglSelf);
} }
lv_coord_t UIElement::GetX() { lv_coord_t UIElement::GetX() {
auto lock = LvglResourceManger::GetInstance().scopeLock();
lv_obj_update_layout(mLvglSelf); lv_obj_update_layout(mLvglSelf);
return lv_obj_get_x(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) { void UIElement::SetBgColor(lv_color_t aColor, lv_style_selector_t aStyle) {
auto lock = LvglMutex::lockScope(); LvglResourceManger::GetInstance().AttemptNow([this, aColor, aStyle] {
lv_obj_set_style_bg_color(mLvglSelf, aColor, aStyle); lv_obj_set_style_bg_color(mLvglSelf, aColor, aStyle);
});
}; };
void UIElement::Show() { 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(); OnShow();
} }
void UIElement::Hide() { 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(); OnHide();
} }