File phonebook.hpp
File List > illixr > phonebook.hpp
Go to the documentation of this file
#pragma once
#include "export.hpp"
#include
#include
#include
#include
#include
#include
#include
#include
#if defined(_WIN32) || defined(_WIN64)
# include
# include
#endif
#ifndef NDEBUG
# include
// # include "spdlog/sinks/stdout_color_sinks.h"
#endif
namespace ILLIXR {
#if defined(_WIN32) || defined(_WIN64)
static void setenv(const std::string& var, const std::string& val, int) {
std::string env_stmt = var + "=" + val;
putenv(env_stmt.c_str());
}
#endif
class MY_EXPORT_API phonebook {
/*
Proof of thread-safety:
- Since all instance members are private, acquiring a lock in each method implies the class is datarace-free.
- Since there is only one lock and this does not call any code containing locks, this is deadlock-free.
- Both of these methods are only used during initialization, so the locks are not contended in steady-state.
However, to write a correct program, one must also check the thread-safety of the elements
inserted into this class by the caller.
*/
public:
class service {
public:
// auto spdlogger(const char* log_level) {
// if (!log_level) {
// #ifdef NDEBUG
// log_level = "warn";
// #else
// log_level = "debug";
// #endif
// }
// std::vector sinks;
// // auto file_sink = std::make_shared("logs/" +
// type_index.name() + ".log"); auto console_sink =
// std::make_shared();
// // sinks.push_back(file_sink);
// sinks.push_back(console_sink);
// plugin_logger = std::make_shared(type_index.name(), begin(sinks), end(sinks));
// plugin_logger->set_level(spdlog::level::from_str(log_level));
// spdlog::register_logger(plugin_logger);
// return plugin_logger;
// }
// void spd_add_file_sink(const std::string& file_name, const std::string& extension, const std::string& log_level) {
// if (!plugin_logger) {
// throw std::runtime_error("Logger not found");
// }
// auto file_sink = std::make_shared("logs/" + file_name + "." + extension, true);
// file_sink->set_level(spdlog::level::from_str(log_level));
// plugin_logger->sinks().push_back(file_sink);
// size_t sink_count = plugin_logger->sinks().size();
// plugin_logger->sinks()[sink_count-1]->set_pattern("%v");
// }
virtual ~service() = default;
// std::shared_ptr plugin_logger;
};
template<typename Specific_service>
void register_impl(std::shared_ptr<Specific_service> impl) {
const std::unique_lock<std::shared_mutex> lock{mutex_};
const std::type_index type_index = std::type_index(typeid(Specific_service));
#ifndef NDEBUG
spdlog::get("illixr")->debug("[phonebook] Register {}", type_index.name());
#endif
assert(registry_.count(type_index.name()) == 0);
registry_.try_emplace(type_index.name(), impl);
}
template<typename Specific_service>
std::shared_ptr<Specific_service> lookup_impl() const {
const std::shared_lock<std::shared_mutex> lock{mutex_};
const std::type_index type_index = std::type_index(typeid(Specific_service));
#ifndef NDEBUG
// if this fails, and there are no duplicate base classes, ensure the hash_code's are unique.
if (registry_.count(type_index.name()) != 1) {
throw std::runtime_error{"Attempted to lookup an unregistered implementation " + std::string{type_index.name()}};
}
#endif
std::shared_ptr<service> this_service = registry_.at(type_index.name());
if (!static_cast<bool>(this_service))
throw std::runtime_error{"Could not find " + std::string{type_index.name()}};
std::shared_ptr<Specific_service> this_specific_service = std::dynamic_pointer_cast<Specific_service>(this_service);
if (!static_cast<bool>(this_service) || this_specific_service == nullptr)
throw std::runtime_error{"Could not find specific " + std::string{type_index.name()}};
return this_specific_service;
}
template<typename specific_service>
[[maybe_unused]] bool has_impl() const {
const std::shared_lock<std::shared_mutex> lock{mutex_};
const std::type_index type_index = std::type_index(typeid(specific_service));
return registry_.count(type_index.name()) == 1;
}
size_t get_next_id() {
size_t val = current_id_;
current_id_++;
return val;
}
private:
std::unordered_map<std::string, const std::shared_ptr<service>> registry_;
mutable std::shared_mutex mutex_;
size_t current_id_ = 0;
};
} // namespace ILLIXR