diff --git a/lib/libimhex/include/hex/api/imhex_api.hpp b/lib/libimhex/include/hex/api/imhex_api.hpp index dfcc13c5b..db22dbc16 100644 --- a/lib/libimhex/include/hex/api/imhex_api.hpp +++ b/lib/libimhex/include/hex/api/imhex_api.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -292,7 +293,7 @@ namespace hex { namespace impl { void resetClosingProvider(); - const std::vector& getClosingProviders(); + const std::set& getClosingProviders(); } diff --git a/lib/libimhex/include/hex/providers/provider_data.hpp b/lib/libimhex/include/hex/providers/provider_data.hpp index da0d5196f..aee4dd2dd 100644 --- a/lib/libimhex/include/hex/providers/provider_data.hpp +++ b/lib/libimhex/include/hex/providers/provider_data.hpp @@ -78,6 +78,10 @@ namespace hex { m_onCreateCallback = std::move(callback); } + void setOnDestroyCallback(std::function callback) { + m_onDestroyCallback = std::move(callback); + } + private: void onCreate() { EventProviderOpened::subscribe(this, [this](prv::Provider *provider) { @@ -88,7 +92,12 @@ namespace hex { }); EventProviderDeleted::subscribe(this, [this](prv::Provider *provider){ - m_data.erase(provider); + if (auto it = m_data.find(provider); it != m_data.end()) { + if (m_onDestroyCallback) + m_onDestroyCallback(provider, m_data.at(provider)); + + m_data.erase(it); + } }); EventImHexClosing::subscribe(this, [this] { @@ -113,6 +122,7 @@ namespace hex { } void onDestroy() { + EventProviderOpened::unsubscribe(this); EventProviderDeleted::unsubscribe(this); EventImHexClosing::unsubscribe(this); @@ -121,7 +131,7 @@ namespace hex { private: std::map m_data; - std::function m_onCreateCallback; + std::function m_onCreateCallback, m_onDestroyCallback; }; } \ No newline at end of file diff --git a/lib/libimhex/source/api/imhex_api.cpp b/lib/libimhex/source/api/imhex_api.cpp index d77fdc1af..9add3f7ba 100644 --- a/lib/libimhex/source/api/imhex_api.cpp +++ b/lib/libimhex/source/api/imhex_api.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #if defined(OS_WINDOWS) @@ -269,15 +270,16 @@ namespace hex { namespace impl { - static std::vector s_closingProviders; + static std::set s_closingProviders; void resetClosingProvider() { s_closingProviders.clear(); } - const std::vector& getClosingProviders() { + const std::set& getClosingProviders() { return s_closingProviders; } + static std::recursive_mutex s_providerMutex; } prv::Provider *get() { @@ -297,6 +299,8 @@ namespace hex { } void setCurrentProvider(i64 index) { + std::scoped_lock lock(impl::s_providerMutex); + if (TaskManager::getRunningTaskCount() > 0) return; @@ -310,6 +314,8 @@ namespace hex { } void setCurrentProvider(NonNull provider) { + std::scoped_lock lock(impl::s_providerMutex); + if (TaskManager::getRunningTaskCount() > 0) return; @@ -344,6 +350,8 @@ namespace hex { } void add(std::unique_ptr &&provider, bool skipLoadInterface, bool select) { + std::scoped_lock lock(impl::s_providerMutex); + if (TaskManager::getRunningTaskCount() > 0) return; @@ -358,14 +366,19 @@ namespace hex { } void remove(prv::Provider *provider, bool noQuestions) { + std::scoped_lock lock(impl::s_providerMutex); + if (provider == nullptr) return; if (TaskManager::getRunningTaskCount() > 0) return; + if (impl::s_closingProviders.contains(provider)) + return; + if (!noQuestions) { - impl::s_closingProviders.push_back(provider); + impl::s_closingProviders.insert(provider); bool shouldClose = true; EventProviderClosing::post(provider, &shouldClose); @@ -419,7 +432,7 @@ namespace hex { TaskManager::runWhenTasksFinished([it, provider] { EventProviderDeleted::post(provider); - std::erase(impl::s_closingProviders, provider); + impl::s_closingProviders.erase(provider); s_providers->erase(it); if (s_currentProvider >= i64(s_providers->size())) @@ -441,7 +454,6 @@ namespace hex { namespace ImHexApi::System { - namespace impl { // Default to true means we forward to ourselves by default diff --git a/lib/libimhex/source/api/task_manager.cpp b/lib/libimhex/source/api/task_manager.cpp index d5390dbb5..fbe9a3bf9 100644 --- a/lib/libimhex/source/api/task_manager.cpp +++ b/lib/libimhex/source/api/task_manager.cpp @@ -426,6 +426,10 @@ namespace hex { void TaskManager::runWhenTasksFinished(const std::function &function) { std::scoped_lock lock(s_tasksFinishedMutex); + for (const auto &task : s_tasks) { + task->interrupt(); + } + s_tasksFinishedCallbacks.push_back(function); } diff --git a/plugins/builtin/include/content/views/view_pattern_editor.hpp b/plugins/builtin/include/content/views/view_pattern_editor.hpp index ce2b4ae4e..70b45506c 100644 --- a/plugins/builtin/include/content/views/view_pattern_editor.hpp +++ b/plugins/builtin/include/content/views/view_pattern_editor.hpp @@ -218,6 +218,7 @@ namespace hex::plugin::builtin { PerProvider> m_envVarEntries; + PerProvider m_analysisTask; PerProvider m_shouldAnalyze; PerProvider m_breakpointHit; PerProvider> m_debuggerDrawer; diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index 3925dc1e2..260e4db43 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -1328,7 +1328,7 @@ namespace hex::plugin::builtin { if (m_shouldAnalyze) { m_shouldAnalyze = false; - TaskManager::createBackgroundTask("Analyzing file content", [this, provider](auto &) { + m_analysisTask = TaskManager::createBackgroundTask("Analyzing file content", [this, provider](const Task &task) { if (!m_autoLoadPatterns) return; @@ -1415,6 +1415,8 @@ namespace hex::plugin::builtin { std::error_code errorCode; for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Patterns)) { for (auto &entry : std::fs::recursive_directory_iterator(dir, errorCode)) { + task.update(); + foundCorrectType = false; if (!entry.is_regular_file()) continue;