MoCSI API Reference
Loading...
Searching...
No Matches
ChainManager.h
Go to the documentation of this file.
1#ifndef CHAIN_MANAGER_H
2#define CHAIN_MANAGER_H
3
4#include <algorithm>
5#include <concepts>
6#include <iostream>
7#include <map>
8#include <memory>
9#include <sstream>
10#include <string>
11#include <unordered_set>
12#include <vector>
13
18template <typename ModuleType>
19
20 requires requires(const ModuleType& module) {
21 module.getNameLocal(); // Checks if getNameLocal() exists and is callable
22 {
23 module.getNameLocal()
24 } -> std::constructible_from<std::string>; // Checks the return type
25 }
26
27class DependencyError : public std::exception
28{
29 private:
30 std::string m_error_string;
31
32 public:
41 const std::vector<std::shared_ptr<ModuleType>> unresolved_dependency_modules)
42 {
43 std::ostringstream oss;
44 oss << "Failed to resolve dependencies for the following modules:\n";
46 {
47 oss << module->getNameLocal() << "\n";
48 }
49 oss << "Please check the dependencies and resolve the circular or missing "
50 "dependencies.\n";
51 m_error_string = oss.str();
52 }
53
57 [[nodiscard]] const char* what() const noexcept override { return m_error_string.c_str(); }
58
59 ~DependencyError() override = default;
60};
61
68template <typename ModuleType>
70{
71 private:
72 using ModuleList = std::vector<std::shared_ptr<ModuleType>>;
73 std::map<std::string_view, ModuleList> m_chain_map{};
74
75 bool checkDependencyCurrentModule(std::shared_ptr<ModuleType> module,
76 ModuleList& sorted_chain_module_vector);
77
78 public:
80 ChainManager(std::string_view chain_type);
81
82 void insertModule(std::string_view key, const std::shared_ptr<ModuleType>& module);
83
84 void runChain(std::string_view key);
85
86 void runSingleModuleInChain(std::string_view chain_key, std::string_view module_key);
87
88 void autoLoader(const ModuleList& all_modules);
89
90 void autoLoader(const ModuleList& all_modules,
91 const std::vector<std::string>& modules_to_load);
92
93 std::vector<std::string> getChainNames() const;
94
95 std::unordered_set<std::string> getManagingModuleNames() const;
96
98};
99
104template <typename ModuleType>
108
114template <typename ModuleType>
116{
117 if (chain_type == "global")
118 {
119 m_chain_map.insert({"InitChain", std::vector<std::shared_ptr<ModuleType>>{}});
120 m_chain_map.insert({"PreTimeStepChain", std::vector<std::shared_ptr<ModuleType>>{}});
121 m_chain_map.insert({"PostNonLinIterChain", std::vector<std::shared_ptr<ModuleType>>{}});
122 m_chain_map.insert({"PostTimeStepChain", std::vector<std::shared_ptr<ModuleType>>{}});
123 m_chain_map.insert({"OutputChain", std::vector<std::shared_ptr<ModuleType>>{}});
124 }
125}
126
133template <typename ModuleType>
135 const std::shared_ptr<ModuleType>& module)
136{
137 m_chain_map[key].emplace_back(module);
138}
139
145template <typename ModuleType>
147{
148 // std::cout << "Entered with key: " << key << "\n";
149 for (const auto& module_pointer :
150 m_chain_map[key]) // m_chain_map[key] is a
151 // std::vector<std::shared_ptr<GenericManagingModule<T>>>
152 {
153 module_pointer->exec(key);
154 }
155}
156
164template <typename ModuleType>
166 std::string_view module_key)
167{
168 for (const auto& module_pointer :
169 m_chain_map[chain_key]) // m_chain_map[key] is a
170 // std::vector<std::shared_ptr<GenericManagingModule<T>>>
171 {
172 if (module_pointer->getNameLocal() == module_key)
173 {
175 }
176 }
177}
178
186template <typename ModuleType>
188{
189 for (auto& module : all_modules)
190 {
191 for (auto& key : module->getChainInsertion())
192 {
193 insertModule(key, module);
194 }
195 }
196 resolveDependencies();
197}
198
207template <typename ModuleType>
209 const std::vector<std::string>& modules_to_load)
210{
211 std::unordered_set<std::string> modules_to_load_set(modules_to_load.begin(),
212 modules_to_load.end());
213
214 for (auto& module : all_modules)
215 {
216 std::string mod_name{module->getNameLocal()};
217 if (modules_to_load_set.contains(mod_name))
218 {
219 for (auto& key : module->getChainInsertion())
220 {
221 insertModule(key, module);
222 }
223 }
224 }
225 resolveDependencies();
226}
227
233template <typename ModuleType>
235{
236 // Check dependencies for every chain
237 for (auto& [key, chain_module_vector] : m_chain_map)
238 {
239 std::vector<std::shared_ptr<ModuleType>> sorted_chain_module_vector{};
240 while (!chain_module_vector.empty())
241 {
242 bool progress = false;
243
244 // Use remove_if to partition the modules: move those with resolved dependencies to the
245 // front
246 auto current_module = std::remove_if(
248 [&](const auto& module)
249 {
250 // If all dependencies are resolved, move this module to the front
251 if (checkDependencyCurrentModule(module, sorted_chain_module_vector))
252 {
253 sorted_chain_module_vector.push_back(module);
254 progress = true;
255 return true; // Mark it for removal (just shifting it)
256 }
257 return false; // Keep the module in place
258 });
259
260 // Erase the modules that were marked for removal (those with unresolved dependencies
261 // stay)
263
264 // If no progress was made, there are circular or missing dependencies
265 if (!progress)
266 {
268 }
269 }
271 }
272}
273
282template <typename ModuleType>
284 ModuleList& sorted_chain_module_vector)
285{
286 std::vector<std::string> module_dependencies{module->getDependencies()};
287 // If there are no dependencies, the module can always be placed
288 if (module_dependencies.empty())
289 {
290 return true;
291 }
292
293 std::unordered_set<std::string_view> resolved_names;
294 for (const auto& sorted_module : sorted_chain_module_vector)
295 {
296 resolved_names.insert(sorted_module->getNameLocal());
297 }
298
299 // Check if all dependencies are resolved
300 return std::all_of(module_dependencies.begin(), module_dependencies.end(),
301 [&resolved_names](const std::string& dependency)
302 { return resolved_names.contains(dependency); });
303}
304
308template <typename ModuleType>
309std::vector<std::string> ChainManager<ModuleType>::getChainNames() const
310{
311 std::vector<std::string> chain_names{};
312 chain_names.reserve(m_chain_map.size());
313 for (const auto& [key, chain] : m_chain_map)
314 {
315 chain_names.emplace_back(key);
316 }
317 return chain_names;
318}
319
326template <typename ModuleType>
327std::unordered_set<std::string> ChainManager<ModuleType>::getManagingModuleNames() const
328{
329 std::unordered_set<std::string> unique_module_names_set;
330 for (auto& [chain_key, chain_module_vector] : m_chain_map)
331 {
332 for (auto const& module_pointer : chain_module_vector)
333 {
334 std::string module_name{module_pointer->getNameLocal()};
336 }
337 }
339}
340
341#endif
Template generalized ChainManager. It stores pointers to the modules and runs their exec-function on ...
Definition ChainManager.h:70
void runChain(std::string_view key)
Runs the exec-functions of each module within the specified chain (if existing).
Definition ChainManager.h:146
void autoLoader(const ModuleList &all_modules, const std::vector< std::string > &modules_to_load)
Inserts only user specified modules derived from a module type into the chain in the load-order....
Definition ChainManager.h:208
void autoLoader(const ModuleList &all_modules)
Inserts all modules derived from a module type into the chain in the load-order. Only used for module...
Definition ChainManager.h:187
std::unordered_set< std::string > getManagingModuleNames() const
Function that returns the names of the requested/loaded managing modules.
Definition ChainManager.h:327
void insertModule(std::string_view key, const std::shared_ptr< ModuleType > &module)
Insert modules into chains. Generates a new chain, if the chain key does not yet exist.
Definition ChainManager.h:134
std::vector< std::string > getChainNames() const
Getter function for the chain names.
Definition ChainManager.h:309
void resolveDependencies()
Guarantees that the module order is correct to ensure all dependencies are met. Throws a DependencyEr...
Definition ChainManager.h:234
void runSingleModuleInChain(std::string_view chain_key, std::string_view module_key)
Runs the exec-function of a singular specified module within a specified chain (if existing).
Definition ChainManager.h:165
ChainManager(std::string_view chain_type)
Constructor of the chain manager with possibility to specify chain type. Option(s): "global"....
Definition ChainManager.h:115
ChainManager()
Constructor of the chain manager without arguments. Does not initialize chains, so the have to be add...
Definition ChainManager.h:105
Concrete implementation of a matrix class representing a Compressed Sparse Rows (CSR) matrix....
Definition CsrMatrix.h:35
CsrSparseMatrix()
Constructor for an empty CsrSparseMatrix object. Leaves all storage arrays empty but sets the flag to...
Definition CsrMatrix.h:92
Error class to throw when a module chain has circular or missing dependencies. Inherits from std::exc...
Definition ChainManager.h:28
DependencyError(const std::vector< std::shared_ptr< ModuleType > > unresolved_dependency_modules)
Definition ChainManager.h:40
~DependencyError() override=default
const char * what() const noexcept override
Supplies the error message as a c-style string/char array.
Definition ChainManager.h:57