make replays useful on BB

This commit is contained in:
Martin Michelsen
2022-07-07 23:46:50 -07:00
parent 58f0501010
commit e5227080b8
18 changed files with 382 additions and 89 deletions
+73 -7
View File
@@ -5,6 +5,8 @@
#include <unordered_map>
#include <functional>
#include <phosg/Time.hh>
using namespace std;
@@ -26,21 +28,85 @@ private:
};
public:
FileContentsCache() = default;
explicit FileContentsCache(uint64_t ttl_usecs);
FileContentsCache(const FileContentsCache&) = delete;
FileContentsCache(FileContentsCache&&) = delete;
FileContentsCache& operator=(const FileContentsCache&) = delete;
FileContentsCache& operator=(FileContentsCache&&) = delete;
~FileContentsCache() = default;
std::shared_ptr<const std::string> get(const std::string& name);
std::shared_ptr<const std::string> get(const char* name);
template <typename NameT>
bool delete_key(NameT key) {
return this->name_to_file.erase(key);
}
std::shared_ptr<const std::string> get(
const std::string& name, std::function<std::string()> generate);
std::shared_ptr<const std::string> get(
const char* name, std::function<std::string()> generate);
std::shared_ptr<const std::string> replace(
const std::string& name, std::string&& data, uint64_t t = 0);
std::shared_ptr<const std::string> replace(
const std::string& name, const void* data, size_t size, uint64_t t = 0);
struct GetResult {
std::shared_ptr<const std::string> data;
bool generate_called;
};
GetResult get_or_load(const std::string& name);
GetResult get_or_load(const char* name);
std::shared_ptr<const string> get_or_throw(const std::string& name);
std::shared_ptr<const string> get_or_throw(const char* name);
GetResult get(
const std::string& name, std::function<std::string(const std::string&)> generate);
GetResult get(
const char* name, std::function<std::string(const std::string&)> generate);
template <typename T>
struct GetObjResult {
const T& obj;
std::shared_ptr<const std::string> data;
bool generate_called;
};
template <typename T, typename NameT>
GetObjResult<T> get_obj_or_load(NameT name) {
auto res = this->get_or_load(name);
if (res.data->size() != sizeof(T)) {
throw runtime_error("cached string size is incorrect");
}
return {*reinterpret_cast<const T*>(res.data->data()), res.data, res.generate_called};
}
template <typename T, typename NameT>
GetObjResult<T> get_obj_or_throw(NameT name) {
auto res = this->get_or_throw(name);
if (res->size() != sizeof(T)) {
throw runtime_error("cached string size is incorrect");
}
return {*reinterpret_cast<const T*>(res.data->data()), res.data, res.generate_called};
}
template <typename T, typename NameT>
GetObjResult<T> get_obj(NameT name, std::function<T(const std::string&)> generate) {
uint64_t t = now();
try {
auto& entry = this->name_to_file.at(name);
if (entry.contents->size() != sizeof(T)) {
throw runtime_error("cached string size is incorrect");
}
if (this->ttl_usecs && (t - entry.load_time < this->ttl_usecs)) {
return {*reinterpret_cast<const T*>(entry.contents->data()), entry.contents, false};
}
} catch (const out_of_range& e) { }
T value = generate(name);
auto ret = this->replace_obj(name, value);
ret.generate_called = true;
return ret;
}
template <typename T, typename NameT>
GetObjResult<T> replace_obj(NameT name, const T& value) {
auto cached_value = this->replace(name, &value, sizeof(value));
return {*reinterpret_cast<const T*>(cached_value->data()), cached_value, false};
}
private:
std::unordered_map<std::string, File> name_to_file;
uint64_t ttl_usecs;
};