diff --git a/include/utils/App/App.h b/include/utils/App/App.h index 8039f06..3a63237 100644 --- a/include/utils/App/App.h +++ b/include/utils/App/App.h @@ -15,17 +15,19 @@ namespace Archimedes { std::abort(); } instance = this; + roInsert = runOrder.begin(); } virtual ~App() { - for(auto it = modules.begin(); it != modules.end(); it++) { - void* handle = (*it)->getHandle(); - delete *it; + for(std::string s : runOrder) { + void* handle = modules[s]->getHandle(); + delete modules[s]; if(handle) dlclose(handle); - it = modules.erase(it); + modules[s] = nullptr; } + runOrder.clear(); } @@ -35,13 +37,15 @@ namespace Archimedes { virtual void run() = 0; - virtual void stopModule(std::list::iterator it) { toClose.push_back(*it); } + virtual void stopModule(std::string lib) { toClose.push_back(lib); } virtual void startModule(std::string lib) { toOpen.push_back(lib); } void end() { done = true; } private: + + std::list::iterator roInsert; inline static App* instance = nullptr; @@ -52,7 +56,7 @@ namespace Archimedes { std::unordered_map modules; std::list runOrder; - std::list toClose; + std::list toClose; std::list toOpen; virtual Module* dynamicLoad(std::string lib) { @@ -75,12 +79,12 @@ namespace Archimedes { return create(h, Get()); } - virtual Module* load(std::string modulePath, std::list::iterator ins) { + virtual Module* load(std::string modulePath) { Module* m = dynamicLoad(modulePath); - return load(m, ins); + return load(m); } - virtual Module* load(Module* m, std::list::iterator ins) { + virtual Module* load(Module* m) { if(!m) { return nullptr; @@ -97,36 +101,51 @@ namespace Archimedes { } } - bool skip = false; + modules[m->getName()] = m; + for(auto it = runOrder.begin(); it != runOrder.end(); it++) { if(m->deps.find(*it) != m->deps.end()) { - skip = true; m->depsInstances[*it] = modules[*it]; - } - if(skip) { - skip = false; - continue; - } else { + //modules should be located after their dependencies + if(std::distance(roInsert, it) <= 0) { + roInsert = ++it--; + } + } + } + + //insert temporarily to avoid circular dependencies + runOrder.insert(roInsert, m->getName()); + + for(auto it = runOrder.begin(); it != runOrder.end(); it++) { + + if(m->deps.find(*it) == m->deps.end()) { if(std::holds_alternative(m->deps[*it])) - m->depsInstances[*it] = load(std::get(m->deps[*it]), ins); + m->depsInstances[*it] = load(std::get(m->deps[*it])); else - m->depsInstances[*it] = load(std::get(m->deps[*it]), ins); + m->depsInstances[*it] = load(std::get(m->deps[*it])); } } + //reinsert once final order has been reached + runOrder.remove(m->getName()); + + runOrder.insert(roInsert, m->getName()); + return m; } - virtual void unload(std::list::iterator it) { - Module* m = *it; + virtual void unload(std::string name) { + Module* m = modules[name]; void* h = m->getHandle(); - modules.erase(m->self); + modules[name] = nullptr; delete m; if(h) dlclose(h); + + runOrder.remove(name); } virtual void printHelp() = 0; diff --git a/modules/examples/GuiModules/TestImgui/src/TestImgui.cpp b/modules/examples/GuiModules/TestImgui/src/TestImgui.cpp index c4b89b7..8dd352d 100644 --- a/modules/examples/GuiModules/TestImgui/src/TestImgui.cpp +++ b/modules/examples/GuiModules/TestImgui/src/TestImgui.cpp @@ -13,8 +13,8 @@ TestImgui::TestImgui(void* h, Archimedes::App* a) : Archimedes::GuiModule(h, a) TestImgui::~TestImgui() { - std::list* cmdList = - std::any_cast*>(depsInstances["WindowModule"]->getData("renderCmdList")); + std::list* cmdList = + std::any_cast*>(depsInstances["WindowModule"]->getData("renderCmdList")); cmdList->erase(rcmd); ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); diff --git a/src/example_apps/MinimalApp/MinimalApp.cpp b/src/example_apps/MinimalApp/MinimalApp.cpp index 092f94c..b3d3d3b 100644 --- a/src/example_apps/MinimalApp/MinimalApp.cpp +++ b/src/example_apps/MinimalApp/MinimalApp.cpp @@ -2,23 +2,23 @@ void MinimalApp::run() { - for(auto* m : modules) - m->onLoad(); + for(auto m : runOrder) + modules[m]->onLoad(); // Main loop - while (!done && !modules.empty()) { + while (!done && !runOrder.empty()) { - for(auto* m : modules) { - m->run(); + for(auto m : runOrder) { + modules[m]->run(); } - for(auto it = toClose.begin(); it != toClose.end(); it++) { - unload(it); + for(auto m : toClose) { + unload(m); } toClose.clear(); - for(std::string s : toOpen) { - load(s, modules.begin()); + for(std::string m : toOpen) { + load(m); } toOpen.clear(); } diff --git a/src/example_apps/MinimalApp/MinimalApp.h b/src/example_apps/MinimalApp/MinimalApp.h index 316e04d..b1e3487 100644 --- a/src/example_apps/MinimalApp/MinimalApp.h +++ b/src/example_apps/MinimalApp/MinimalApp.h @@ -14,7 +14,7 @@ class MinimalApp : public Archimedes::App { void handleArgs(const int& argc, char* argv[]) { if(argc > 1) { for(int i = 1; i < argc; i++) - load(dynamicLoad(argv[i]), modules.begin()); + load(dynamicLoad(argv[i])); } else { std::cout << "No modules to load\n"; end();