#include #include #include #include #include #include namespace psemek::rs { namespace { auto & resources_mutex() { static std::mutex instance; return instance; } auto & resources() { static std::map instance; return instance; } auto & name_map_mutex() { static std::mutex instance; return instance; } auto & name_map() { static util::hash_map instance; return instance; } std::atomic next_id{0}; } unknown_id_error::unknown_id_error(rs::id id, util::stacktrace stacktrace) : util::exception(util::to_string("unknown resource id: ", id), std::move(stacktrace)) , id_(id) {} unknown_name_error::unknown_name_error(std::string_view name, util::stacktrace stacktrace) : util::exception(util::to_string("unknown resource name: ", name), std::move(stacktrace)) {} resource const * find(id id) { std::lock_guard lock{resources_mutex()}; auto it = resources().find(id); if (it == resources().end()) return nullptr; return &(it->second); } resource const * find(std::string_view name) { rs::id id; { std::lock_guard lock{name_map_mutex()}; auto it = name_map().find(name); if (it == name_map().end()) return nullptr; id = it->second; } return find(id); } resource const & get(id id) { auto result = find(id); if (!result) throw unknown_id_error{id}; return *result; } resource const & get(std::string_view name) { auto result = find(name); if (!result) throw unknown_name_error{name}; return *result; } id add(std::string_view name, std::string_view data) { auto id = next_id.fetch_add(1); { std::lock_guard lock{name_map_mutex()}; name_map()[name] = id; } { std::lock_guard lock{resources_mutex()}; resources()[id] = {id, name, data}; } return id; } }