Loading...
Searching...
No Matches
RecentParseCache.hpp
1#pragma once
2#include <ossia/detail/hash.hpp>
3#include <ossia/detail/small_vector.hpp>
4
5#include <QDateTime>
6#include <QFileInfo>
7#include <QString>
8
9#include <algorithm>
10#include <chrono>
11#include <memory>
12#include <mutex>
13#include <string>
14#include <string_view>
15
16namespace Threedim
17{
31template <typename T>
33{
34public:
35 struct Key
36 {
37 std::string filename;
38 std::size_t size{};
39 std::size_t fingerprint{};
40 };
41
42 static Key key(std::string_view filename, std::string_view bytes)
43 {
44 constexpr std::size_t window = 64 * 1024;
45 std::size_t h = std::hash<std::string_view>{}(bytes.substr(0, window));
46 if(bytes.size() > window)
47 ossia::hash_combine(
48 h, std::hash<std::string_view>{}(bytes.substr(bytes.size() - window)));
49 const QFileInfo fi{QString::fromUtf8(filename.data(), qsizetype(filename.size()))};
50 if(fi.exists())
51 ossia::hash_combine(h, fi.lastModified().toMSecsSinceEpoch());
52 return Key{std::string{filename}, bytes.size(), h};
53 }
54
55 std::shared_ptr<const T> find(const Key& k)
56 {
57 const auto now = clock::now();
58 std::lock_guard lock{m_mutex};
59 m_entries.erase(
60 std::remove_if(
61 m_entries.begin(), m_entries.end(),
62 [&](const Entry& e) { return now - e.last_use > ttl; }),
63 m_entries.end());
64 for(auto& e : m_entries)
65 {
66 if(e.key.size == k.size && e.key.fingerprint == k.fingerprint
67 && e.key.filename == k.filename)
68 {
69 e.last_use = now;
70 return e.data;
71 }
72 }
73 return {};
74 }
75
76 void store(Key k, std::shared_ptr<const T> data)
77 {
78 std::lock_guard lock{m_mutex};
79 if(m_entries.size() >= max_entries)
80 m_entries.erase(std::min_element(
81 m_entries.begin(), m_entries.end(),
82 [](const Entry& a, const Entry& b) { return a.last_use < b.last_use; }));
83 m_entries.push_back(Entry{std::move(k), std::move(data), clock::now()});
84 }
85
86private:
87 using clock = std::chrono::steady_clock;
88 static constexpr std::size_t max_entries = 4;
89 static constexpr auto ttl = std::chrono::seconds(30);
90
91 struct Entry
92 {
93 Key key;
94 std::shared_ptr<const T> data;
95 clock::time_point last_use;
96 };
97
98 std::mutex m_mutex;
99 ossia::small_vector<Entry, max_entries> m_entries;
100};
101}
The last few parses of the files a loader port read.
Definition RecentParseCache.hpp:33
Definition RecentParseCache.hpp:36