27 static std::string getUniqString(
const std::string& s) {
28 static std::atomic<size_t> counter{ 0 };
29 return s +
'(' + std::to_string(counter.fetch_add(1)) +
')';
33 static QDebug operator<<(QDebug debug,
const std::string& s) {
34 QDebugStateSaver saver(debug);
35 debug.nospace() << s.c_str();
42 using Map = std::map<K, size_t>;
52 Counter(
const std::string& name, LogLevel logLevel = LogLevel::DETAILED) :
53 _logLevel{ logLevel } {
59 void add(
const K& key,
size_t inc = 1);
62 void sub(
const K& key,
size_t dec = 1);
69 std::vector<std::string> _legend;
84 using Map = std::map<K, size_t>;
85 using DuplicateValueMap = std::map<size_t, size_t>;
86 using DuplicateMap = std::map<K, DuplicateValueMap>;
101 Tracker(
const std::string& name,
const std::vector<std::string>& legend, LogLevel logLevel = SUMMARY,
bool allowReuse =
true) :
102 _logLevel{ logLevel }, _allowReuse{ allowReuse }, _max{ legend.size() - 1 } {
106 ~Tracker() { log(); }
111 void set(
const K& key,
const size_t& state);
118 std::vector<std::string> _legend;
125 DuplicateMap _duplicates;
129 void Counter<K>::add(
const K& k,
size_t inc) {
130 std::lock_guard<std::mutex> lock(_mutex);
132 auto& it = _map.find(k);
134 if (it == _map.end()) {
136 _map.insert(std::pair<K, size_t>(k, inc));
144 void Counter<K>::sub(
const K& k,
size_t dec) {
149 void Counter<K>::log() {
151 if (!_map.size())
return;
153 std::map<size_t, size_t> results;
154 for (
const auto& entry : _map) {
155 if (!results.insert(std::pair<size_t, size_t>(entry.second, 1)).second) {
156 results.find(entry.second)->second++;
160 qCDebug(shared) <<
"Counts for" << _name;
161 for (
const auto& entry : results) {
162 qCDebug(shared) << entry.first <<
'\t' << entry.second <<
"entries";
164 if (_logLevel == LogLevel::SUMMARY)
return;
166 qCDebug(shared) <<
"Entries";
167 for (
const auto& entry : _map) {
168 qCDebug(shared) << entry.first <<
'\t' << entry.second;
170 if (_logLevel == LogLevel::DETAILED)
return;
174 void Tracker<K>::set(
const K& k,
const size_t& v) {
175 std::lock_guard<std::mutex> lock(_mutex);
177 auto& it = _map.find(k);
179 if (it == _map.end()) {
181 _map.insert(std::pair<K, size_t>(k, v));
182 }
else if (v > it->second) {
185 }
else if (v == it->second) {
187 auto& dit = _duplicates.find(k);
189 if (dit == _duplicates.end()) {
191 DuplicateValueMap duplicateValueMap{ std::pair<size_t, size_t>(v, 1) };
192 _duplicates.insert(std::pair<K, DuplicateValueMap>(k, duplicateValueMap));
195 auto& dvit = dit->second.find(v);
197 if (dvit == dit->second.end()) {
199 dit->second.insert(std::pair<size_t, size_t>(v, 1));
206 if (_allowReuse && it->second == _max) {
211 qCDebug(shared) <<
"Badly ordered entry detected:" <<
212 k << _legend.at(it->second).c_str() <<
"->" << _legend.at(v).c_str();
220 void Tracker<K>::log() {
222 if (!_map.size())
return;
224 std::vector<std::vector<K>> results(_max + 1);
225 for (
const auto& entry : _map) {
226 results.at(entry.second).push_back(entry.first);
229 qCDebug(shared) <<
"Summary of" << _name;
230 for (
auto i = 0; i < results.size(); ++i) {
231 qCDebug(shared) << _legend.at(i) <<
'\t' << results[i].size() <<
"entries";
233 if (_logLevel == LogLevel::SUMMARY)
return;
236 for (
const auto& entry : _duplicates) {
237 size += entry.second.size();
239 qCDebug(shared) <<
"Duplicates" << size <<
"entries";
241 if (_logLevel <= LogLevel::DUPLICATES)
return;
243 qCDebug(shared) <<
"Entries";
245 for (
auto i = 0; i < _max; ++i) {
246 qCDebug(shared) <<
"----" << _legend.at(i) <<
"----";
247 for (
const auto& entry : results[i]) {
248 qCDebug(shared) <<
"\t" << entry;
251 if (_logLevel <= LogLevel::DETAILED)
return;