24 #include "SharedLogging.h"
27 static QDebug operator<<(QDebug debug,
const std::string& s) {
28 QDebugStateSaver saver(debug);
29 debug.nospace() << s.c_str();
36 using Map = std::map<K, size_t>;
46 Counter(
const std::string& name, LogLevel logLevel = LogLevel::DETAILED) :
47 _logLevel{ logLevel } {
53 void add(
const K& key,
size_t inc = 1);
56 void sub(
const K& key,
size_t dec = 1);
63 std::vector<std::string> _legend;
78 using Map = std::map<K, size_t>;
79 using DuplicateValueMap = std::map<size_t, size_t>;
80 using DuplicateMap = std::map<K, DuplicateValueMap>;
95 Tracker(
const std::string& name,
const std::vector<std::string>& legend, LogLevel logLevel = SUMMARY,
bool allowReuse =
true) :
96 _logLevel{ logLevel }, _allowReuse{ allowReuse }, _max{ legend.size() - 1 } {
100 ~Tracker() { log(); }
105 void set(
const K& key,
const size_t& state);
112 std::vector<std::string> _legend;
119 DuplicateMap _duplicates;
123 void Counter<K>::add(
const K& k,
size_t inc) {
124 std::lock_guard<std::mutex> lock(_mutex);
126 auto& it = _map.find(k);
128 if (it == _map.end()) {
130 _map.insert(std::pair<K, size_t>(k, inc));
138 void Counter<K>::sub(
const K& k,
size_t dec) {
143 void Counter<K>::log() {
145 if (!_map.size())
return;
147 std::map<size_t, size_t> results;
148 for (
const auto& entry : _map) {
149 if (!results.insert(std::pair<size_t, size_t>(entry.second, 1)).second) {
150 results.find(entry.second)->second++;
154 qCDebug(shared) <<
"Counts for" << _name;
155 for (
const auto& entry : results) {
156 qCDebug(shared) << entry.first <<
'\t' << entry.second <<
"entries";
158 if (_logLevel == LogLevel::SUMMARY)
return;
160 qCDebug(shared) <<
"Entries";
161 for (
const auto& entry : _map) {
162 qCDebug(shared) << entry.first <<
'\t' << entry.second;
164 if (_logLevel == LogLevel::DETAILED)
return;
168 void Tracker<K>::set(
const K& k,
const size_t& v) {
169 std::lock_guard<std::mutex> lock(_mutex);
171 auto& it = _map.find(k);
173 if (it == _map.end()) {
175 _map.insert(std::pair<K, size_t>(k, v));
176 }
else if (v > it->second) {
179 }
else if (v == it->second) {
181 auto& dit = _duplicates.find(k);
183 if (dit == _duplicates.end()) {
185 DuplicateValueMap duplicateValueMap{ std::pair<size_t, size_t>(v, 1) };
186 _duplicates.insert(std::pair<K, DuplicateValueMap>(k, duplicateValueMap));
189 auto& dvit = dit->second.find(v);
191 if (dvit == dit->second.end()) {
193 dit->second.insert(std::pair<size_t, size_t>(v, 1));
200 if (_allowReuse && it->second == _max) {
205 qCDebug(shared) <<
"Badly ordered entry detected:" <<
206 k << _legend.at(it->second).c_str() <<
"->" << _legend.at(v).c_str();
214 void Tracker<K>::log() {
216 if (!_map.size())
return;
218 std::vector<std::vector<K>> results(_max + 1);
219 for (
const auto& entry : _map) {
220 results.at(entry.second).push_back(entry.first);
223 qCDebug(shared) <<
"Summary of" << _name;
224 for (
auto i = 0; i < results.size(); ++i) {
225 qCDebug(shared) << _legend.at(i) <<
'\t' << results[i].size() <<
"entries";
227 if (_logLevel == LogLevel::SUMMARY)
return;
230 for (
const auto& entry : _duplicates) {
231 size += entry.second.size();
233 qCDebug(shared) <<
"Duplicates" << size <<
"entries";
235 if (_logLevel <= LogLevel::DUPLICATES)
return;
237 qCDebug(shared) <<
"Entries";
239 for (
auto i = 0; i < _max; ++i) {
240 qCDebug(shared) <<
"----" << _legend.at(i) <<
"----";
241 for (
const auto& entry : results[i]) {
242 qCDebug(shared) <<
"\t" << entry;
245 if (_logLevel <= LogLevel::DETAILED)
return;