#pragma once #include #include #include #include #include #include #include #include #include #include #include #include template class snDataCache { public: explicit snDataCache(std::size_t maxEntries = 300) : maxEntries(maxEntries) { if (maxEntries == 0) { throw std::invalid_argument("snDataCache maxEntries must be greater than zero"); } } std::shared_ptr get(const std::string& sn,const summaryDataTemplate& defvalue) { QMutexLocker locker(&_mutex); auto it = map.find(sn); if (it != map.end()) { return it->second.first; } return insert(sn, defvalue); } void set(const std::string& sn, const summaryDataTemplate& value) { QMutexLocker locker(&_mutex); auto it = map.find(sn); if (it != map.end()) { it->second.first = std::make_shared(value); return; } insert(sn, value); } std::size_t size() const { QMutexLocker locker(&_mutex); return map.size(); } bool remove(const std::string& sn) { QMutexLocker locker(&_mutex); auto it = map.find(sn); if (it != map.end()) { order.erase(it->second.second); map.erase(it); return true; } return false; } private: std::shared_ptr insert(const std::string& sn, const summaryDataTemplate& value) { auto newValue = std::make_shared(value); order.push_back(sn); auto list_it = std::prev(order.end()); try { map.emplace(sn, std::make_pair(newValue, list_it)); } catch (...) { order.pop_back(); throw; } cleanOldest(); return newValue; } void cleanOldest() { while (map.size() > maxEntries) { const std::string& oldest_sn = order.front(); auto it = map.find(oldest_sn); if (it != map.end()) { map.erase(it); } order.pop_front(); } } const std::size_t maxEntries; std::unordered_map, std::list::iterator>> map; std::list order; mutable QMutex _mutex; }; template class snSummaryCache { public: struct summary { std::string sn; std::vector values; }; explicit snSummaryCache(std::size_t summarySize) : summarySize(summarySize) { if (summarySize == 0) { throw std::invalid_argument("snSummaryCache summarySize must be greater than zero"); } } std::optional add(const std::string& sn, std::size_t index, const summaryDataTemplate& value) { if (index >= summarySize) { return std::nullopt; } QMutexLocker locker(&_mutex); auto it = map.find(sn); if (it == map.end()) { it = map.emplace(sn, entry(summarySize)).first; } entry& currentEntry = it->second; if (!currentEntry.values[index].has_value()) { ++currentEntry.filledCount; } currentEntry.values[index] = value; if (currentEntry.filledCount != summarySize) { return std::nullopt; } summary result; result.sn = sn; result.values.resize(summarySize); for (std::size_t i = 0; i < summarySize; ++i) { result.values[i] = *currentEntry.values[i]; } map.erase(it); return result; } bool remove(const std::string& sn) { QMutexLocker locker(&_mutex); return map.erase(sn) != 0; } std::size_t size() const { QMutexLocker locker(&_mutex); return map.size(); } private: struct entry { explicit entry(std::size_t summarySize) : values(summarySize) {} std::vector> values; std::size_t filledCount = 0; }; const std::size_t summarySize; std::unordered_map map; mutable QMutex _mutex; };