mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-20 17:32:26 +00:00
Convert actions storage to unordered_map
Enhance action lookup efficiency by switching from a vector to an unordered_map, allowing faster access by action ID.
This commit is contained in:
@@ -75,18 +75,14 @@ void ActionRegistry::upsert(std::shared_ptr<AppAction> action)
|
||||
return;
|
||||
|
||||
seed_state(*action);
|
||||
auto existing = std::find_if(m_actions.begin(), m_actions.end(),
|
||||
[&](const auto& current) { return current->id == action->id; });
|
||||
if (existing == m_actions.end())
|
||||
m_actions.push_back(std::move(action));
|
||||
else
|
||||
*existing = std::move(action);
|
||||
std::string id = action->id;
|
||||
m_actions.insert_or_assign(std::move(id), std::move(action));
|
||||
}
|
||||
|
||||
void ActionRegistry::remove(const std::string& id)
|
||||
{
|
||||
assert(wxThread::IsMain());
|
||||
erase_id(id);
|
||||
m_actions.erase(id);
|
||||
}
|
||||
|
||||
void ActionRegistry::seed_state(AppAction& a) const
|
||||
@@ -110,8 +106,8 @@ void ActionRegistry::seed_state(AppAction& a) const
|
||||
const AppAction* ActionRegistry::by_id(const std::string& id) const
|
||||
{
|
||||
assert(wxThread::IsMain());
|
||||
auto it = std::find_if(m_actions.begin(), m_actions.end(), [&](const auto& a) { return a->id == id; });
|
||||
return it == m_actions.end() ? nullptr : it->get();
|
||||
auto it = m_actions.find(id);
|
||||
return it == m_actions.end() ? nullptr : it->second.get();
|
||||
}
|
||||
|
||||
AppAction* ActionRegistry::find(const std::string& id)
|
||||
@@ -119,25 +115,18 @@ AppAction* ActionRegistry::find(const std::string& id)
|
||||
return const_cast<AppAction*>(by_id(id));
|
||||
}
|
||||
|
||||
void ActionRegistry::erase_id(const std::string& id)
|
||||
{
|
||||
m_actions.erase(std::remove_if(m_actions.begin(), m_actions.end(),
|
||||
[&](const auto& a) { return a->id == id; }),
|
||||
m_actions.end());
|
||||
}
|
||||
|
||||
// ---- dispatch + write-through ----------------------------------------------
|
||||
|
||||
AppActionRunResult ActionRegistry::run(const std::string& id)
|
||||
{
|
||||
assert(wxThread::IsMain());
|
||||
auto it = std::find_if(m_actions.begin(), m_actions.end(), [&](const auto& e) { return e->id == id; });
|
||||
auto it = m_actions.find(id);
|
||||
if (it == m_actions.end())
|
||||
return {}; // default Info, empty message
|
||||
// why: hold a shared_ptr keep-alive, never a bare vector element. A runner may pump
|
||||
// a nested event loop; a queued source refresh can erase this action from m_actions,
|
||||
// while the keep-alive preserves the object until run returns.
|
||||
std::shared_ptr<AppAction> keep = *it;
|
||||
// why: hold a shared_ptr keep-alive, never a bare map entry. A runner may pump a
|
||||
// nested event loop; a queued source refresh can erase the entry while the
|
||||
// keep-alive preserves the action until run returns.
|
||||
std::shared_ptr<AppAction> keep = it->second;
|
||||
AppActionRunResult o = keep->run();
|
||||
if (o.level == AppActionRunResult::Level::Busy)
|
||||
return o;
|
||||
@@ -210,16 +199,20 @@ nlohmann::json ActionRegistry::snapshot() const
|
||||
assert(wxThread::IsMain());
|
||||
std::vector<const AppAction*> sorted;
|
||||
sorted.reserve(m_actions.size());
|
||||
for (const auto& a : m_actions)
|
||||
sorted.push_back(a.get());
|
||||
for (const auto& entry : m_actions)
|
||||
sorted.push_back(entry.second.get());
|
||||
|
||||
const long long now = (long long) std::time(nullptr);
|
||||
std::stable_sort(sorted.begin(), sorted.end(), [&](const AppAction* a, const AppAction* b) {
|
||||
std::sort(sorted.begin(), sorted.end(), [&](const AppAction* a, const AppAction* b) {
|
||||
double sa = frecency_score(a->count, a->last, now);
|
||||
double sb = frecency_score(b->count, b->last, now);
|
||||
if (sa != sb)
|
||||
return sa > sb;
|
||||
return a->title < b->title; // ties alphabetical
|
||||
if (a->title != b->title)
|
||||
return a->title < b->title;
|
||||
if (a->source != b->source)
|
||||
return a->source < b->source;
|
||||
return a->id < b->id;
|
||||
});
|
||||
|
||||
nlohmann::json actions = nlohmann::json::array();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -81,7 +82,6 @@ public:
|
||||
void remove(const std::string& id);
|
||||
|
||||
// Always-clean read surface. UI thread only.
|
||||
const std::vector<std::shared_ptr<AppAction>>& all() const { assert(wxThread::IsMain()); return m_actions; }
|
||||
const AppAction* by_id(const std::string& id) const;
|
||||
|
||||
// Dispatch + write-through (registry is the only thing that touches AppConfig).
|
||||
@@ -99,15 +99,9 @@ public:
|
||||
private:
|
||||
void seed_state(AppAction& a) const; // favourite/stats from config
|
||||
AppAction* find(const std::string& id);
|
||||
void erase_id(const std::string& id);
|
||||
|
||||
// why: vector storage favors the popup path, which snapshots by iterating, sorting, and
|
||||
// serializing small action sets. Id lookups are event-driven and initialization is startup-only, so
|
||||
// a persistent map would add hashing/allocation cost without helping render.
|
||||
// shared_ptr: AppAction is abstract (stored by pointer), and run() takes a keep-alive
|
||||
// copy so a queued source refresh cannot erase the object mid-run.
|
||||
std::vector<std::unique_ptr<IActionSource>> m_sources;
|
||||
std::vector<std::shared_ptr<AppAction>> m_actions; // UI-thread confined; no lock
|
||||
std::unordered_map<std::string, std::shared_ptr<AppAction>> m_actions; // UI-thread confined; no lock
|
||||
};
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
Reference in New Issue
Block a user