SAE Teensy ECU
IIT SAE Microcontroller programming
Loading...
Searching...
No Matches
moduleOrder.hpp
Go to the documentation of this file.
1
12#ifndef __MODULEORDER_HPP__
13#define __MODULEORDER_HPP__
14
15#include "mainModule.hpp"
16#include "manager.hpp"
17
18#include <list>
19#include <map>
20#include <vector>
21
22namespace Module {
23
24static bitmapVal_t errC = 0;
25static const Module_t *errorVec[maxModules] = {0};
26
27struct Node {
28 bool marked = false;
29 const Module_t *module = nullptr;
30 bitmapVal_t nID = 0U;
31 bitmapVal_t dependencies = 0U;
32 bitmapVal_t *depList[maxModules] = {0};
33 Node(const Module_t *module, bitmapVal_t nID) : module{module}, nID{nID} {
34 }
35};
36
37bool finder(Node *n, std::map<bitmapVal_t, Node *> &nodesR, std::list<Node *> &error, bool &done) {
38 if (nodesR[n->nID]->marked) {
39 error.push_back(n);
40 return true;
41 }
42 nodesR[n->nID]->marked = true;
43
44 for (bitmapVal_t *v : n->depList) {
45 if (v == 0)
46 break;
47 auto node = nodesR.find(*v);
48 if (node != nodesR.end()) {
49 if (finder(node->second, nodesR, error, done)) {
50 if (!done && error.front()->nID != n->nID)
51 error.push_back(n);
52 else
53 done = true;
54 return true;
55 }
56 }
57 }
58 return false;
59}
60
61bool Manager_t::orderModules() {
62 errC = 0;
63 std::list<Node *> nodes;
64
65 bitmapVal_t final = 0;
66 bitmapVal_t mapped = 0;
67
68 int c = 0;
69 const Module_t *newModules[s_id];
70
71 Log.d(ID, "Mapping module nodes");
72
73 // Map modules to nodes
74 for (size_t i = 0; i < s_id; i++) {
75 const Module_t *mod = allModules[i];
76 Node *node = new Node(mod, mod->id);
77
78 bitmapVal_t dC = allModules[i]->count;
79
80 if (dC == 0) { // mapped starts with 'root' nodes (no deps)
81 Log.d(ID, "Root node", node->nID);
82 node->marked = true;
83 mapped |= node->nID;
84 newModules[c++] = node->module;
85 delete node;
86 } else {
87 Log.d(ID, "Dependent node", node->nID);
88 const Module_t *const *dependents = allModules[i]->dependents;
89 for (size_t j = 0; j < allModules[i]->count; j++) {
90 const Module_t *dep = dependents[j];
91 Log.d(ID, " ├─ Dependency", dep->id);
92 node->dependencies |= dep->id;
93 dep++;
94 }
95 Log.d(ID, " └ Final dependencies", node->dependencies);
96 nodes.push_back(node);
97 }
98 final |= node->nID;
99 }
100
101 int last_c = c;
102
103 Log.d(ID, "Tracing graph");
104
105 while (mapped != final) {
106 bitmapVal_t _mapped = mapped;
107
108 typename std::list<Node *>::iterator iter;
109
110 for (iter = nodes.begin(); iter != nodes.end();) {
111 Node *node = *iter;
112 if ((mapped & node->dependencies) && !(~mapped & node->dependencies)) {
113 _mapped |= node->nID;
114 newModules[c++] = node->module;
115 delete node;
116 iter = nodes.erase(iter);
117 } else {
118 iter++;
119 }
120 }
121
122 if (last_c == c) { // Circular dependency
123
124 Log.f(ID, "Circular dependency detected");
125
126 std::list<Node *> error;
127
128 std::map<bitmapVal_t, Node *> nodesR;
129 for (Node *node : nodes) {
130 nodesR[node->nID] = node;
131 }
132
133 bool done = false;
134
135 for (Node *node : nodes) {
136 if (finder(node, nodesR, error, done))
137 break;
138
139 for (auto &n : nodesR) {
140 n.second->marked = false;
141 }
142 }
143
144 for (Node *node : error) {
145 errorVec[errC++] = node->module;
146 }
147#if CONF_LOGGING_ASCII_DEBUG
148 for (bitmapVal_t i = 0; i < errC - 1; i++) {
149 Serial.print(errorVec[i]->id);
150 Serial.print(" <---> ");
151 }
152 Serial.println(errorVec[errC - 1]->id);
153#else
154 for (bitmapVal_t i = 0; i < errC - 1; i++) {
155 Log.e(ID, "Depends on vv", errorVec[i]->id);
156 }
157 Log.e(ID, "Circles back to start ^^", errorVec[errC - 1]->id);
158#endif
159 return false;
160 }
161
162 last_c = c;
163
164 mapped |= _mapped;
165 }
166
167 for (Node *node : nodes) {
168 delete node;
169 }
170
171 Log.d(ID, "Modules ordered", c);
172
173 std::copy(newModules, newModules + s_id, allModules);
174 return true;
175}
176
177} // namespace Module
178
179#endif // __MODULEORDER_HPP__
Logging::Log_t Log
The global logging object.
Module_t should be used for major components of a framework, it is used to isolate,...
void d(LOG_TAG TAG, LOG_MSG message)
Log a string using a debug tag.
void e(LOG_TAG TAG, LOG_MSG message)
Log a string using an error tag.
void f(LOG_TAG TAG, LOG_MSG message)
Log a string using a fatal tag.