1
0
mirror of synced 2025-02-12 08:43:03 +01:00

ux: Reduce file loading time to basically zero

This commit is contained in:
WerWolv 2022-09-19 16:09:22 +02:00
parent b11dbe4fe1
commit 7b61268f22
7 changed files with 143 additions and 106 deletions

View File

@ -19,7 +19,7 @@ namespace hex {
class Task { class Task {
public: public:
Task() = default; Task() = default;
Task(std::string unlocalizedName, u64 maxValue, std::function<void(Task &)> function); Task(std::string unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
Task(const Task&) = delete; Task(const Task&) = delete;
Task(Task &&other) noexcept; Task(Task &&other) noexcept;
@ -28,6 +28,7 @@ namespace hex {
void update(u64 value = 0); void update(u64 value = 0);
void setMaxValue(u64 value); void setMaxValue(u64 value);
[[nodiscard]] bool isBackgroundTask() const;
[[nodiscard]] bool isFinished() const; [[nodiscard]] bool isFinished() const;
[[nodiscard]] bool hadException() const; [[nodiscard]] bool hadException() const;
[[nodiscard]] bool wasInterrupted() const; [[nodiscard]] bool wasInterrupted() const;
@ -56,6 +57,7 @@ namespace hex {
std::function<void()> m_interruptCallback; std::function<void()> m_interruptCallback;
bool m_shouldInterrupt = false; bool m_shouldInterrupt = false;
bool m_background = true;
bool m_interrupted = false; bool m_interrupted = false;
bool m_finished = false; bool m_finished = false;
@ -89,6 +91,7 @@ namespace hex {
constexpr static auto NoProgress = 0; constexpr static auto NoProgress = 0;
static TaskHolder createTask(std::string name, u64 maxValue, std::function<void(Task &)> function); static TaskHolder createTask(std::string name, u64 maxValue, std::function<void(Task &)> function);
static TaskHolder createBackgroundTask(std::string name, std::function<void(Task &)> function);
static void collectGarbage(); static void collectGarbage();
static size_t getRunningTaskCount(); static size_t getRunningTaskCount();

View File

@ -9,11 +9,11 @@ namespace hex {
std::mutex TaskManager::s_deferredCallsMutex; std::mutex TaskManager::s_deferredCallsMutex;
std::list<std::shared_ptr<Task>> TaskManager::s_tasks; std::list<std::shared_ptr<Task>> TaskManager::s_tasks, s_backgroundTasks;
std::list<std::function<void()>> TaskManager::s_deferredCalls; std::list<std::function<void()>> TaskManager::s_deferredCalls;
Task::Task(std::string unlocalizedName, u64 maxValue, std::function<void(Task &)> function) Task::Task(std::string unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function)
: m_unlocalizedName(std::move(unlocalizedName)), m_currValue(0), m_maxValue(maxValue) { : m_unlocalizedName(std::move(unlocalizedName)), m_currValue(0), m_maxValue(maxValue), m_background(background) {
this->m_thread = std::thread([this, func = std::move(function)] { this->m_thread = std::thread([this, func = std::move(function)] {
try { try {
func(*this); func(*this);
@ -83,6 +83,12 @@ namespace hex {
this->m_interruptCallback = std::move(callback); this->m_interruptCallback = std::move(callback);
} }
bool Task::isBackgroundTask() const {
std::scoped_lock lock(this->m_mutex);
return this->m_background;
}
bool Task::isFinished() const { bool Task::isFinished() const {
std::scoped_lock lock(this->m_mutex); std::scoped_lock lock(this->m_mutex);
@ -164,13 +170,20 @@ namespace hex {
TaskHolder TaskManager::createTask(std::string name, u64 maxValue, std::function<void(Task &)> function) { TaskHolder TaskManager::createTask(std::string name, u64 maxValue, std::function<void(Task &)> function) {
s_tasks.emplace_back(std::make_shared<Task>(std::move(name), maxValue, std::move(function))); s_tasks.emplace_back(std::make_shared<Task>(std::move(name), maxValue, false, std::move(function)));
return TaskHolder(s_tasks.back()); return TaskHolder(s_tasks.back());
} }
TaskHolder TaskManager::createBackgroundTask(std::string name, std::function<void(Task &)> function) {
s_backgroundTasks.emplace_back(std::make_shared<Task>(std::move(name), 0, true, std::move(function)));
return TaskHolder(s_backgroundTasks.back());
}
void TaskManager::collectGarbage() { void TaskManager::collectGarbage() {
std::erase_if(s_tasks, [](const auto &task) { return task->isFinished() && !task->hadException(); }); std::erase_if(s_tasks, [](const auto &task) { return task->isFinished() && !task->hadException(); });
std::erase_if(s_backgroundTasks, [](const auto &task) { return task->isFinished(); });
} }
std::list<std::shared_ptr<Task>> &TaskManager::getRunningTasks() { std::list<std::shared_ptr<Task>> &TaskManager::getRunningTasks() {

View File

@ -52,6 +52,7 @@ namespace hex {
ImGui::Texture m_logoTexture = { nullptr }; ImGui::Texture m_logoTexture = { nullptr };
std::mutex m_popupMutex;
std::list<std::string> m_popupsToOpen; std::list<std::string> m_popupsToOpen;
std::vector<int> m_pressedKeys; std::vector<int> m_pressedKeys;

View File

@ -144,6 +144,8 @@ namespace hex {
}); });
EventManager::subscribe<RequestOpenPopup>(this, [this](auto name) { EventManager::subscribe<RequestOpenPopup>(this, [this](auto name) {
std::scoped_lock lock(this->m_popupMutex);
this->m_popupsToOpen.push_back(name); this->m_popupsToOpen.push_back(name);
}); });
@ -424,7 +426,8 @@ namespace hex {
ImGui::EndPopup(); ImGui::EndPopup();
} }
} }
{
std::scoped_lock lock(this->m_popupMutex);
this->m_popupsToOpen.remove_if([](const auto &name) { this->m_popupsToOpen.remove_if([](const auto &name) {
if (ImGui::IsPopupOpen(name.c_str())) if (ImGui::IsPopupOpen(name.c_str()))
return true; return true;
@ -433,6 +436,7 @@ namespace hex {
return false; return false;
}); });
}
TaskManager::runDeferredCalls(); TaskManager::runDeferredCalls();

View File

@ -106,14 +106,16 @@ namespace hex::plugin::builtin {
void ViewPatternData::drawContent() { void ViewPatternData::drawContent() {
if (ImGui::Begin(View::toWindowName("hex.builtin.view.pattern_data.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { if (ImGui::Begin(View::toWindowName("hex.builtin.view.pattern_data.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
if (ImHexApi::Provider::isValid()) {
auto provider = ImHexApi::Provider::get(); auto provider = ImHexApi::Provider::get();
if (ImHexApi::Provider::isValid() && provider->isReadable() && !ProviderExtraData::get(provider).patternLanguage.runtime->isRunning()) { auto &runtime = ProviderExtraData::get(provider).patternLanguage.runtime;
if (provider->isReadable() && runtime != nullptr && !runtime->isRunning()) {
auto &sortedPatterns = this->m_sortedPatterns[ImHexApi::Provider::get()]; auto &sortedPatterns = this->m_sortedPatterns[ImHexApi::Provider::get()];
if (beginPatternTable(provider, ProviderExtraData::get(provider).patternLanguage.runtime->getAllPatterns(), sortedPatterns)) { if (beginPatternTable(provider, ProviderExtraData::get(provider).patternLanguage.runtime->getAllPatterns(), sortedPatterns)) {
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
if (!sortedPatterns.empty()) {
if (!sortedPatterns.empty()) {
for (auto &patterns : sortedPatterns) for (auto &patterns : sortedPatterns)
patterns->accept(this->m_patternDrawer); patterns->accept(this->m_patternDrawer);
} }
@ -122,6 +124,7 @@ namespace hex::plugin::builtin {
} }
} }
} }
}
ImGui::End(); ImGui::End();
} }

View File

@ -114,15 +114,16 @@ namespace hex::plugin::builtin {
patternLanguageData.runtime = std::make_unique<pl::PatternLanguage>(); patternLanguageData.runtime = std::make_unique<pl::PatternLanguage>();
ContentRegistry::PatternLanguage::configureRuntime(*patternLanguageData.runtime, provider); ContentRegistry::PatternLanguage::configureRuntime(*patternLanguageData.runtime, provider);
TaskManager::createBackgroundTask("Analyzing file content", [this, provider, &data = patternLanguageData](auto &) {
if (!this->m_autoLoadPatterns) if (!this->m_autoLoadPatterns)
return; return;
// Copy over current pattern source code to the new provider // Copy over current pattern source code to the new provider
if (!this->m_syncPatternSourceCode) { if (!this->m_syncPatternSourceCode) {
patternLanguageData.sourceCode = this->m_textEditor.GetText(); data.sourceCode = this->m_textEditor.GetText();
} }
auto &runtime = patternLanguageData.runtime; auto &runtime = data.runtime;
auto mimeType = magic::getMIMEType(provider); auto mimeType = magic::getMIMEType(provider);
@ -167,6 +168,7 @@ namespace hex::plugin::builtin {
this->m_acceptPatternWindowOpen = true; this->m_acceptPatternWindowOpen = true;
} }
}); });
});
EventManager::subscribe<EventProviderChanged>(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) { EventManager::subscribe<EventProviderChanged>(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) {
if (!this->m_syncPatternSourceCode) { if (!this->m_syncPatternSourceCode) {

View File

@ -52,9 +52,17 @@ namespace hex::plugin::builtin {
}; };
static std::atomic<bool> s_recentProvidersUpdating = false;
static std::list<RecentProvider> s_recentProviders; static std::list<RecentProvider> s_recentProviders;
static void updateRecentProviders() { static void updateRecentProviders() {
TaskManager::createBackgroundTask("Updating recent files", [](auto&){
if (s_recentProvidersUpdating)
return;
s_recentProvidersUpdating = true;
ON_SCOPE_EXIT { s_recentProvidersUpdating = false; };
s_recentProviders.clear(); s_recentProviders.clear();
// Query all recent providers // Query all recent providers
@ -86,6 +94,7 @@ namespace hex::plugin::builtin {
} }
std::copy(uniqueProviders.begin(), uniqueProviders.end(), std::front_inserter(s_recentProviders)); std::copy(uniqueProviders.begin(), uniqueProviders.end(), std::front_inserter(s_recentProviders));
});
} }
static void loadRecentProvider(const RecentProvider &recentProvider) { static void loadRecentProvider(const RecentProvider &recentProvider) {
@ -227,6 +236,7 @@ namespace hex::plugin::builtin {
ImGui::UnderlinedText("hex.builtin.welcome.start.recent"_lang); ImGui::UnderlinedText("hex.builtin.welcome.start.recent"_lang);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled);
{ {
if (!s_recentProvidersUpdating) {
for (const auto &recentProvider : s_recentProviders) { for (const auto &recentProvider : s_recentProviders) {
ImGui::PushID(&recentProvider); ImGui::PushID(&recentProvider);
ON_SCOPE_EXIT { ImGui::PopID(); }; ON_SCOPE_EXIT { ImGui::PopID(); };
@ -237,6 +247,7 @@ namespace hex::plugin::builtin {
} }
} }
} }
}
if (ImHexApi::System::getInitArguments().contains("update-available")) { if (ImHexApi::System::getInitArguments().contains("update-available")) {
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5); ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5);
@ -500,7 +511,7 @@ namespace hex::plugin::builtin {
}); });
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1075, [&] { ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1075, [&] {
if (ImGui::BeginMenu("hex.builtin.menu.file.open_recent"_lang, !s_recentProviders.empty())) { if (ImGui::BeginMenu("hex.builtin.menu.file.open_recent"_lang, !s_recentProvidersUpdating && !s_recentProviders.empty())) {
// Copy to avoid changing list while iteration // Copy to avoid changing list while iteration
auto recentProviders = s_recentProviders; auto recentProviders = s_recentProviders;
for (auto &recentProvider : recentProviders) { for (auto &recentProvider : recentProviders) {